1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3
4package main
5
6import (
7 "runtime"
8 "syscall"
9 "unsafe"
10
11 "github.com/ebitengine/purego"
12)
13
14const (
15 WS_OVERLAPPEDWINDOW = 0x00000000 | 0x00C00000 | 0x00080000 | 0x00040000 | 0x00020000 | 0x00010000
16 CW_USEDEFAULT = ^0x7fffffff
17 SW_SHOW = 5
18 WM_DESTROY = 2
19)
20
21type (
22 ATOM uint16
23 HANDLE uintptr
24 HINSTANCE HANDLE
25 HICON HANDLE
26 HCURSOR HANDLE
27 HBRUSH HANDLE
28 HWND HANDLE
29 HMENU HANDLE
30)
31
32type WNDCLASSEX struct {
33 Size uint32
34 Style uint32
35 WndProc uintptr
36 ClsExtra int32
37 WndExtra int32
38 Instance HINSTANCE
39 Icon HICON
40 Cursor HCURSOR
41 Background HBRUSH
42 MenuName *uint16
43 ClassName *uint16
44 IconSm HICON
45}
46
47type RECT struct {
48 Left, Top, Right, Bottom int32
49}
50
51type POINT struct {
52 X, Y int32
53}
54
55type MSG struct {
56 Hwnd HWND
57 Message uint32
58 WParam uintptr
59 LParam uintptr
60 Time uint32
61 Pt POINT
62}
63
64var (
65 GetModuleHandle func(modulename *uint16) HINSTANCE
66 RegisterClassEx func(w *WNDCLASSEX) ATOM
67 CreateWindowEx func(exStyle uint, className, windowName *uint16,
68 style uint, x, y, width, height int, parent HWND, menu HMENU,
69 instance HINSTANCE, param unsafe.Pointer) HWND
70 AdjustWindowRect func(rect *RECT, style uint, menu bool) bool
71 ShowWindow func(hwnd HWND, cmdshow int) bool
72 GetMessage func(msg *MSG, hwnd HWND, msgFilterMin, msgFilterMax uint32) int
73 TranslateMessage func(msg *MSG) bool
74 DispatchMessage func(msg *MSG) uintptr
75 DefWindowProc func(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr
76 PostQuitMessage func(exitCode int)
77)
78
79func init() {
80 // Use [syscall.NewLazyDLL] here to avoid external dependencies (#270).
81 // For actual use cases, [golang.org/x/sys/windows.NewLazySystemDLL] is recommended.
82 kernel32 := syscall.NewLazyDLL("kernel32.dll").Handle()
83 purego.RegisterLibFunc(&GetModuleHandle, kernel32, "GetModuleHandleW")
84
85 // Use [syscall.NewLazyDLL] here to avoid external dependencies (#270).
86 // For actual use cases, [golang.org/x/sys/windows.NewLazySystemDLL] is recommended.
87 user32 := syscall.NewLazyDLL("user32.dll").Handle()
88 purego.RegisterLibFunc(&RegisterClassEx, user32, "RegisterClassExW")
89 purego.RegisterLibFunc(&CreateWindowEx, user32, "CreateWindowExW")
90 purego.RegisterLibFunc(&AdjustWindowRect, user32, "AdjustWindowRect")
91 purego.RegisterLibFunc(&ShowWindow, user32, "ShowWindow")
92 purego.RegisterLibFunc(&GetMessage, user32, "GetMessageW")
93 purego.RegisterLibFunc(&TranslateMessage, user32, "TranslateMessage")
94 purego.RegisterLibFunc(&DispatchMessage, user32, "DispatchMessageW")
95 purego.RegisterLibFunc(&DefWindowProc, user32, "DefWindowProcW")
96 purego.RegisterLibFunc(&PostQuitMessage, user32, "PostQuitMessage")
97
98 runtime.LockOSThread()
99}
100
101func main() {
102 className, err := syscall.UTF16PtrFromString("Sample Window Class")
103 if err != nil {
104 panic(err)
105 }
106 inst := GetModuleHandle(className)
107
108 wc := WNDCLASSEX{
109 Size: uint32(unsafe.Sizeof(WNDCLASSEX{})),
110 WndProc: syscall.NewCallback(wndProc),
111 Instance: inst,
112 ClassName: className,
113 }
114
115 RegisterClassEx(&wc)
116
117 wr := RECT{
118 Left: 0,
119 Top: 0,
120 Right: 320,
121 Bottom: 240,
122 }
123 title, err := syscall.UTF16PtrFromString("My Title")
124 if err != nil {
125 panic(err)
126 }
127 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, false)
128 hwnd := CreateWindowEx(
129 0, className,
130 title,
131 WS_OVERLAPPEDWINDOW,
132 CW_USEDEFAULT, CW_USEDEFAULT, int(wr.Right-wr.Left), int(wr.Bottom-wr.Top),
133 0, 0, inst, nil,
134 )
135 if hwnd == 0 {
136 panic(syscall.GetLastError())
137 }
138
139 ShowWindow(hwnd, SW_SHOW)
140
141 var msg MSG
142 for GetMessage(&msg, 0, 0, 0) != 0 {
143 TranslateMessage(&msg)
144 DispatchMessage(&msg)
145 }
146}
147
148func wndProc(hwnd HWND, msg uint32, wparam, lparam uintptr) uintptr {
149 switch msg {
150 case WM_DESTROY:
151 PostQuitMessage(0)
152 }
153 return DefWindowProc(hwnd, msg, wparam, lparam)
154}