github.com/utopiagio/gio@v0.0.8/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_MOVE                 = 0x0003	// Added RNW 16/01/23
   269  	WM_NCACTIVATE           = 0x0086
   270  	WM_NCHITTEST            = 0x0084
   271  	WM_NCCALCSIZE           = 0x0083
   272  	WM_PAINT                = 0x000F
   273  	WM_QUIT                 = 0x0012
   274  	WM_SETCURSOR            = 0x0020
   275  	WM_SETFOCUS             = 0x0007
   276  	WM_SHOWWINDOW           = 0x0018
   277  	WM_SIZE                 = 0x0005
   278  	WM_SYSKEYDOWN           = 0x0104
   279  	WM_SYSKEYUP             = 0x0105
   280  	WM_RBUTTONDOWN          = 0x0204
   281  	WM_RBUTTONUP            = 0x0205
   282  	WM_TIMER                = 0x0113
   283  	WM_UNICHAR              = 0x0109
   284  	WM_USER                 = 0x0400
   285  	WM_WINDOWPOSCHANGED     = 0x0047
   286  
   287  	WS_CLIPCHILDREN     = 0x02000000
   288  	WS_CLIPSIBLINGS     = 0x04000000
   289  	WS_MAXIMIZE         = 0x01000000
   290  	WS_ICONIC           = 0x20000000
   291  	WS_VISIBLE          = 0x10000000
   292  	WS_OVERLAPPED       = 0x00000000
   293  	WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
   294  		WS_MINIMIZEBOX | WS_MAXIMIZEBOX
   295  	WS_CAPTION     = 0x00C00000
   296  	WS_SYSMENU     = 0x00080000
   297  	WS_THICKFRAME  = 0x00040000
   298  	WS_MINIMIZEBOX = 0x00020000
   299  	WS_MAXIMIZEBOX = 0x00010000
   300  	
   301  	WS_EX_TOPMOST    = 0x00000008	// Added RNW 02/03/24
   302  	WS_EX_APPWINDOW  = 0x00040000
   303  	WS_EX_WINDOWEDGE = 0x00000100
   304  
   305  	QS_ALLINPUT = 0x04FF
   306  
   307  	MWMO_WAITALL        = 0x0001
   308  	MWMO_INPUTAVAILABLE = 0x0004
   309  
   310  	WAIT_OBJECT_0 = 0
   311  
   312  	PM_REMOVE   = 0x0001
   313  	PM_NOREMOVE = 0x0000
   314  
   315  	GHND = 0x0042
   316  
   317  	CF_UNICODETEXT = 13
   318  	IMAGE_BITMAP   = 0
   319  	IMAGE_ICON     = 1
   320  	IMAGE_CURSOR   = 2
   321  
   322  	LR_CREATEDIBSECTION = 0x00002000
   323  	LR_DEFAULTCOLOR     = 0x00000000
   324  	LR_DEFAULTSIZE      = 0x00000040
   325  	LR_LOADFROMFILE     = 0x00000010
   326  	LR_LOADMAP3DCOLORS  = 0x00001000
   327  	LR_LOADTRANSPARENT  = 0x00000020
   328  	LR_MONOCHROME       = 0x00000001
   329  	LR_SHARED           = 0x00008000
   330  	LR_VGACOLOR         = 0x00000080
   331  )
   332  
   333  var (
   334  	kernel32          = syscall.NewLazySystemDLL("kernel32.dll")
   335  	_GetModuleHandleW = kernel32.NewProc("GetModuleHandleW")
   336  	_GlobalAlloc      = kernel32.NewProc("GlobalAlloc")
   337  	_GlobalFree       = kernel32.NewProc("GlobalFree")
   338  	_GlobalLock       = kernel32.NewProc("GlobalLock")
   339  	_GlobalUnlock     = kernel32.NewProc("GlobalUnlock")
   340  
   341  	user32                       = syscall.NewLazySystemDLL("user32.dll")
   342  	_AdjustWindowRectEx          = user32.NewProc("AdjustWindowRectEx")
   343  	_CallMsgFilter               = user32.NewProc("CallMsgFilterW")
   344  	_CloseClipboard              = user32.NewProc("CloseClipboard")
   345  	_CreateWindowEx              = user32.NewProc("CreateWindowExW")
   346  	_DefWindowProc               = user32.NewProc("DefWindowProcW")
   347  	_DestroyWindow               = user32.NewProc("DestroyWindow")
   348  	_DispatchMessage             = user32.NewProc("DispatchMessageW")
   349  	_EmptyClipboard              = user32.NewProc("EmptyClipboard")
   350  	_GetWindowRect               = user32.NewProc("GetWindowRect")
   351  	_GetClientRect               = user32.NewProc("GetClientRect")
   352  	_GetClipboardData            = user32.NewProc("GetClipboardData")
   353  	_GetDC                       = user32.NewProc("GetDC")
   354  	_GetDpiForWindow             = user32.NewProc("GetDpiForWindow")
   355  	_GetKeyState                 = user32.NewProc("GetKeyState")
   356  	_GetMessage                  = user32.NewProc("GetMessageW")
   357  	_GetMessageTime              = user32.NewProc("GetMessageTime")
   358  	_GetMonitorInfo              = user32.NewProc("GetMonitorInfoW")
   359  	_GetSystemMetrics            = user32.NewProc("GetSystemMetrics")
   360  	_GetWindowLong               = user32.NewProc("GetWindowLongPtrW")
   361  	_GetWindowLong32             = user32.NewProc("GetWindowLongW")
   362  	_GetWindowPlacement          = user32.NewProc("GetWindowPlacement")
   363  	_KillTimer                   = user32.NewProc("KillTimer")
   364  	_LoadCursor                  = user32.NewProc("LoadCursorW")
   365  	_LoadImage                   = user32.NewProc("LoadImageW")
   366  	_MonitorFromPoint            = user32.NewProc("MonitorFromPoint")
   367  	_MonitorFromWindow           = user32.NewProc("MonitorFromWindow")
   368  	_MoveWindow                  = user32.NewProc("MoveWindow")
   369  	_MsgWaitForMultipleObjectsEx = user32.NewProc("MsgWaitForMultipleObjectsEx")
   370  	_OpenClipboard               = user32.NewProc("OpenClipboard")
   371  	_PeekMessage                 = user32.NewProc("PeekMessageW")
   372  	_PostMessage                 = user32.NewProc("PostMessageW")
   373  	_PostQuitMessage             = user32.NewProc("PostQuitMessage")
   374  	_ReleaseCapture              = user32.NewProc("ReleaseCapture")
   375  	_RegisterClassExW            = user32.NewProc("RegisterClassExW")
   376  	_ReleaseDC                   = user32.NewProc("ReleaseDC")
   377  	_ScreenToClient              = user32.NewProc("ScreenToClient")
   378  	_ShowWindow                  = user32.NewProc("ShowWindow")
   379  	_SetCapture                  = user32.NewProc("SetCapture")
   380  	_SetCursor                   = user32.NewProc("SetCursor")
   381  	_SetClipboardData            = user32.NewProc("SetClipboardData")
   382  	_SetForegroundWindow         = user32.NewProc("SetForegroundWindow")
   383  	_SetFocus                    = user32.NewProc("SetFocus")
   384  	_SetProcessDPIAware          = user32.NewProc("SetProcessDPIAware")
   385  	_SetTimer                    = user32.NewProc("SetTimer")
   386  	_SetWindowLong               = user32.NewProc("SetWindowLongPtrW")
   387  	_SetWindowLong32             = user32.NewProc("SetWindowLongW")
   388  	_SetWindowPlacement          = user32.NewProc("SetWindowPlacement")
   389  	_SetWindowPos                = user32.NewProc("SetWindowPos")
   390  	_SetWindowText               = user32.NewProc("SetWindowTextW")
   391  	_TranslateMessage            = user32.NewProc("TranslateMessage")
   392  	_UnregisterClass             = user32.NewProc("UnregisterClassW")
   393  	_UpdateWindow                = user32.NewProc("UpdateWindow")
   394  
   395  	shcore            = syscall.NewLazySystemDLL("shcore")
   396  	_GetDpiForMonitor = shcore.NewProc("GetDpiForMonitor")
   397  
   398  	gdi32          = syscall.NewLazySystemDLL("gdi32")
   399  	_GetDeviceCaps = gdi32.NewProc("GetDeviceCaps")
   400  
   401  	imm32                    = syscall.NewLazySystemDLL("imm32")
   402  	_ImmGetContext           = imm32.NewProc("ImmGetContext")
   403  	_ImmGetCompositionString = imm32.NewProc("ImmGetCompositionStringW")
   404  	_ImmNotifyIME            = imm32.NewProc("ImmNotifyIME")
   405  	_ImmReleaseContext       = imm32.NewProc("ImmReleaseContext")
   406  	_ImmSetCandidateWindow   = imm32.NewProc("ImmSetCandidateWindow")
   407  	_ImmSetCompositionWindow = imm32.NewProc("ImmSetCompositionWindow")
   408  
   409  	dwmapi                        = syscall.NewLazySystemDLL("dwmapi")
   410  	_DwmExtendFrameIntoClientArea = dwmapi.NewProc("DwmExtendFrameIntoClientArea")
   411  )
   412  
   413  func AdjustWindowRectEx(r *Rect, dwStyle uint32, bMenu int, dwExStyle uint32) {
   414  	_AdjustWindowRectEx.Call(uintptr(unsafe.Pointer(r)), uintptr(dwStyle), uintptr(bMenu), uintptr(dwExStyle))
   415  }
   416  
   417  func CallMsgFilter(m *Msg, nCode uintptr) bool {
   418  	r, _, _ := _CallMsgFilter.Call(uintptr(unsafe.Pointer(m)), nCode)
   419  	return r != 0
   420  }
   421  
   422  func CloseClipboard() error {
   423  	r, _, err := _CloseClipboard.Call()
   424  	if r == 0 {
   425  		return fmt.Errorf("CloseClipboard: %v", err)
   426  	}
   427  	return nil
   428  }
   429  
   430  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) {
   431  	wname := syscall.StringToUTF16Ptr(lpWindowName)
   432  	hwnd, _, err := _CreateWindowEx.Call(
   433  		uintptr(dwExStyle),
   434  		uintptr(lpClassName),
   435  		uintptr(unsafe.Pointer(wname)),
   436  		uintptr(dwStyle),
   437  		uintptr(x), uintptr(y),
   438  		uintptr(w), uintptr(h),
   439  		uintptr(hWndParent),
   440  		uintptr(hMenu),
   441  		uintptr(hInstance),
   442  		uintptr(lpParam))
   443  	if hwnd == 0 {
   444  		return 0, fmt.Errorf("CreateWindowEx failed: %v", err)
   445  	}
   446  	return syscall.Handle(hwnd), nil
   447  }
   448  
   449  func DefWindowProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) uintptr {
   450  	r, _, _ := _DefWindowProc.Call(uintptr(hwnd), uintptr(msg), wparam, lparam)
   451  	return r
   452  }
   453  
   454  func DestroyWindow(hwnd syscall.Handle) {
   455  	_DestroyWindow.Call(uintptr(hwnd))
   456  }
   457  
   458  func DispatchMessage(m *Msg) {
   459  	_DispatchMessage.Call(uintptr(unsafe.Pointer(m)))
   460  }
   461  
   462  func DwmExtendFrameIntoClientArea(hwnd syscall.Handle, margins Margins) error {
   463  	r, _, _ := _DwmExtendFrameIntoClientArea.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&margins)))
   464  	if r != 0 {
   465  		return fmt.Errorf("DwmExtendFrameIntoClientArea: %#x", r)
   466  	}
   467  	return nil
   468  }
   469  
   470  func EmptyClipboard() error {
   471  	r, _, err := _EmptyClipboard.Call()
   472  	if r == 0 {
   473  		return fmt.Errorf("EmptyClipboard: %v", err)
   474  	}
   475  	return nil
   476  }
   477  
   478  func GetWindowRect(hwnd syscall.Handle) Rect {
   479  	var r Rect
   480  	_GetWindowRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&r)))
   481  	return r
   482  }
   483  
   484  func GetClientRect(hwnd syscall.Handle) Rect {
   485  	var r Rect
   486  	_GetClientRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&r)))
   487  	return r
   488  }
   489  
   490  func GetClipboardData(format uint32) (syscall.Handle, error) {
   491  	r, _, err := _GetClipboardData.Call(uintptr(format))
   492  	if r == 0 {
   493  		return 0, fmt.Errorf("GetClipboardData: %v", err)
   494  	}
   495  	return syscall.Handle(r), nil
   496  }
   497  
   498  func GetDC(hwnd syscall.Handle) (syscall.Handle, error) {
   499  	hdc, _, err := _GetDC.Call(uintptr(hwnd))
   500  	if hdc == 0 {
   501  		return 0, fmt.Errorf("GetDC failed: %v", err)
   502  	}
   503  	return syscall.Handle(hdc), nil
   504  }
   505  
   506  func GetModuleHandle() (syscall.Handle, error) {
   507  	h, _, err := _GetModuleHandleW.Call(uintptr(0))
   508  	if h == 0 {
   509  		return 0, fmt.Errorf("GetModuleHandleW failed: %v", err)
   510  	}
   511  	return syscall.Handle(h), nil
   512  }
   513  
   514  func getDeviceCaps(hdc syscall.Handle, index int32) int {
   515  	c, _, _ := _GetDeviceCaps.Call(uintptr(hdc), uintptr(index))
   516  	return int(c)
   517  }
   518  
   519  func getDpiForMonitor(hmonitor syscall.Handle, dpiType uint32) int {
   520  	var dpiX, dpiY uintptr
   521  	_GetDpiForMonitor.Call(uintptr(hmonitor), uintptr(dpiType), uintptr(unsafe.Pointer(&dpiX)), uintptr(unsafe.Pointer(&dpiY)))
   522  	return int(dpiX)
   523  }
   524  
   525  // GetSystemDPI returns the effective DPI of the system.
   526  func GetSystemDPI() int {
   527  	// Check for GetDpiForMonitor, introduced in Windows 8.1.
   528  	if _GetDpiForMonitor.Find() == nil {
   529  		hmon := monitorFromPoint(Point{}, MONITOR_DEFAULTTOPRIMARY)
   530  		dpi := getDpiForMonitor(hmon, MDT_EFFECTIVE_DPI)
   531  		return dpi
   532  	} else {
   533  		// Fall back to the physical device DPI.
   534  		screenDC, err := GetDC(0)
   535  		if err != nil {
   536  			return 96
   537  		}
   538  		defer ReleaseDC(screenDC)
   539  		return getDeviceCaps(screenDC, LOGPIXELSX)
   540  	}
   541  }
   542  
   543  func GetKeyState(nVirtKey int32) int16 {
   544  	c, _, _ := _GetKeyState.Call(uintptr(nVirtKey))
   545  	return int16(c)
   546  }
   547  
   548  func GetMessage(m *Msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax uint32) int32 {
   549  	r, _, _ := _GetMessage.Call(uintptr(unsafe.Pointer(m)),
   550  		uintptr(hwnd),
   551  		uintptr(wMsgFilterMin),
   552  		uintptr(wMsgFilterMax))
   553  	return int32(r)
   554  }
   555  
   556  func GetMessageTime() time.Duration {
   557  	r, _, _ := _GetMessageTime.Call()
   558  	return time.Duration(r) * time.Millisecond
   559  }
   560  
   561  func GetSystemMetrics(nIndex int) int {
   562  	r, _, _ := _GetSystemMetrics.Call(uintptr(nIndex))
   563  	return int(r)
   564  }
   565  
   566  // GetWindowDPI returns the effective DPI of the window.
   567  func GetWindowDPI(hwnd syscall.Handle) int {
   568  	// Check for GetDpiForWindow, introduced in Windows 10.
   569  	if _GetDpiForWindow.Find() == nil {
   570  		dpi, _, _ := _GetDpiForWindow.Call(uintptr(hwnd))
   571  		return int(dpi)
   572  	} else {
   573  		return GetSystemDPI()
   574  	}
   575  }
   576  
   577  func GetWindowPlacement(hwnd syscall.Handle) *WindowPlacement {
   578  	var wp WindowPlacement
   579  	wp.length = uint32(unsafe.Sizeof(wp))
   580  	_GetWindowPlacement.Call(uintptr(hwnd), uintptr(unsafe.Pointer(&wp)))
   581  	return &wp
   582  }
   583  
   584  func GetMonitorInfo(hwnd syscall.Handle) MonitorInfo {
   585  	var mi MonitorInfo
   586  	mi.cbSize = uint32(unsafe.Sizeof(mi))
   587  	v, _, _ := _MonitorFromWindow.Call(uintptr(hwnd), MONITOR_DEFAULTTOPRIMARY)
   588  	_GetMonitorInfo.Call(v, uintptr(unsafe.Pointer(&mi)))
   589  	return mi
   590  }
   591  
   592  func GetWindowLong(hwnd syscall.Handle, index uintptr) (val uintptr) {
   593  	if runtime.GOARCH == "386" {
   594  		val, _, _ = _GetWindowLong32.Call(uintptr(hwnd), index)
   595  	} else {
   596  		val, _, _ = _GetWindowLong.Call(uintptr(hwnd), index)
   597  	}
   598  	return
   599  }
   600  
   601  func ImmGetContext(hwnd syscall.Handle) syscall.Handle {
   602  	h, _, _ := _ImmGetContext.Call(uintptr(hwnd))
   603  	return syscall.Handle(h)
   604  }
   605  
   606  func ImmReleaseContext(hwnd, imc syscall.Handle) {
   607  	_ImmReleaseContext.Call(uintptr(hwnd), uintptr(imc))
   608  }
   609  
   610  func ImmNotifyIME(imc syscall.Handle, action, index, value int) {
   611  	_ImmNotifyIME.Call(uintptr(imc), uintptr(action), uintptr(index), uintptr(value))
   612  }
   613  
   614  func ImmGetCompositionString(imc syscall.Handle, key int) string {
   615  	size, _, _ := _ImmGetCompositionString.Call(uintptr(imc), uintptr(key), 0, 0)
   616  	if int32(size) <= 0 {
   617  		return ""
   618  	}
   619  	u16 := make([]uint16, size/unsafe.Sizeof(uint16(0)))
   620  	_ImmGetCompositionString.Call(uintptr(imc), uintptr(key), uintptr(unsafe.Pointer(&u16[0])), size)
   621  	return string(utf16.Decode(u16))
   622  }
   623  
   624  func ImmGetCompositionValue(imc syscall.Handle, key int) int {
   625  	val, _, _ := _ImmGetCompositionString.Call(uintptr(imc), uintptr(key), 0, 0)
   626  	return int(int32(val))
   627  }
   628  
   629  func ImmSetCompositionWindow(imc syscall.Handle, x, y int) {
   630  	f := CompositionForm{
   631  		dwStyle: CFS_POINT,
   632  		ptCurrentPos: Point{
   633  			X: int32(x), Y: int32(y),
   634  		},
   635  	}
   636  	_ImmSetCompositionWindow.Call(uintptr(imc), uintptr(unsafe.Pointer(&f)))
   637  }
   638  
   639  func ImmSetCandidateWindow(imc syscall.Handle, x, y int) {
   640  	f := CandidateForm{
   641  		dwStyle: CFS_CANDIDATEPOS,
   642  		ptCurrentPos: Point{
   643  			X: int32(x), Y: int32(y),
   644  		},
   645  	}
   646  	_ImmSetCandidateWindow.Call(uintptr(imc), uintptr(unsafe.Pointer(&f)))
   647  }
   648  
   649  func SetWindowLong(hwnd syscall.Handle, idx uintptr, style uintptr) {
   650  	if runtime.GOARCH == "386" {
   651  		_SetWindowLong32.Call(uintptr(hwnd), idx, style)
   652  	} else {
   653  		_SetWindowLong.Call(uintptr(hwnd), idx, style)
   654  	}
   655  }
   656  
   657  func SetWindowPlacement(hwnd syscall.Handle, wp *WindowPlacement) {
   658  	_SetWindowPlacement.Call(uintptr(hwnd), uintptr(unsafe.Pointer(wp)))
   659  }
   660  
   661  func SetWindowPos(hwnd syscall.Handle, hwndInsertAfter uint32, x, y, dx, dy int32, style uintptr) {
   662  	_SetWindowPos.Call(uintptr(hwnd), uintptr(hwndInsertAfter),
   663  		uintptr(x), uintptr(y),
   664  		uintptr(dx), uintptr(dy),
   665  		style,
   666  	)
   667  }
   668  
   669  func SetWindowText(hwnd syscall.Handle, title string) {
   670  	wname := syscall.StringToUTF16Ptr(title)
   671  	_SetWindowText.Call(uintptr(hwnd), uintptr(unsafe.Pointer(wname)))
   672  }
   673  
   674  func GlobalAlloc(size int) (syscall.Handle, error) {
   675  	r, _, err := _GlobalAlloc.Call(GHND, uintptr(size))
   676  	if r == 0 {
   677  		return 0, fmt.Errorf("GlobalAlloc: %v", err)
   678  	}
   679  	return syscall.Handle(r), nil
   680  }
   681  
   682  func GlobalFree(h syscall.Handle) {
   683  	_GlobalFree.Call(uintptr(h))
   684  }
   685  
   686  func GlobalLock(h syscall.Handle) (unsafe.Pointer, error) {
   687  	r, _, err := _GlobalLock.Call(uintptr(h))
   688  	if r == 0 {
   689  		return nil, fmt.Errorf("GlobalLock: %v", err)
   690  	}
   691  	return unsafe.Pointer(r), nil
   692  }
   693  
   694  func GlobalUnlock(h syscall.Handle) {
   695  	_GlobalUnlock.Call(uintptr(h))
   696  }
   697  
   698  func KillTimer(hwnd syscall.Handle, nIDEvent uintptr) error {
   699  	r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), 0, 0)
   700  	if r == 0 {
   701  		return fmt.Errorf("KillTimer failed: %v", err)
   702  	}
   703  	return nil
   704  }
   705  
   706  func LoadCursor(curID uint16) (syscall.Handle, error) {
   707  	h, _, err := _LoadCursor.Call(0, uintptr(curID))
   708  	if h == 0 {
   709  		return 0, fmt.Errorf("LoadCursorW failed: %v", err)
   710  	}
   711  	return syscall.Handle(h), nil
   712  }
   713  
   714  func LoadImage(hInst syscall.Handle, res uint32, typ uint32, cx, cy int, fuload uint32) (syscall.Handle, error) {
   715  	h, _, err := _LoadImage.Call(uintptr(hInst), uintptr(res), uintptr(typ), uintptr(cx), uintptr(cy), uintptr(fuload))
   716  	if h == 0 {
   717  		return 0, fmt.Errorf("LoadImageW failed: %v", err)
   718  	}
   719  	return syscall.Handle(h), nil
   720  }
   721  
   722  func MoveWindow(hwnd syscall.Handle, x, y, width, height int32, repaint bool) {
   723  	var paint uintptr
   724  	if repaint {
   725  		paint = TRUE
   726  	}
   727  	_MoveWindow.Call(uintptr(hwnd), uintptr(x), uintptr(y), uintptr(width), uintptr(height), paint)
   728  }
   729  
   730  func monitorFromPoint(pt Point, flags uint32) syscall.Handle {
   731  	r, _, _ := _MonitorFromPoint.Call(uintptr(pt.X), uintptr(pt.Y), uintptr(flags))
   732  	return syscall.Handle(r)
   733  }
   734  
   735  func MsgWaitForMultipleObjectsEx(nCount uint32, pHandles uintptr, millis, mask, flags uint32) (uint32, error) {
   736  	r, _, err := _MsgWaitForMultipleObjectsEx.Call(uintptr(nCount), pHandles, uintptr(millis), uintptr(mask), uintptr(flags))
   737  	res := uint32(r)
   738  	if res == 0xFFFFFFFF {
   739  		return 0, fmt.Errorf("MsgWaitForMultipleObjectsEx failed: %v", err)
   740  	}
   741  	return res, nil
   742  }
   743  
   744  func OpenClipboard(hwnd syscall.Handle) error {
   745  	r, _, err := _OpenClipboard.Call(uintptr(hwnd))
   746  	if r == 0 {
   747  		return fmt.Errorf("OpenClipboard: %v", err)
   748  	}
   749  	return nil
   750  }
   751  
   752  func PeekMessage(m *Msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax, wRemoveMsg uint32) bool {
   753  	r, _, _ := _PeekMessage.Call(uintptr(unsafe.Pointer(m)), uintptr(hwnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), uintptr(wRemoveMsg))
   754  	return r != 0
   755  }
   756  
   757  func PostQuitMessage(exitCode uintptr) {
   758  	_PostQuitMessage.Call(exitCode)
   759  }
   760  
   761  func PostMessage(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) error {
   762  	r, _, err := _PostMessage.Call(uintptr(hwnd), uintptr(msg), wParam, lParam)
   763  	if r == 0 {
   764  		return fmt.Errorf("PostMessage failed: %v", err)
   765  	}
   766  	return nil
   767  }
   768  
   769  func ReleaseCapture() bool {
   770  	r, _, _ := _ReleaseCapture.Call()
   771  	return r != 0
   772  }
   773  
   774  func RegisterClassEx(cls *WndClassEx) (uint16, error) {
   775  	a, _, err := _RegisterClassExW.Call(uintptr(unsafe.Pointer(cls)))
   776  	if a == 0 {
   777  		return 0, fmt.Errorf("RegisterClassExW failed: %v", err)
   778  	}
   779  	return uint16(a), nil
   780  }
   781  
   782  func ReleaseDC(hdc syscall.Handle) {
   783  	_ReleaseDC.Call(uintptr(hdc))
   784  }
   785  
   786  func SetForegroundWindow(hwnd syscall.Handle) {
   787  	_SetForegroundWindow.Call(uintptr(hwnd))
   788  }
   789  
   790  func SetFocus(hwnd syscall.Handle) {
   791  	_SetFocus.Call(uintptr(hwnd))
   792  }
   793  
   794  func SetProcessDPIAware() {
   795  	_SetProcessDPIAware.Call()
   796  }
   797  
   798  func SetCapture(hwnd syscall.Handle) syscall.Handle {
   799  	r, _, _ := _SetCapture.Call(uintptr(hwnd))
   800  	return syscall.Handle(r)
   801  }
   802  
   803  func SetClipboardData(format uint32, mem syscall.Handle) error {
   804  	r, _, err := _SetClipboardData.Call(uintptr(format), uintptr(mem))
   805  	if r == 0 {
   806  		return fmt.Errorf("SetClipboardData: %v", err)
   807  	}
   808  	return nil
   809  }
   810  
   811  func SetCursor(h syscall.Handle) {
   812  	_SetCursor.Call(uintptr(h))
   813  }
   814  
   815  func SetTimer(hwnd syscall.Handle, nIDEvent uintptr, uElapse uint32, timerProc uintptr) error {
   816  	r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), uintptr(uElapse), timerProc)
   817  	if r == 0 {
   818  		return fmt.Errorf("SetTimer failed: %v", err)
   819  	}
   820  	return nil
   821  }
   822  
   823  func ScreenToClient(hwnd syscall.Handle, p *Point) {
   824  	_ScreenToClient.Call(uintptr(hwnd), uintptr(unsafe.Pointer(p)))
   825  }
   826  
   827  func ShowWindow(hwnd syscall.Handle, nCmdShow int32) {
   828  	_ShowWindow.Call(uintptr(hwnd), uintptr(nCmdShow))
   829  }
   830  
   831  func TranslateMessage(m *Msg) {
   832  	_TranslateMessage.Call(uintptr(unsafe.Pointer(m)))
   833  }
   834  
   835  func UnregisterClass(cls uint16, hInst syscall.Handle) {
   836  	_UnregisterClass.Call(uintptr(cls), uintptr(hInst))
   837  }
   838  
   839  func UpdateWindow(hwnd syscall.Handle) {
   840  	_UpdateWindow.Call(uintptr(hwnd))
   841  }
   842  
   843  func (p WindowPlacement) Rect() Rect {
   844  	return p.rcNormalPosition
   845  }
   846  
   847  func (p WindowPlacement) IsMinimized() bool {
   848  	return p.showCmd == SW_SHOWMINIMIZED
   849  }
   850  
   851  func (p WindowPlacement) IsMaximized() bool {
   852  	return p.showCmd == SW_SHOWMAXIMIZED
   853  }
   854  
   855  func (p *WindowPlacement) Set(Left, Top, Right, Bottom int) {
   856  	p.rcNormalPosition.Left = int32(Left)
   857  	p.rcNormalPosition.Top = int32(Top)
   858  	p.rcNormalPosition.Right = int32(Right)
   859  	p.rcNormalPosition.Bottom = int32(Bottom)
   860  }