package main import ( "fmt" "runtime" "syscall" "unsafe" ) var ( user32 = syscall.NewLazyDLL("user32.dll") kernel32 = syscall.NewLazyDLL("kernel32.dll") procRegisterClassExW = user32.NewProc("RegisterClassExW") procCreateWindowExW = user32.NewProc("CreateWindowExW") procDefWindowProcW = user32.NewProc("DefWindowProcW") procShowWindow = user32.NewProc("ShowWindow") procUpdateWindow = user32.NewProc("UpdateWindow") procGetMessageW = user32.NewProc("GetMessageW") procTranslateMessage = user32.NewProc("TranslateMessage") procDispatchMessageW = user32.NewProc("DispatchMessageW") procPostQuitMessage = user32.NewProc("PostQuitMessage") procLoadCursorW = user32.NewProc("LoadCursorW") procGetModuleHandleW = kernel32.NewProc("GetModuleHandleW") ) const ( CS_HREDRAW = 0x0002 CS_VREDRAW = 0x0001 CW_USEDEFAULT = 0x80000000 WS_OVERLAPPEDWINDOW = 0x00CF0000 SW_SHOWDEFAULT = 10 WM_DESTROY = 0x0002 IDC_ARROW = 32512 COLOR_WINDOW = 5 ) type wndClassEx struct { cbSize uint32 style uint32 lpfnWndProc uintptr cbClsExtra int32 cbWndExtra int32 hInstance syscall.Handle hIcon syscall.Handle hCursor syscall.Handle hbrBackground syscall.Handle lpszMenuName *uint16 lpszClassName *uint16 hIconSm syscall.Handle } type point struct { x int32 y int32 } type msg struct { hwnd syscall.Handle message uint32 wParam uintptr lParam uintptr time uint32 pt point } func wndProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr { switch msg { case WM_DESTROY: postQuitMessage(0) return 0 } ret, _, _ := procDefWindowProcW.Call(uintptr(hwnd), uintptr(msg), wParam, lParam) return ret } func registerWindowClass(className *uint16, instance syscall.Handle, wndProcPtr uintptr) error { wc := wndClassEx{ cbSize: uint32(unsafe.Sizeof(wndClassEx{})), style: CS_HREDRAW | CS_VREDRAW, lpfnWndProc: wndProcPtr, hInstance: instance, hCursor: loadCursor(0, IDC_ARROW), hbrBackground: syscall.Handle(COLOR_WINDOW + 1), lpszClassName: className, } atom, _, err := procRegisterClassExW.Call(uintptr(unsafe.Pointer(&wc))) if atom == 0 { return err } return nil } func createWindow(className, windowTitle *uint16, instance syscall.Handle) (syscall.Handle, error) { hwnd, _, err := procCreateWindowExW.Call( 0, uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(windowTitle)), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, uintptr(instance), 0, ) if hwnd == 0 { return 0, err } return syscall.Handle(hwnd), nil } func showWindow(hwnd syscall.Handle, cmdShow int32) { procShowWindow.Call(uintptr(hwnd), uintptr(cmdShow)) procUpdateWindow.Call(uintptr(hwnd)) } func loadCursor(instance syscall.Handle, cursorID uintptr) syscall.Handle { hCursor, _, _ := procLoadCursorW.Call(uintptr(instance), cursorID) return syscall.Handle(hCursor) } func postQuitMessage(exitCode int32) { procPostQuitMessage.Call(uintptr(exitCode)) } func getModuleHandle() syscall.Handle { handle, _, _ := procGetModuleHandleW.Call(0) return syscall.Handle(handle) } func messageLoop() { var m msg for { ret, _, err := procGetMessageW.Call(uintptr(unsafe.Pointer(&m)), 0, 0, 0) switch int32(ret) { case -1: fmt.Printf("GetMessage failed: %v\n", err) return case 0: return default: procTranslateMessage.Call(uintptr(unsafe.Pointer(&m))) procDispatchMessageW.Call(uintptr(unsafe.Pointer(&m))) } } } func main() { runtime.LockOSThread() className := syscall.StringToUTF16Ptr("GoWinClass") windowTitle := syscall.StringToUTF16Ptr("Go Windows API Window") instance := getModuleHandle() wndProcPtr := syscall.NewCallback(func(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr { return wndProc(hwnd, msg, wParam, lParam) }) if err := registerWindowClass(className, instance, wndProcPtr); err != nil { fmt.Printf("RegisterClassEx failed: %v\n", err) return } hwnd, err := createWindow(className, windowTitle, instance) if err != nil { fmt.Printf("CreateWindowEx failed: %v\n", err) return } showWindow(hwnd, SW_SHOWDEFAULT) messageLoop()