gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/app/internal/windows/windows.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  //go:build windows
     4  // +build windows
     5  
     6  package windows
     7  
     8  import (
     9  	"fmt"
    10  	"runtime"
    11  	"time"
    12  	"unicode/utf16"
    13  	"unsafe"
    14  
    15  	syscall "golang.org/x/sys/windows"
    16  )
    17  
    18  type CompositionForm struct {
    19  	dwStyle      uint32
    20  	ptCurrentPos Point
    21  	rcArea       Rect
    22  }
    23  
    24  type CandidateForm struct {
    25  	dwIndex      uint32
    26  	dwStyle      uint32
    27  	ptCurrentPos Point
    28  	rcArea       Rect
    29  }
    30  
    31  type Rect struct {
    32  	Left, Top, Right, Bottom int32
    33  }
    34  
    35  type WndClassEx struct {
    36  	CbSize        uint32
    37  	Style         uint32
    38  	LpfnWndProc   uintptr
    39  	CnClsExtra    int32
    40  	CbWndExtra    int32
    41  	HInstance     syscall.Handle
    42  	HIcon         syscall.Handle
    43  	HCursor       syscall.Handle
    44  	HbrBackground syscall.Handle
    45  	LpszMenuName  *uint16
    46  	LpszClassName *uint16
    47  	HIconSm       syscall.Handle
    48  }
    49  
    50  type Margins struct {
    51  	CxLeftWidth    int32
    52  	CxRightWidth   int32
    53  	CyTopHeight    int32
    54  	CyBottomHeight int32
    55  }
    56  
    57  type Msg struct {
    58  	Hwnd     syscall.Handle
    59  	Message  uint32
    60  	WParam   uintptr
    61  	LParam   uintptr
    62  	Time     uint32
    63  	Pt       Point
    64  	LPrivate uint32
    65  }
    66  
    67  type Point struct {
    68  	X, Y int32
    69  }
    70  
    71  type MinMaxInfo struct {
    72  	PtReserved     Point
    73  	PtMaxSize      Point
    74  	PtMaxPosition  Point
    75  	PtMinTrackSize Point
    76  	PtMaxTrackSize Point
    77  }
    78  
    79  type NCCalcSizeParams struct {
    80  	Rgrc  [3]Rect
    81  	LpPos *WindowPos
    82  }
    83  
    84  type WindowPos struct {
    85  	HWND            syscall.Handle
    86  	HWNDInsertAfter syscall.Handle
    87  	x               int32
    88  	y               int32
    89  	cx              int32
    90  	cy              int32
    91  	flags           uint32
    92  }
    93  
    94  type WindowPlacement struct {
    95  	length           uint32
    96  	flags            uint32
    97  	showCmd          uint32
    98  	ptMinPosition    Point
    99  	ptMaxPosition    Point
   100  	rcNormalPosition Rect
   101  	rcDevice         Rect
   102  }
   103  
   104  type MonitorInfo struct {
   105  	cbSize   uint32
   106  	Monitor  Rect
   107  	WorkArea Rect
   108  	Flags    uint32
   109  }
   110  
   111  const (
   112  	TRUE = 1
   113  
   114  	CPS_CANCEL = 0x0004
   115  
   116  	CS_HREDRAW     = 0x0002
   117  	CS_INSERTCHAR  = 0x2000
   118  	CS_NOMOVECARET = 0x4000
   119  	CS_VREDRAW     = 0x0001
   120  	CS_OWNDC       = 0x0020
   121  
   122  	CW_USEDEFAULT = -2147483648
   123  
   124  	GWL_STYLE = ^(uintptr(16) - 1) // -16
   125  
   126  	GCS_COMPSTR       = 0x0008
   127  	GCS_COMPREADSTR   = 0x0001
   128  	GCS_CURSORPOS     = 0x0080
   129  	GCS_DELTASTART    = 0x0100
   130  	GCS_RESULTREADSTR = 0x0200
   131  	GCS_RESULTSTR     = 0x0800
   132  
   133  	CFS_POINT        = 0x0002
   134  	CFS_CANDIDATEPOS = 0x0040
   135  
   136  	HWND_TOPMOST = ^(uint32(1) - 1) // -1
   137  
   138  	HTCAPTION     = 2
   139  	HTCLIENT      = 1
   140  	HTLEFT        = 10
   141  	HTRIGHT       = 11
   142  	HTTOP         = 12
   143  	HTTOPLEFT     = 13
   144  	HTTOPRIGHT    = 14
   145  	HTBOTTOM      = 15
   146  	HTBOTTOMLEFT  = 16
   147  	HTBOTTOMRIGHT = 17
   148  
   149  	IDC_APPSTARTING = 32650 // Standard arrow and small hourglass
   150  	IDC_ARROW       = 32512 // Standard arrow
   151  	IDC_CROSS       = 32515 // Crosshair
   152  	IDC_HAND        = 32649 // Hand
   153  	IDC_HELP        = 32651 // Arrow and question mark
   154  	IDC_IBEAM       = 32513 // I-beam
   155  	IDC_NO          = 32648 // Slashed circle
   156  	IDC_SIZEALL     = 32646 // Four-pointed arrow pointing north, south, east, and west
   157  	IDC_SIZENESW    = 32643 // Double-pointed arrow pointing northeast and southwest
   158  	IDC_SIZENS      = 32645 // Double-pointed arrow pointing north and south
   159  	IDC_SIZENWSE    = 32642 // Double-pointed arrow pointing northwest and southeast
   160  	IDC_SIZEWE      = 32644 // Double-pointed arrow pointing west and east
   161  	IDC_UPARROW     = 32516 // Vertical arrow
   162  	IDC_WAIT        = 32514 // Hour
   163  
   164  	INFINITE = 0xFFFFFFFF
   165  
   166  	LOGPIXELSX = 88
   167  
   168  	MDT_EFFECTIVE_DPI = 0
   169  
   170  	MONITOR_DEFAULTTOPRIMARY = 1
   171  
   172  	NI_COMPOSITIONSTR = 0x0015
   173  
   174  	SIZE_MAXIMIZED = 2
   175  	SIZE_MINIMIZED = 1
   176  	SIZE_RESTORED  = 0
   177  
   178  	SCS_SETSTR = GCS_COMPREADSTR | GCS_COMPSTR
   179  
   180  	SM_CXSIZEFRAME = 32
   181  	SM_CYSIZEFRAME = 33
   182  
   183  	SW_SHOWDEFAULT   = 10
   184  	SW_SHOWMINIMIZED = 2
   185  	SW_SHOWMAXIMIZED = 3
   186  	SW_SHOWNORMAL    = 1
   187  	SW_SHOW          = 5
   188  
   189  	SWP_FRAMECHANGED  = 0x0020
   190  	SWP_NOMOVE        = 0x0002
   191  	SWP_NOOWNERZORDER = 0x0200
   192  	SWP_NOSIZE        = 0x0001
   193  	SWP_NOZORDER      = 0x0004
   194  	SWP_SHOWWINDOW    = 0x0040
   195  
   196  	USER_TIMER_MINIMUM = 0x0000000A
   197  
   198  	VK_CONTROL = 0x11
   199  	VK_LWIN    = 0x5B
   200  	VK_MENU    = 0x12
   201  	VK_RWIN    = 0x5C
   202  	VK_SHIFT   = 0x10
   203  
   204  	VK_BACK   = 0x08
   205  	VK_DELETE = 0x2e
   206  	VK_DOWN   = 0x28
   207  	VK_END    = 0x23
   208  	VK_ESCAPE = 0x1b
   209  	VK_HOME   = 0x24
   210  	VK_LEFT   = 0x25
   211  	VK_NEXT   = 0x22
   212  	VK_PRIOR  = 0x21
   213  	VK_RIGHT  = 0x27
   214  	VK_RETURN = 0x0d
   215  	VK_SPACE  = 0x20
   216  	VK_TAB    = 0x09
   217  	VK_UP     = 0x26
   218  
   219  	VK_F1  = 0x70
   220  	VK_F2  = 0x71
   221  	VK_F3  = 0x72
   222  	VK_F4  = 0x73
   223  	VK_F5  = 0x74
   224  	VK_F6  = 0x75
   225  	VK_F7  = 0x76
   226  	VK_F8  = 0x77
   227  	VK_F9  = 0x78
   228  	VK_F10 = 0x79
   229  	VK_F11 = 0x7A
   230  	VK_F12 = 0x7B
   231  
   232  	VK_OEM_1      = 0xba
   233  	VK_OEM_PLUS   = 0xbb
   234  	VK_OEM_COMMA  = 0xbc
   235  	VK_OEM_MINUS  = 0xbd
   236  	VK_OEM_PERIOD = 0xbe
   237  	VK_OEM_2      = 0xbf
   238  	VK_OEM_3      = 0xc0
   239  	VK_OEM_4      = 0xdb
   240  	VK_OEM_5      = 0xdc
   241  	VK_OEM_6      = 0xdd
   242  	VK_OEM_7      = 0xde
   243  	VK_OEM_102    = 0xe2
   244  
   245  	UNICODE_NOCHAR = 65535
   246  
   247  	WM_CANCELMODE           = 0x001F
   248  	WM_CHAR                 = 0x0102
   249  	WM_CLOSE                = 0x0010
   250  	WM_CREATE               = 0x0001
   251  	WM_DPICHANGED           = 0x02E0
   252  	WM_DESTROY              = 0x0002
   253  	WM_ERASEBKGND           = 0x0014
   254  	WM_GETMINMAXINFO        = 0x0024
   255  	WM_IME_COMPOSITION      = 0x010F
   256  	WM_IME_ENDCOMPOSITION   = 0x010E
   257  	WM_IME_STARTCOMPOSITION = 0x010D
   258  	WM_KEYDOWN              = 0x0100
   259  	WM_KEYUP                = 0x0101
   260  	WM_KILLFOCUS            = 0x0008
   261  	WM_LBUTTONDOWN          = 0x0201
   262  	WM_LBUTTONUP            = 0x0202
   263  	WM_MBUTTONDOWN          = 0x0207
   264  	WM_MBUTTONUP            = 0x0208
   265  	WM_MOUSEMOVE            = 0x0200
   266  	WM_MOUSEWHEEL           = 0x020A
   267  	WM_MOUSEHWHEEL          = 0x020E
   268  	WM_NCACTIVATE           = 0x0086
   269  	WM_NCHITTEST            = 0x0084
   270  	WM_NCCALCSIZE           = 0x0083
   271  	WM_PAINT                = 0x000F
   272  	WM_QUIT                 = 0x0012
   273  	WM_SETCURSOR            = 0x0020
   274  	WM_SETFOCUS             = 0x0007
   275  	WM_SHOWWINDOW           = 0x0018
   276  	WM_SIZE                 = 0x0005
   277  	WM_SYSKEYDOWN           = 0x0104
   278  	WM_SYSKEYUP             = 0x0105
   279  	WM_RBUTTONDOWN          = 0x0204
   280  	WM_RBUTTONUP            = 0x0205
   281  	WM_TIMER                = 0x0113
   282  	WM_UNICHAR              = 0x0109
   283  	WM_USER                 = 0x0400
   284  	WM_WINDOWPOSCHANGED     = 0x0047
   285  
   286  	WS_CLIPCHILDREN     = 0x02000000
   287  	WS_CLIPSIBLINGS     = 0x04000000
   288  	WS_MAXIMIZE         = 0x01000000
   289  	WS_ICONIC           = 0x20000000
   290  	WS_VISIBLE          = 0x10000000
   291  	WS_OVERLAPPED       = 0x00000000
   292  	WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
   293  		WS_MINIMIZEBOX | WS_MAXIMIZEBOX
   294  	WS_CAPTION     = 0x00C00000
   295  	WS_SYSMENU     = 0x00080000
   296  	WS_THICKFRAME  = 0x00040000
   297  	WS_MINIMIZEBOX = 0x00020000
   298  	WS_MAXIMIZEBOX = 0x00010000
   299  
   300  	WS_EX_APPWINDOW  = 0x00040000
   301  	WS_EX_WINDOWEDGE = 0x00000100
   302  
   303  	QS_ALLINPUT = 0x04FF
   304  
   305  	MWMO_WAITALL        = 0x0001
   306  	MWMO_INPUTAVAILABLE = 0x0004
   307  
   308  	WAIT_OBJECT_0 = 0
   309  
   310  	PM_REMOVE   = 0x0001
   311  	PM_NOREMOVE = 0x0000
   312  
   313  	GHND = 0x0042
   314  
   315  	CF_UNICODETEXT = 13
   316  	IMAGE_BITMAP   = 0
   317  	IMAGE_ICON     = 1
   318  	IMAGE_CURSOR   = 2
   319  
   320  	LR_CREATEDIBSECTION = 0x00002000
   321  	LR_DEFAULTCOLOR     = 0x00000000
   322  	LR_DEFAULTSIZE      = 0x00000040
   323  	LR_LOADFROMFILE     = 0x00000010
   324  	LR_LOADMAP3DCOLORS  = 0x00001000
   325  	LR_LOADTRANSPARENT  = 0x00000020
   326  	LR_MONOCHROME       = 0x00000001
   327  	LR_SHARED           = 0x00008000
   328  	LR_VGACOLOR         = 0x00000080
   329  )
   330  
   331  var (
   332  	kernel32          = syscall.NewLazySystemDLL("kernel32.dll")
   333  	_GetModuleHandleW = kernel32.NewProc("GetModuleHandleW")
   334  	_GlobalAlloc      = kernel32.NewProc("GlobalAlloc")
   335  	_GlobalFree       = kernel32.NewProc("GlobalFree")
   336  	_GlobalLock       = kernel32.NewProc("GlobalLock")
   337  	_GlobalUnlock     = kernel32.NewProc("GlobalUnlock")
   338  
   339  	user32                       = syscall.NewLazySystemDLL("user32.dll")
   340  	_AdjustWindowRectEx          = user32.NewProc("AdjustWindowRectEx")
   341  	_CallMsgFilter               = user32.NewProc("CallMsgFilterW")
   342  	_CloseClipboard              = user32.NewProc("CloseClipboard")
   343  	_CreateWindowEx              = user32.NewProc("CreateWindowExW")
   344  	_DefWindowProc               = user32.NewProc("DefWindowProcW")
   345  	_DestroyWindow               = user32.NewProc("DestroyWindow")
   346  	_DispatchMessage             = user32.NewProc("DispatchMessageW")
   347  	_EmptyClipboard              = user32.NewProc("EmptyClipboard")
   348  	_GetWindowRect               = user32.NewProc("GetWindowRect")
   349  	_GetClientRect               = user32.NewProc("GetClientRect")
   350  	_GetClipboardData            = user32.NewProc("GetClipboardData")
   351  	_GetDC                       = user32.NewProc("GetDC")
   352  	_GetDpiForWindow             = user32.NewProc("GetDpiForWindow")
   353  	_GetKeyState                 = user32.NewProc("GetKeyState")
   354  	_GetMessage                  = user32.NewProc("GetMessageW")
   355  	_GetMessageTime              = user32.NewProc("GetMessageTime")
   356  	_GetMonitorInfo              = user32.NewProc("GetMonitorInfoW")
   357  	_GetSystemMetrics            = user32.NewProc("GetSystemMetrics")
   358  	_GetWindowLong               = user32.NewProc("GetWindowLongPtrW")
   359  	_GetWindowLong32             = user32.NewProc("GetWindowLongW")
   360  	_GetWindowPlacement          = user32.NewProc("GetWindowPlacement")
   361  	_KillTimer                   = user32.NewProc("KillTimer")
   362  	_LoadCursor                  = user32.NewProc("LoadCursorW")
   363  	_LoadImage                   = user32.NewProc("LoadImageW")
   364  	_MonitorFromPoint            = user32.NewProc("MonitorFromPoint")
   365  	_MonitorFromWindow           = user32.NewProc("MonitorFromWindow")
   366  	_MoveWindow                  = user32.NewProc("MoveWindow")
   367  	_MsgWaitForMultipleObjectsEx = user32.NewProc("MsgWaitForMultipleObjectsEx")
   368  	_OpenClipboard               = user32.NewProc("OpenClipboard")
   369  	_PeekMessage                 = user32.NewProc("PeekMessageW")
   370  	_PostMessage                 = user32.NewProc("PostMessageW")
   371  	_PostQuitMessage             = user32.NewProc("PostQuitMessage")
   372  	_ReleaseCapture              = user32.NewProc("ReleaseCapture")
   373  	_RegisterClassExW            = user32.NewProc("RegisterClassExW")
   374  	_ReleaseDC                   = user32.NewProc("ReleaseDC")
   375  	_ScreenToClient              = user32.NewProc("ScreenToClient")
   376  	_ShowWindow                  = user32.NewProc("ShowWindow")
   377  	_SetCapture                  = user32.NewProc("SetCapture")
   378  	_SetCursor                   = user32.NewProc("SetCursor")
   379  	_SetClipboardData            = user32.NewProc("SetClipboardData")
   380  	_SetForegroundWindow         = user32.NewProc("SetForegroundWindow")
   381  	_SetFocus                    = user32.NewProc("SetFocus")
   382  	_SetProcessDPIAware          = user32.NewProc("SetProcessDPIAware")
   383  	_SetTimer                    = user32.NewProc("SetTimer")
   384  	_SetWindowLong               = user32.NewProc("SetWindowLongPtrW")
   385  	_SetWindowLong32             = user32.NewProc("SetWindowLongW")
   386  	_SetWindowPlacement          = user32.NewProc("SetWindowPlacement")
   387  	_SetWindowPos                = user32.NewProc("SetWindowPos")
   388  	_SetWindowText               = user32.NewProc("SetWindowTextW")
   389  	_TranslateMessage            = user32.NewProc("TranslateMessage")
   390  	_UnregisterClass             = user32.NewProc("UnregisterClassW")
   391  	_UpdateWindow                = user32.NewProc("UpdateWindow")
   392  
   393  	shcore            = syscall.NewLazySystemDLL("shcore")
   394  	_GetDpiForMonitor = shcore.NewProc("GetDpiForMonitor")
   395  
   396  	gdi32          = syscall.NewLazySystemDLL("gdi32")
   397  	_GetDeviceCaps = gdi32.NewProc("GetDeviceCaps")
   398  
   399  	imm32                    = syscall.NewLazySystemDLL("imm32")
   400  	_ImmGetContext           = imm32.NewProc("ImmGetContext")
   401  	_ImmGetCompositionString = imm32.NewProc("ImmGetCompositionStringW")
   402  	_ImmNotifyIME            = imm32.NewProc("ImmNotifyIME")
   403  	_ImmReleaseContext       = imm32.NewProc("ImmReleaseContext")
   404  	_ImmSetCandidateWindow   = imm32.NewProc("ImmSetCandidateWindow")
   405  	_ImmSetCompositionWindow = imm32.NewProc("ImmSetCompositionWindow")
   406  
   407  	dwmapi                        = syscall.NewLazySystemDLL("dwmapi")
   408  	_DwmExtendFrameIntoClientArea = dwmapi.NewProc("DwmExtendFrameIntoClientArea")
   409  )
   410  
   411  func AdjustWindowRectEx(r *Rect, dwStyle uint32, bMenu int, dwExStyle uint32) {
   412  	_AdjustWindowRectEx.Call(uintptr(unsafe.Pointer(r)), uintptr(dwStyle), uintptr(bMenu), uintptr(dwExStyle))
   413  }
   414  
   415  func CallMsgFilter(m *Msg, nCode uintptr) bool {
   416  	r, _, _ := _CallMsgFilter.Call(uintptr(unsafe.Pointer(m)), nCode)
   417  	return r != 0
   418  }
   419  
   420  func CloseClipboard() error {
   421  	r, _, err := _CloseClipboard.Call()
   422  	if r == 0 {
   423  		return fmt.Errorf("CloseClipboard: %v", err)
   424  	}
   425  	return nil
   426  }
   427  
   428  func CreateWindowEx(dwExStyle uint32, lpClassName uint16, lpWindowName string, dwStyle uint32, x, y, w, h int32, hWndParent, hMenu, hInstance syscall.Handle, lpParam uintptr) (syscall.Handle, error) {
   429  	wname := syscall.StringToUTF16Ptr(lpWindowName)
   430  	hwnd, _, err := _CreateWindowEx.Call(
   431  		uintptr(dwExStyle),
   432  		uintptr(lpClassName),
   433  		uintptr(unsafe.Pointer(wname)),
   434  		uintptr(dwStyle),
   435  		uintptr(x), uintptr(y),
   436  		uintptr(w), uintptr(h),
   437  		uintptr(hWndParent),
   438  		uintptr(hMenu),
   439  		uintptr(hInstance),
   440  		uintptr(lpParam))
   441  	if hwnd == 0 {
   442  		return 0, fmt.Errorf("CreateWindowEx failed: %v", err)
   443  	}
   444  	return syscall.Handle(hwnd), nil
   445  }
   446  
   447  func DefWindowProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) uintptr {
   448  	r, _, _ := _DefWindowProc.Call(uintptr(hwnd), uintptr(msg), wparam, lparam)
   449  	return r
   450  }
   451  
   452  func DestroyWindow(hwnd syscall.Handle) {
   453  	_DestroyWindow.Call(uintptr(hwnd))
   454  }
   455  
   456  func DispatchMessage(m *Msg) {
   457  	_DispatchMessage.Call(uintptr(unsafe.Pointer(m)))
   458  }
   459  
   460  func DwmExtendFrameIntoClientArea(hwnd syscall.Handle, margins Margins) error {
   461  	r, _, _ := _DwmExtendFrameIntoClientArea.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&margins)))
   462  	if r != 0 {
   463  		return fmt.Errorf("DwmExtendFrameIntoClientArea: %#x", r)
   464  	}
   465  	return nil
   466  }
   467  
   468  func EmptyClipboard() error {
   469  	r, _, err := _EmptyClipboard.Call()
   470  	if r == 0 {
   471  		return fmt.Errorf("EmptyClipboard: %v", err)
   472  	}
   473  	return nil
   474  }
   475  
   476  func GetWindowRect(hwnd syscall.Handle) Rect {
   477  	var r Rect
   478  	_GetWindowRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&r)))
   479  	return r
   480  }
   481  
   482  func GetClientRect(hwnd syscall.Handle) Rect {
   483  	var r Rect
   484  	_GetClientRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&r)))
   485  	return r
   486  }
   487  
   488  func GetClipboardData(format uint32) (syscall.Handle, error) {
   489  	r, _, err := _GetClipboardData.Call(uintptr(format))
   490  	if r == 0 {
   491  		return 0, fmt.Errorf("GetClipboardData: %v", err)
   492  	}
   493  	return syscall.Handle(r), nil
   494  }
   495  
   496  func GetDC(hwnd syscall.Handle) (syscall.Handle, error) {
   497  	hdc, _, err := _GetDC.Call(uintptr(hwnd))
   498  	if hdc == 0 {
   499  		return 0, fmt.Errorf("GetDC failed: %v", err)
   500  	}
   501  	return syscall.Handle(hdc), nil
   502  }
   503  
   504  func GetModuleHandle() (syscall.Handle, error) {
   505  	h, _, err := _GetModuleHandleW.Call(uintptr(0))
   506  	if h == 0 {
   507  		return 0, fmt.Errorf("GetModuleHandleW failed: %v", err)
   508  	}
   509  	return syscall.Handle(h), nil
   510  }
   511  
   512  func getDeviceCaps(hdc syscall.Handle, index int32) int {
   513  	c, _, _ := _GetDeviceCaps.Call(uintptr(hdc), uintptr(index))
   514  	return int(c)
   515  }
   516  
   517  func getDpiForMonitor(hmonitor syscall.Handle, dpiType uint32) int {
   518  	var dpiX, dpiY uintptr
   519  	_GetDpiForMonitor.Call(uintptr(hmonitor), uintptr(dpiType), uintptr(unsafe.Pointer(&dpiX)), uintptr(unsafe.Pointer(&dpiY)))
   520  	return int(dpiX)
   521  }
   522  
   523  // GetSystemDPI returns the effective DPI of the system.
   524  func GetSystemDPI() int {
   525  	// Check for GetDpiForMonitor, introduced in Windows 8.1.
   526  	if _GetDpiForMonitor.Find() == nil {
   527  		hmon := monitorFromPoint(Point{}, MONITOR_DEFAULTTOPRIMARY)
   528  		return getDpiForMonitor(hmon, MDT_EFFECTIVE_DPI)
   529  	} else {
   530  		// Fall back to the physical device DPI.
   531  		screenDC, err := GetDC(0)
   532  		if err != nil {
   533  			return 96
   534  		}
   535  		defer ReleaseDC(screenDC)
   536  		return getDeviceCaps(screenDC, LOGPIXELSX)
   537  	}
   538  }
   539  
   540  func GetKeyState(nVirtKey int32) int16 {
   541  	c, _, _ := _GetKeyState.Call(uintptr(nVirtKey))
   542  	return int16(c)
   543  }
   544  
   545  func GetMessage(m *Msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax uint32) int32 {
   546  	r, _, _ := _GetMessage.Call(uintptr(unsafe.Pointer(m)),
   547  		uintptr(hwnd),
   548  		uintptr(wMsgFilterMin),
   549  		uintptr(wMsgFilterMax))
   550  	return int32(r)
   551  }
   552  
   553  func GetMessageTime() time.Duration {
   554  	r, _, _ := _GetMessageTime.Call()
   555  	return time.Duration(r) * time.Millisecond
   556  }
   557  
   558  func GetSystemMetrics(nIndex int) int {
   559  	r, _, _ := _GetSystemMetrics.Call(uintptr(nIndex))
   560  	return int(r)
   561  }
   562  
   563  // GetWindowDPI returns the effective DPI of the window.
   564  func GetWindowDPI(hwnd syscall.Handle) int {
   565  	// Check for GetDpiForWindow, introduced in Windows 10.
   566  	if _GetDpiForWindow.Find() == nil {
   567  		dpi, _, _ := _GetDpiForWindow.Call(uintptr(hwnd))
   568  		return int(dpi)
   569  	} else {
   570  		return GetSystemDPI()
   571  	}
   572  }
   573  
   574  func GetWindowPlacement(hwnd syscall.Handle) *WindowPlacement {
   575  	var wp WindowPlacement
   576  	wp.length = uint32(unsafe.Sizeof(wp))
   577  	_GetWindowPlacement.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&wp)))
   578  	return &wp
   579  }
   580  
   581  func GetMonitorInfo(hwnd syscall.Handle) MonitorInfo {
   582  	var mi MonitorInfo
   583  	mi.cbSize = uint32(unsafe.Sizeof(mi))
   584  	v, _, _ := _MonitorFromWindow.Call(uintptr(hwnd), MONITOR_DEFAULTTOPRIMARY)
   585  	_GetMonitorInfo.Call(v, uintptr(unsafe.Pointer(&mi)))
   586  	return mi
   587  }
   588  
   589  func GetWindowLong(hwnd syscall.Handle, index uintptr) (val uintptr) {
   590  	if runtime.GOARCH == "386" {
   591  		val, _, _ = _GetWindowLong32.Call(uintptr(hwnd), index)
   592  	} else {
   593  		val, _, _ = _GetWindowLong.Call(uintptr(hwnd), index)
   594  	}
   595  	return
   596  }
   597  
   598  func ImmGetContext(hwnd syscall.Handle) syscall.Handle {
   599  	h, _, _ := _ImmGetContext.Call(uintptr(hwnd))
   600  	return syscall.Handle(h)
   601  }
   602  
   603  func ImmReleaseContext(hwnd, imc syscall.Handle) {
   604  	_ImmReleaseContext.Call(uintptr(hwnd), uintptr(imc))
   605  }
   606  
   607  func ImmNotifyIME(imc syscall.Handle, action, index, value int) {
   608  	_ImmNotifyIME.Call(uintptr(imc), uintptr(action), uintptr(index), uintptr(value))
   609  }
   610  
   611  func ImmGetCompositionString(imc syscall.Handle, key int) string {
   612  	size, _, _ := _ImmGetCompositionString.Call(uintptr(imc), uintptr(key), 0, 0)
   613  	if int32(size) <= 0 {
   614  		return ""
   615  	}
   616  	u16 := make([]uint16, size/unsafe.Sizeof(uint16(0)))
   617  	_ImmGetCompositionString.Call(uintptr(imc), uintptr(key), uintptr(unsafe.Pointer(&u16[0])), size)
   618  	return string(utf16.Decode(u16))
   619  }
   620  
   621  func ImmGetCompositionValue(imc syscall.Handle, key int) int {
   622  	val, _, _ := _ImmGetCompositionString.Call(uintptr(imc), uintptr(key), 0, 0)
   623  	return int(int32(val))
   624  }
   625  
   626  func ImmSetCompositionWindow(imc syscall.Handle, x, y int) {
   627  	f := CompositionForm{
   628  		dwStyle: CFS_POINT,
   629  		ptCurrentPos: Point{
   630  			X: int32(x), Y: int32(y),
   631  		},
   632  	}
   633  	_ImmSetCompositionWindow.Call(uintptr(imc), uintptr(unsafe.Pointer(&f)))
   634  }
   635  
   636  func ImmSetCandidateWindow(imc syscall.Handle, x, y int) {
   637  	f := CandidateForm{
   638  		dwStyle: CFS_CANDIDATEPOS,
   639  		ptCurrentPos: Point{
   640  			X: int32(x), Y: int32(y),
   641  		},
   642  	}
   643  	_ImmSetCandidateWindow.Call(uintptr(imc), uintptr(unsafe.Pointer(&f)))
   644  }
   645  
   646  func SetWindowLong(hwnd syscall.Handle, idx uintptr, style uintptr) {
   647  	if runtime.GOARCH == "386" {
   648  		_SetWindowLong32.Call(uintptr(hwnd), idx, style)
   649  	} else {
   650  		_SetWindowLong.Call(uintptr(hwnd), idx, style)
   651  	}
   652  }
   653  
   654  func SetWindowPlacement(hwnd syscall.Handle, wp *WindowPlacement) {
   655  	_SetWindowPlacement.Call(uintptr(hwnd), uintptr(unsafe.Pointer(wp)))
   656  }
   657  
   658  func SetWindowPos(hwnd syscall.Handle, hwndInsertAfter uint32, x, y, dx, dy int32, style uintptr) {
   659  	_SetWindowPos.Call(uintptr(hwnd), uintptr(hwndInsertAfter),
   660  		uintptr(x), uintptr(y),
   661  		uintptr(dx), uintptr(dy),
   662  		style,
   663  	)
   664  }
   665  
   666  func SetWindowText(hwnd syscall.Handle, title string) {
   667  	wname := syscall.StringToUTF16Ptr(title)
   668  	_SetWindowText.Call(uintptr(hwnd), uintptr(unsafe.Pointer(wname)))
   669  }
   670  
   671  func GlobalAlloc(size int) (syscall.Handle, error) {
   672  	r, _, err := _GlobalAlloc.Call(GHND, uintptr(size))
   673  	if r == 0 {
   674  		return 0, fmt.Errorf("GlobalAlloc: %v", err)
   675  	}
   676  	return syscall.Handle(r), nil
   677  }
   678  
   679  func GlobalFree(h syscall.Handle) {
   680  	_GlobalFree.Call(uintptr(h))
   681  }
   682  
   683  func GlobalLock(h syscall.Handle) (unsafe.Pointer, error) {
   684  	r, _, err := _GlobalLock.Call(uintptr(h))
   685  	if r == 0 {
   686  		return nil, fmt.Errorf("GlobalLock: %v", err)
   687  	}
   688  	return unsafe.Pointer(r), nil
   689  }
   690  
   691  func GlobalUnlock(h syscall.Handle) {
   692  	_GlobalUnlock.Call(uintptr(h))
   693  }
   694  
   695  func KillTimer(hwnd syscall.Handle, nIDEvent uintptr) error {
   696  	r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), 0, 0)
   697  	if r == 0 {
   698  		return fmt.Errorf("KillTimer failed: %v", err)
   699  	}
   700  	return nil
   701  }
   702  
   703  func LoadCursor(curID uint16) (syscall.Handle, error) {
   704  	h, _, err := _LoadCursor.Call(0, uintptr(curID))
   705  	if h == 0 {
   706  		return 0, fmt.Errorf("LoadCursorW failed: %v", err)
   707  	}
   708  	return syscall.Handle(h), nil
   709  }
   710  
   711  func LoadImage(hInst syscall.Handle, res uint32, typ uint32, cx, cy int, fuload uint32) (syscall.Handle, error) {
   712  	h, _, err := _LoadImage.Call(uintptr(hInst), uintptr(res), uintptr(typ), uintptr(cx), uintptr(cy), uintptr(fuload))
   713  	if h == 0 {
   714  		return 0, fmt.Errorf("LoadImageW failed: %v", err)
   715  	}
   716  	return syscall.Handle(h), nil
   717  }
   718  
   719  func MoveWindow(hwnd syscall.Handle, x, y, width, height int32, repaint bool) {
   720  	var paint uintptr
   721  	if repaint {
   722  		paint = TRUE
   723  	}
   724  	_MoveWindow.Call(uintptr(hwnd), uintptr(x), uintptr(y), uintptr(width), uintptr(height), paint)
   725  }
   726  
   727  func monitorFromPoint(pt Point, flags uint32) syscall.Handle {
   728  	r, _, _ := _MonitorFromPoint.Call(uintptr(pt.X), uintptr(pt.Y), uintptr(flags))
   729  	return syscall.Handle(r)
   730  }
   731  
   732  func MsgWaitForMultipleObjectsEx(nCount uint32, pHandles uintptr, millis, mask, flags uint32) (uint32, error) {
   733  	r, _, err := _MsgWaitForMultipleObjectsEx.Call(uintptr(nCount), pHandles, uintptr(millis), uintptr(mask), uintptr(flags))
   734  	res := uint32(r)
   735  	if res == 0xFFFFFFFF {
   736  		return 0, fmt.Errorf("MsgWaitForMultipleObjectsEx failed: %v", err)
   737  	}
   738  	return res, nil
   739  }
   740  
   741  func OpenClipboard(hwnd syscall.Handle) error {
   742  	r, _, err := _OpenClipboard.Call(uintptr(hwnd))
   743  	if r == 0 {
   744  		return fmt.Errorf("OpenClipboard: %v", err)
   745  	}
   746  	return nil
   747  }
   748  
   749  func PeekMessage(m *Msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax, wRemoveMsg uint32) bool {
   750  	r, _, _ := _PeekMessage.Call(uintptr(unsafe.Pointer(m)), uintptr(hwnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), uintptr(wRemoveMsg))
   751  	return r != 0
   752  }
   753  
   754  func PostQuitMessage(exitCode uintptr) {
   755  	_PostQuitMessage.Call(exitCode)
   756  }
   757  
   758  func PostMessage(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) error {
   759  	r, _, err := _PostMessage.Call(uintptr(hwnd), uintptr(msg), wParam, lParam)
   760  	if r == 0 {
   761  		return fmt.Errorf("PostMessage failed: %v", err)
   762  	}
   763  	return nil
   764  }
   765  
   766  func ReleaseCapture() bool {
   767  	r, _, _ := _ReleaseCapture.Call()
   768  	return r != 0
   769  }
   770  
   771  func RegisterClassEx(cls *WndClassEx) (uint16, error) {
   772  	a, _, err := _RegisterClassExW.Call(uintptr(unsafe.Pointer(cls)))
   773  	if a == 0 {
   774  		return 0, fmt.Errorf("RegisterClassExW failed: %v", err)
   775  	}
   776  	return uint16(a), nil
   777  }
   778  
   779  func ReleaseDC(hdc syscall.Handle) {
   780  	_ReleaseDC.Call(uintptr(hdc))
   781  }
   782  
   783  func SetForegroundWindow(hwnd syscall.Handle) {
   784  	_SetForegroundWindow.Call(uintptr(hwnd))
   785  }
   786  
   787  func SetFocus(hwnd syscall.Handle) {
   788  	_SetFocus.Call(uintptr(hwnd))
   789  }
   790  
   791  func SetProcessDPIAware() {
   792  	_SetProcessDPIAware.Call()
   793  }
   794  
   795  func SetCapture(hwnd syscall.Handle) syscall.Handle {
   796  	r, _, _ := _SetCapture.Call(uintptr(hwnd))
   797  	return syscall.Handle(r)
   798  }
   799  
   800  func SetClipboardData(format uint32, mem syscall.Handle) error {
   801  	r, _, err := _SetClipboardData.Call(uintptr(format), uintptr(mem))
   802  	if r == 0 {
   803  		return fmt.Errorf("SetClipboardData: %v", err)
   804  	}
   805  	return nil
   806  }
   807  
   808  func SetCursor(h syscall.Handle) {
   809  	_SetCursor.Call(uintptr(h))
   810  }
   811  
   812  func SetTimer(hwnd syscall.Handle, nIDEvent uintptr, uElapse uint32, timerProc uintptr) error {
   813  	r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), uintptr(uElapse), timerProc)
   814  	if r == 0 {
   815  		return fmt.Errorf("SetTimer failed: %v", err)
   816  	}
   817  	return nil
   818  }
   819  
   820  func ScreenToClient(hwnd syscall.Handle, p *Point) {
   821  	_ScreenToClient.Call(uintptr(hwnd), uintptr(unsafe.Pointer(p)))
   822  }
   823  
   824  func ShowWindow(hwnd syscall.Handle, nCmdShow int32) {
   825  	_ShowWindow.Call(uintptr(hwnd), uintptr(nCmdShow))
   826  }
   827  
   828  func TranslateMessage(m *Msg) {
   829  	_TranslateMessage.Call(uintptr(unsafe.Pointer(m)))
   830  }
   831  
   832  func UnregisterClass(cls uint16, hInst syscall.Handle) {
   833  	_UnregisterClass.Call(uintptr(cls), uintptr(hInst))
   834  }
   835  
   836  func UpdateWindow(hwnd syscall.Handle) {
   837  	_UpdateWindow.Call(uintptr(hwnd))
   838  }
   839  
   840  func (p WindowPlacement) Rect() Rect {
   841  	return p.rcNormalPosition
   842  }
   843  
   844  func (p WindowPlacement) IsMinimized() bool {
   845  	return p.showCmd == SW_SHOWMINIMIZED
   846  }
   847  
   848  func (p WindowPlacement) IsMaximized() bool {
   849  	return p.showCmd == SW_SHOWMAXIMIZED
   850  }
   851  
   852  func (p *WindowPlacement) Set(Left, Top, Right, Bottom int) {
   853  	p.rcNormalPosition.Left = int32(Left)
   854  	p.rcNormalPosition.Top = int32(Top)
   855  	p.rcNormalPosition.Right = int32(Right)
   856  	p.rcNormalPosition.Bottom = int32(Bottom)
   857  }