win32api/user32.go

688 lines
18 KiB
Go
Raw Normal View History

2020-10-19 21:14:49 +08:00
package win32api
import (
"errors"
"syscall"
2024-03-26 11:10:26 +08:00
"unsafe"
2020-10-19 21:14:49 +08:00
)
func Keybd_event(keyname string, keydown bool) error {
var key int
var down uintptr
if !keydown {
down = KEYEVENTF_KEYUP
}
switch keyname {
case "shift":
key = VK_SHIFT
case "lshift":
key = VK_LSHIFT
case "rshift":
key = VK_RSHIFT
case "a":
key = VK_A
}
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
keyevent, err := syscall.GetProcAddress(syscall.Handle(user32), "keybd_event")
if err != nil {
return errors.New("Can't Load Keybd_event API")
}
syscall.Syscall6(keyevent, 4, uintptr(key), uintptr(key), down, 0, 0, 0)
return nil
}
func Keybd_event_origin(key, keyenv, down, extra uintptr) error {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
keyevent, err := syscall.GetProcAddress(syscall.Handle(user32), "keybd_event")
if err != nil {
return errors.New("Can't Load Keybd_event API")
}
syscall.Syscall6(keyevent, 4, key, keyenv, down, extra, 0, 0)
return nil
}
2024-03-26 11:10:26 +08:00
func OpenClipboard(hWnd HWND) error {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
oc, err := syscall.GetProcAddress(syscall.Handle(user32), "OpenClipboard")
if err != nil {
return errors.New("Can't Load OpenClipboard API")
}
if hWnd != 0 {
if r, _, errno := syscall.Syscall(oc, 1, uintptr(hWnd), 0, 0); r == 0 {
return error(errno)
}
return nil
}
if r, _, errno := syscall.Syscall(oc, 1, 0, 0, 0); r == 0 {
2024-03-26 11:10:26 +08:00
return error(errno)
}
return nil
}
func CloseClipboard() error {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
cc, err := syscall.GetProcAddress(syscall.Handle(user32), "CloseClipboard")
if err != nil {
return errors.New("Can't Load CloseClipboard API")
}
if r, _, errno := syscall.Syscall(cc, 0, 0, 0, 0); r == 0 {
return error(errno)
}
return nil
}
func GetClipboardData(uFormat DWORD) (HGLOBAL, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
gcd, err := syscall.GetProcAddress(syscall.Handle(user32), "GetClipboardData")
if err != nil {
return 0, errors.New("Can't Load GetClipboardData API")
}
r, _, errno := syscall.Syscall(gcd, 1, uintptr(uFormat), 0, 0)
if r == 0 {
return 0, error(errno)
}
return HGLOBAL(r), nil
}
func EnumClipboardFormats(uFormat DWORD) (DWORD, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
ecf, err := syscall.GetProcAddress(syscall.Handle(user32), "EnumClipboardFormats")
if err != nil {
return 0, errors.New("Can't Load EnumClipboardFormats API")
}
r, _, errno := syscall.Syscall(ecf, 1, uintptr(uFormat), 0, 0)
if r == 0 {
if errno == 0 {
return 0, nil
}
2024-03-26 11:10:26 +08:00
return 0, error(errno)
}
return DWORD(r), nil
}
func EnumAllClipboardFormats() ([]DWORD, error) {
var formats []DWORD
var current DWORD
for {
format, err := EnumClipboardFormats(current)
2024-03-26 11:10:26 +08:00
if err != nil {
return nil, err
}
if format == 0 {
2024-03-26 11:10:26 +08:00
break
}
formats = append(formats, format)
current = format
2024-03-26 11:10:26 +08:00
}
return formats, nil
}
func GetClipboardFormatName(uFormat DWORD) (string, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return "", errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
gcfn, err := syscall.GetProcAddress(syscall.Handle(user32), "GetClipboardFormatNameW")
if err != nil {
return "", errors.New("Can't Load GetClipboardFormatName API")
}
var buffer [256]uint16
r, _, errno := syscall.Syscall6(gcfn, 3, uintptr(uFormat), uintptr(unsafe.Pointer(&buffer)), uintptr(len(buffer)), 0, 0, 0)
if r == 0 {
return "", error(errno)
}
return syscall.UTF16ToString(buffer[:]), nil
}
func RegisterClipboardFormat(lpszFormat string) DWORD {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0
}
defer syscall.FreeLibrary(user32)
rcf, err := syscall.GetProcAddress(syscall.Handle(user32), "RegisterClipboardFormatW")
if err != nil {
return 0
}
r, _, _ := syscall.Syscall(rcf, 1, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpszFormat))), 0, 0)
return DWORD(r)
}
2024-03-26 13:49:52 +08:00
func EmptyClipboard() error {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
ec, err := syscall.GetProcAddress(syscall.Handle(user32), "EmptyClipboard")
if err != nil {
return errors.New("Can't Load EmptyClipboard API")
}
if r, _, errno := syscall.Syscall(ec, 0, 0, 0, 0); r == 0 {
return error(errno)
}
return nil
}
func CountClipboardFormats() (int, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
ccf, err := syscall.GetProcAddress(syscall.Handle(user32), "CountClipboardFormats")
if err != nil {
return 0, errors.New("Can't Load CountClipboardFormats API")
}
r, _, errno := syscall.Syscall(ccf, 0, 0, 0, 0)
if r == 0 {
if errno == 0 {
return 0, nil
}
2024-03-26 13:49:52 +08:00
return 0, error(errno)
}
return int(r), nil
}
func GetClipboardOwner() (HWND, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
gco, err := syscall.GetProcAddress(syscall.Handle(user32), "GetClipboardOwner")
if err != nil {
return 0, errors.New("Can't Load GetClipboardOwner API")
}
r, _, errno := syscall.Syscall(gco, 0, 0, 0, 0)
if r == 0 {
if errno == 0 {
return 0, nil
}
2024-03-26 13:49:52 +08:00
return 0, error(errno)
}
return HWND(r), nil
}
2024-03-26 16:07:49 +08:00
func GetUpdatedClipboardFormats(lpuiFormats unsafe.Pointer, cFormats int, pcFormats unsafe.Pointer) (int, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
2024-03-26 13:49:52 +08:00
}
2024-03-26 16:07:49 +08:00
defer syscall.FreeLibrary(user32)
gucf, err := syscall.GetProcAddress(syscall.Handle(user32), "GetUpdatedClipboardFormats")
if err != nil {
return 0, errors.New("Can't Load GetUpdatedClipboardFormats API")
}
r, _, errno := syscall.Syscall(gucf, 3, uintptr(lpuiFormats), uintptr(cFormats), uintptr(pcFormats))
if r == 0 {
return 0, error(errno)
}
return int(r), nil
}
type updatedClipboardFormatsFunc func(lpuiFormats unsafe.Pointer, cFormats int, pcFormats unsafe.Pointer) (int, error)
func getUpdatedClipboardFormatsAll(fetch updatedClipboardFormatsFunc) ([]DWORD, error) {
if fetch == nil {
fetch = GetUpdatedClipboardFormats
}
for size := 32; ; {
formats := make([]uint32, size)
var count uint32
_, err := fetch(unsafe.Pointer(&formats[0]), len(formats), unsafe.Pointer(&count))
if err != nil {
if errors.Is(err, syscall.ERROR_INSUFFICIENT_BUFFER) {
nextSize := size * 2
if count > uint32(size) {
nextSize = int(count)
}
size = nextSize
continue
}
return nil, err
}
if count > uint32(len(formats)) {
size = int(count)
continue
}
res := make([]DWORD, 0, int(count))
for i := 0; i < int(count); i++ {
res = append(res, DWORD(formats[i]))
}
return res, nil
2024-03-26 16:07:49 +08:00
}
}
func GetUpdatedClipboardFormatsAll() ([]DWORD, error) {
return getUpdatedClipboardFormatsAll(GetUpdatedClipboardFormats)
2024-03-26 13:49:52 +08:00
}
func IsClipboardFormatAvailable(uFormat DWORD) (bool, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return false, err
}
defer syscall.FreeLibrary(user32)
icfa, err := syscall.GetProcAddress(syscall.Handle(user32), "IsClipboardFormatAvailable")
if err != nil {
return false, err
}
r, _, _ := syscall.Syscall(icfa, 1, uintptr(uFormat), 0, 0)
return r != 0, nil
}
func AddClipboardFormatListener(hWnd HWND) (bool, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return false, err
}
defer syscall.FreeLibrary(user32)
acfl, err := syscall.GetProcAddress(syscall.Handle(user32), "AddClipboardFormatListener")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall(acfl, 1, uintptr(hWnd), 0, 0)
if r == 0 {
if errno != 0 {
return false, error(errno)
}
return false, syscall.EINVAL
}
return true, nil
2024-03-26 13:49:52 +08:00
}
func RemoveClipboardFormatListener(hWnd HWND) (bool, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return false, err
}
defer syscall.FreeLibrary(user32)
rcfl, err := syscall.GetProcAddress(syscall.Handle(user32), "RemoveClipboardFormatListener")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall(rcfl, 1, uintptr(hWnd), 0, 0)
if r == 0 {
if errno != 0 {
return false, error(errno)
}
return false, syscall.EINVAL
}
return true, nil
2024-03-26 13:49:52 +08:00
}
func SetClipboardData(uFormat DWORD, hMem HGLOBAL) (HGLOBAL, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
scd, err := syscall.GetProcAddress(syscall.Handle(user32), "SetClipboardData")
if err != nil {
return 0, errors.New("Can't Load SetClipboardData API")
}
r, _, errno := syscall.Syscall(scd, 2, uintptr(uFormat), uintptr(hMem), 0)
if r == 0 {
return 0, error(errno)
}
return HGLOBAL(r), nil
}
func SetClipboardViewer(hWndNewViewer HWND) (HWND, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
scv, err := syscall.GetProcAddress(syscall.Handle(user32), "SetClipboardViewer")
if err != nil {
return 0, errors.New("Can't Load SetClipboardViewer API")
}
r, _, errno := syscall.Syscall(scv, 1, uintptr(hWndNewViewer), 0, 0)
if r == 0 {
if errno == 0 {
return 0, nil
}
2024-03-26 13:49:52 +08:00
return 0, error(errno)
}
return HWND(r), nil
}
2024-03-27 14:19:52 +08:00
2024-03-30 15:06:00 +08:00
func GetClipboardSequenceNumber() (DWORD, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
gcsn, err := syscall.GetProcAddress(syscall.Handle(user32), "GetClipboardSequenceNumber")
if err != nil {
return 0, errors.New("Can't Load GetClipboardSequenceNumber API")
}
r, _, errno := syscall.Syscall(gcsn, 0, 0, 0, 0)
if r == 0 {
return 0, error(errno)
}
return DWORD(r), nil
}
2024-03-27 14:19:52 +08:00
func CreateWindowEx(dwExStyle DWORD, lpClassName, lpWindowName string, dwStyle DWORD, x, y, nWidth, nHeight int, hWndParent HWND, hMenu HMENU, hInstance HINSTANCE, lpParam unsafe.Pointer) (HWND, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
cwe, err := syscall.GetProcAddress(syscall.Handle(user32), "CreateWindowExW")
if err != nil {
return 0, errors.New("Can't Load CreateWindowEx API")
}
r, _, errno := syscall.Syscall12(cwe, 12, uintptr(dwExStyle), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpClassName))), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpWindowName))), uintptr(dwStyle), uintptr(x), uintptr(y), uintptr(nWidth), uintptr(nHeight), uintptr(hWndParent), uintptr(hMenu), uintptr(hInstance), uintptr(lpParam))
2024-03-27 14:19:52 +08:00
if r == 0 {
return 0, error(errno)
}
return HWND(r), nil
}
2025-11-07 22:37:37 +08:00
func DestroyWindow(hWnd HWND) (bool, error) {
2024-03-28 09:09:43 +08:00
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return false, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
dw, err := syscall.GetProcAddress(syscall.Handle(user32), "DestroyWindow")
if err != nil {
return false, errors.New("Can't Load DestroyWindow API")
}
r, _, errno := syscall.Syscall(dw, 1, uintptr(hWnd), 0, 0)
if r == 0 {
if errno != 0 {
return false, error(errno)
}
return false, syscall.EINVAL
}
return true, nil
2024-03-28 09:09:43 +08:00
}
2024-03-27 14:19:52 +08:00
func GetMessage(lpMsg *MSG, hWnd HWND, wMsgFilterMin, wMsgFilterMax DWORD) (DWORD, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, errors.New("Can't Load User32 API")
}
defer syscall.FreeLibrary(user32)
gm, err := syscall.GetProcAddress(syscall.Handle(user32), "GetMessageW")
if err != nil {
return 0, errors.New("Can't Load GetMessage API")
}
r, _, errno := syscall.Syscall6(gm, 4, uintptr(unsafe.Pointer(lpMsg)), uintptr(hWnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), 0, 0)
if int32(r) == -1 {
2024-03-27 14:19:52 +08:00
return 0, error(errno)
}
return DWORD(r), nil
}
2025-11-07 22:37:37 +08:00
func TranslateMessage(lpMsg *MSG) (bool, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return false, err
}
defer syscall.FreeLibrary(user32)
proc, err := syscall.GetProcAddress(syscall.Handle(user32), "TranslateMessage")
if err != nil {
return false, err
}
r, _, _ := syscall.Syscall(proc, 1, uintptr(unsafe.Pointer(lpMsg)), 0, 0)
return r != 0, nil
}
func DispatchMessage(lpMsg *MSG) (LRESULT, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, err
}
defer syscall.FreeLibrary(user32)
proc, err := syscall.GetProcAddress(syscall.Handle(user32), "DispatchMessageW")
if err != nil {
return 0, err
}
r, _, _ := syscall.Syscall(proc, 1, uintptr(unsafe.Pointer(lpMsg)), 0, 0)
return LRESULT(r), nil
2025-11-07 22:37:37 +08:00
}
func DefWindowProc(hWnd HWND, uMsg UINT, wParam WPARAM, lParam LPARAM) LRESULT {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0
}
defer syscall.FreeLibrary(user32)
proc, err := syscall.GetProcAddress(syscall.Handle(user32), "DefWindowProcW")
if err != nil {
return 0
}
r, _, _ := syscall.Syscall6(proc, 4, uintptr(hWnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0)
return LRESULT(r)
}
func PostMessage(hWnd HWND, msg UINT, wParam WPARAM, lParam LPARAM) (bool, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return false, err
}
defer syscall.FreeLibrary(user32)
proc, err := syscall.GetProcAddress(syscall.Handle(user32), "PostMessageW")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall6(proc, 4, uintptr(hWnd), uintptr(msg), uintptr(wParam), uintptr(lParam), 0, 0)
if r == 0 {
if errno != 0 {
return false, error(errno)
}
return false, syscall.EINVAL
}
return true, nil
2025-11-07 22:37:37 +08:00
}
func PostQuitMessage(nExitCode int) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return
}
defer syscall.FreeLibrary(user32)
proc, err := syscall.GetProcAddress(syscall.Handle(user32), "PostQuitMessage")
if err != nil {
return
}
syscall.Syscall(proc, 1, uintptr(nExitCode), 0, 0)
}
func RegisterClassEx(lpWndClass *WNDCLASSEX) (uint16, error) {
user32, err := syscall.LoadLibrary("user32.dll")
if err != nil {
return 0, err
}
defer syscall.FreeLibrary(user32)
proc, err := syscall.GetProcAddress(syscall.Handle(user32), "RegisterClassExW")
if err != nil {
return 0, err
}
r, _, err := syscall.Syscall(proc, 1, uintptr(unsafe.Pointer(lpWndClass)), 0, 0)
if r == 0 {
return 0, err
}
return uint16(r), nil
}
func OpenInputDesktop(dwFlags DWORD, fInherit bool, dwDesiredAccess DWORD) (HDESK, error) {
proc, err := getProcAddr("user32.dll", "OpenInputDesktop")
if err != nil {
return 0, err
}
inherit := uintptr(0)
if fInherit {
inherit = 1
}
r, _, errno := syscall.Syscall(proc, 3, uintptr(dwFlags), inherit, uintptr(dwDesiredAccess))
if r == 0 {
if errno != 0 {
return 0, error(errno)
}
return 0, syscall.EINVAL
}
return HDESK(r), nil
}
func CloseDesktop(hDesktop HDESK) error {
proc, err := getProcAddr("user32.dll", "CloseDesktop")
if err != nil {
return err
}
r, _, errno := syscall.Syscall(proc, 1, uintptr(hDesktop), 0, 0)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func SwitchDesktop(hDesktop HDESK) error {
proc, err := getProcAddr("user32.dll", "SwitchDesktop")
if err != nil {
return err
}
r, _, errno := syscall.Syscall(proc, 1, uintptr(hDesktop), 0, 0)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func GetThreadDesktop(dwThreadId DWORD) (HDESK, error) {
proc, err := getProcAddr("user32.dll", "GetThreadDesktop")
if err != nil {
return 0, err
}
r, _, errno := syscall.Syscall(proc, 1, uintptr(dwThreadId), 0, 0)
if r == 0 {
if errno != 0 {
return 0, error(errno)
}
return 0, syscall.EINVAL
}
return HDESK(r), nil
}
func SetThreadDesktop(hDesktop HDESK) error {
proc, err := getProcAddr("user32.dll", "SetThreadDesktop")
if err != nil {
return err
}
r, _, errno := syscall.Syscall(proc, 1, uintptr(hDesktop), 0, 0)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func GetDesktopWindow() HWND {
proc, err := getProcAddr("user32.dll", "GetDesktopWindow")
if err != nil {
return 0
}
r, _, _ := syscall.Syscall(proc, 0, 0, 0, 0)
return HWND(r)
}
func GetShellWindow() HWND {
proc, err := getProcAddr("user32.dll", "GetShellWindow")
if err != nil {
return 0
}
r, _, _ := syscall.Syscall(proc, 0, 0, 0, 0)
return HWND(r)
}
func GetForegroundWindow() HWND {
proc, err := getProcAddr("user32.dll", "GetForegroundWindow")
if err != nil {
return 0
}
r, _, _ := syscall.Syscall(proc, 0, 0, 0, 0)
return HWND(r)
}
func GetWindowThreadProcessId(hWnd HWND) (DWORD, DWORD, error) {
proc, err := getProcAddr("user32.dll", "GetWindowThreadProcessId")
if err != nil {
return 0, 0, err
}
var processID DWORD
r, _, errno := syscall.Syscall(proc, 2, uintptr(hWnd), uintptr(unsafe.Pointer(&processID)), 0)
threadID := DWORD(r)
if threadID == 0 {
if errno != 0 {
return 0, processID, error(errno)
}
return 0, processID, syscall.EINVAL
}
return threadID, processID, nil
}
func GetWindowText(hWnd HWND) (string, error) {
lenProc, err := getProcAddr("user32.dll", "GetWindowTextLengthW")
if err != nil {
return "", err
}
textProc, err := getProcAddr("user32.dll", "GetWindowTextW")
if err != nil {
return "", err
}
n, _, _ := syscall.Syscall(lenProc, 1, uintptr(hWnd), 0, 0)
size := uint32(n) + 1
if size < 2 {
size = 2
}
buf := make([]uint16, size)
r, _, errno := syscall.Syscall(textProc, 3, uintptr(hWnd), uintptr(unsafe.Pointer(&buf[0])), uintptr(size))
if r == 0 {
if errno != 0 {
return "", error(errno)
}
return "", nil
}
return syscall.UTF16ToString(buf[:r]), nil
}