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