authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 16:02:40-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-01-11 16:02:40-08:00
log4f5fa90d6d921eac07f95fa19c8fd7cf80615537
tree0e25b4180e0012652d6c787431cf1ece9caf01b9
parent483c057a771aca3b045ec8148fa5fb1a5e28fa17
parentc8723beda8c7a0fa7d2137d63afc13ae5334fca3
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7195 from Aransentin/master

A win32-api proposal, implemented for user32.zig

3 files changed, 616 insertions(+), 103 deletions(-)

lib/std/os/windows/bits.zig+13
......@@ -37,6 +37,7 @@ pub const UCHAR = u8;
3737pub const FLOAT = f32;
3838pub const HANDLE = *c_void;
3939pub const HCRYPTPROV = ULONG_PTR;
40pub const ATOM = u16;
4041pub const HBRUSH = *opaque {};
4142pub const HCURSOR = *opaque {};
4243pub const HICON = *opaque {};
......@@ -770,6 +771,13 @@ pub const FILE_FLAG_SESSION_AWARE = 0x00800000;
770771pub const FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000;
771772pub const FILE_FLAG_WRITE_THROUGH = 0x80000000;
772773
774pub const RECT = extern struct {
775 left: LONG,
776 top: LONG,
777 right: LONG,
778 bottom: LONG,
779};
780
773781pub const SMALL_RECT = extern struct {
774782 Left: SHORT,
775783 Top: SHORT,
......@@ -777,6 +785,11 @@ pub const SMALL_RECT = extern struct {
777785 Bottom: SHORT,
778786};
779787
788pub const POINT = extern struct {
789 x: LONG,
790 y: LONG,
791};
792
780793pub const COORD = extern struct {
781794 X: SHORT,
782795 Y: SHORT,
lib/std/os/windows/kernel32.zig+1
......@@ -115,6 +115,7 @@ pub extern "kernel32" fn GetModuleFileNameW(hModule: ?HMODULE, lpFilename: [*]u1
115115pub extern "kernel32" fn GetModuleHandleW(lpModuleName: ?[*:0]const WCHAR) callconv(WINAPI) ?HMODULE;
116116
117117pub extern "kernel32" fn GetLastError() callconv(WINAPI) Win32Error;
118pub extern "kernel32" fn SetLastError(dwErrCode: Win32Error) callconv(WINAPI) void;
118119
119120pub extern "kernel32" fn GetFileInformationByHandle(
120121 hFile: HANDLE,
lib/std/os/windows/user32.zig+602-103
......@@ -4,45 +4,79 @@
44// The MIT license requires this copyright notice to be included in all copies
55// and substantial portions of the software.
66usingnamespace @import("bits.zig");
7const std = @import("std");
8const builtin = @import("builtin");
9const assert = std.debug.assert;
10const windows = @import("../windows.zig");
11const unexpectedError = windows.unexpectedError;
12const GetLastError = windows.kernel32.GetLastError;
13const SetLastError = windows.kernel32.SetLastError;
714
8// PM
9pub const PM_REMOVE = 0x0001;
10pub const PM_NOREMOVE = 0x0000;
11pub const PM_NOYIELD = 0x0002;
15fn selectSymbol(comptime function_static: anytype, function_dynamic: @TypeOf(function_static), comptime os: std.Target.Os.WindowsVersion) @TypeOf(function_static) {
16 comptime {
17 const sym_ok = builtin.Target.current.os.isAtLeast(.windows, os);
18 if (sym_ok == true) return function_static;
19 if (sym_ok == null) return function_dynamic;
20 if (sym_ok == false) @compileError("Target OS range does not support function, at least " ++ @tagName(os) ++ " is required");
21 }
22}
23
24// === Messages ===
25
26pub const WNDPROC = fn (hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(WINAPI) LRESULT;
27
28pub const MSG = extern struct {
29 hWnd: ?HWND,
30 message: UINT,
31 wParam: WPARAM,
32 lParam: LPARAM,
33 time: DWORD,
34 pt: POINT,
35 lPrivate: DWORD,
36};
1237
13// WM
1438pub const WM_NULL = 0x0000;
1539pub const WM_CREATE = 0x0001;
1640pub const WM_DESTROY = 0x0002;
41pub const WM_NCDESTROY = WM_DESTROY;
1742pub const WM_MOVE = 0x0003;
1843pub const WM_SIZE = 0x0005;
19
2044pub const WM_ACTIVATE = 0x0006;
21pub const WM_PAINT = 0x000F;
22pub const WM_CLOSE = 0x0010;
23pub const WM_QUIT = 0x0012;
2445pub const WM_SETFOCUS = 0x0007;
25
2646pub const WM_KILLFOCUS = 0x0008;
2747pub const WM_ENABLE = 0x000A;
2848pub const WM_SETREDRAW = 0x000B;
29
30pub const WM_SYSCOLORCHANGE = 0x0015;
49pub const WM_SETTEXT = 0x000C;
50pub const WM_GETTEXT = 0x000D;
51pub const WM_GETTEXTLENGTH = 0x000E;
52pub const WM_PAINT = 0x000F;
53pub const WM_CLOSE = 0x0010;
54pub const WM_QUIT = 0x0012;
55pub const WM_ERASEBKGND = 0x0014;
3156pub const WM_SHOWWINDOW = 0x0018;
32
33pub const WM_WINDOWPOSCHANGING = 0x0046;
57pub const WM_CTLCOLOR = 0x0019;
58pub const WM_NEXTDLGCTL = 0x0028;
59pub const WM_DRAWITEM = 0x002B;
60pub const WM_MEASUREITEM = 0x002C;
61pub const WM_DELETEITEM = 0x002D;
62pub const WM_VKEYTOITEM = 0x002E;
63pub const WM_CHARTOITEM = 0x002F;
64pub const WM_SETFONT = 0x0030;
65pub const WM_GETFONT = 0x0031;
66pub const WM_COMPAREITEM = 0x0039;
3467pub const WM_WINDOWPOSCHANGED = 0x0047;
35pub const WM_POWER = 0x0048;
36
37pub const WM_CONTEXTMENU = 0x007B;
38pub const WM_STYLECHANGING = 0x007C;
39pub const WM_STYLECHANGED = 0x007D;
40pub const WM_DISPLAYCHANGE = 0x007E;
41pub const WM_GETICON = 0x007F;
42pub const WM_SETICON = 0x0080;
43
44pub const WM_INPUT_DEVICE_CHANGE = 0x00fe;
45pub const WM_INPUT = 0x00FF;
68pub const WM_NOTIFY = 0x004E;
69pub const WM_NCCALCSIZE = 0x0083;
70pub const WM_NCHITTEST = 0x0084;
71pub const WM_NCPAINT = 0x0085;
72pub const WM_GETDLGCODE = 0x0087;
73pub const WM_NCMOUSEMOVE = 0x00A0;
74pub const WM_NCLBUTTONDOWN = 0x00A1;
75pub const WM_NCLBUTTONUP = 0x00A2;
76pub const WM_NCLBUTTONDBLCLK = 0x00A3;
77pub const WM_NCRBUTTONDOWN = 0x00A4;
78pub const WM_NCRBUTTONUP = 0x00A5;
79pub const WM_NCRBUTTONDBLCLK = 0x00A6;
4680pub const WM_KEYFIRST = 0x0100;
4781pub const WM_KEYDOWN = 0x0100;
4882pub const WM_KEYUP = 0x0101;
......@@ -54,11 +88,20 @@ pub const WM_SYSCHAR = 0x0106;
5488pub const WM_SYSDEADCHAR = 0x0107;
5589pub const WM_UNICHAR = 0x0109;
5690pub const WM_KEYLAST = 0x0109;
57
91pub const WM_INITDIALOG = 0x0110;
5892pub const WM_COMMAND = 0x0111;
5993pub const WM_SYSCOMMAND = 0x0112;
6094pub const WM_TIMER = 0x0113;
61
95pub const WM_HSCROLL = 0x0114;
96pub const WM_VSCROLL = 0x0115;
97pub const WM_ENTERIDLE = 0x0121;
98pub const WM_CTLCOLORMSGBOX = 0x0132;
99pub const WM_CTLCOLOREDIT = 0x0133;
100pub const WM_CTLCOLORLISTBOX = 0x0134;
101pub const WM_CTLCOLORBTN = 0x0135;
102pub const WM_CTLCOLORDLG = 0x0136;
103pub const WM_CTLCOLORSCROLLBAR = 0x0137;
104pub const WM_CTLCOLORSTATIC = 0x0138;
62105pub const WM_MOUSEFIRST = 0x0200;
63106pub const WM_MOUSEMOVE = 0x0200;
64107pub const WM_LBUTTONDOWN = 0x0201;
......@@ -71,105 +114,561 @@ pub const WM_MBUTTONDOWN = 0x0207;
71114pub const WM_MBUTTONUP = 0x0208;
72115pub const WM_MBUTTONDBLCLK = 0x0209;
73116pub const WM_MOUSEWHEEL = 0x020A;
74pub const WM_XBUTTONDOWN = 0x020B;
75pub const WM_XBUTTONUP = 0x020C;
76pub const WM_XBUTTONDBLCLK = 0x020D;
117pub const WM_MOUSELAST = 0x020A;
118pub const WM_HOTKEY = 0x0312;
119pub const WM_CARET_CREATE = 0x03E0;
120pub const WM_CARET_DESTROY = 0x03E1;
121pub const WM_CARET_BLINK = 0x03E2;
122pub const WM_FDINPUT = 0x03F0;
123pub const WM_FDOUTPUT = 0x03F1;
124pub const WM_FDEXCEPT = 0x03F2;
125pub const WM_USER = 0x0400;
77126
78// WA
79pub const WA_INACTIVE = 0;
80pub const WA_ACTIVE = 0x0006;
127pub extern "user32" fn GetMessageA(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) callconv(WINAPI) BOOL;
128pub fn getMessageA(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: u32, wMsgFilterMax: u32) !void {
129 const r = GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
130 if (r == 0) return error.Quit;
131 if (r != -1) return;
132 switch (GetLastError()) {
133 .INVALID_WINDOW_HANDLE => unreachable,
134 .INVALID_PARAMETER => unreachable,
135 else => |err| return windows.unexpectedError(err),
136 }
137}
81138
82// WS
83pub const WS_OVERLAPPED = 0x00000000;
84pub const WS_CAPTION = 0x00C00000;
85pub const WS_SYSMENU = 0x00080000;
86pub const WS_THICKFRAME = 0x00040000;
87pub const WS_MINIMIZEBOX = 0x00020000;
88pub const WS_MAXIMIZEBOX = 0x00010000;
139pub extern "user32" fn GetMessageW(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) callconv(WINAPI) BOOL;
140pub var pfnGetMessageW: @TypeOf(GetMessageW) = undefined;
141pub fn getMessageW(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: u32, wMsgFilterMax: u32) !void {
142 const function = selectSymbol(GetMessageW, pfnGetMessageW, .win2k);
89143
90// PFD
91pub const PFD_DRAW_TO_WINDOW = 0x00000004;
92pub const PFD_SUPPORT_OPENGL = 0x00000020;
93pub const PFD_DOUBLEBUFFER = 0x00000001;
94pub const PFD_MAIN_PLANE = 0;
95pub const PFD_TYPE_RGBA = 0;
144 const r = function(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
145 if (r == 0) return error.Quit;
146 if (r != -1) return;
147 switch (GetLastError()) {
148 .INVALID_WINDOW_HANDLE => unreachable,
149 .INVALID_PARAMETER => unreachable,
150 else => |err| return windows.unexpectedError(err),
151 }
152}
96153
97// CS
98pub const CS_HREDRAW = 0x0002;
99pub const CS_VREDRAW = 0x0001;
100pub const CS_OWNDC = 0x0020;
154pub const PM_NOREMOVE = 0x0000;
155pub const PM_REMOVE = 0x0001;
156pub const PM_NOYIELD = 0x0002;
101157
102// SW
103pub const SW_HIDE = 0;
104pub const SW_SHOW = 5;
158pub extern "user32" fn PeekMessageA(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) callconv(WINAPI) BOOL;
159pub fn peekMessageA(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: u32, wMsgFilterMax: u32, wRemoveMsg: u32) !bool {
160 const r = PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
161 if (r == 0) return false;
162 if (r != -1) return true;
163 switch (GetLastError()) {
164 .INVALID_WINDOW_HANDLE => unreachable,
165 .INVALID_PARAMETER => unreachable,
166 else => |err| return windows.unexpectedError(err),
167 }
168}
169
170pub extern "user32" fn PeekMessageW(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) callconv(WINAPI) BOOL;
171pub var pfnPeekMessageW: @TypeOf(PeekMessageW) = undefined;
172pub fn peekMessageW(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: u32, wMsgFilterMax: u32, wRemoveMsg: u32) !bool {
173 const function = selectSymbol(PeekMessageW, pfnPeekMessageW, .win2k);
174
175 const r = function(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
176 if (r == 0) return false;
177 if (r != -1) return true;
178 switch (GetLastError()) {
179 .INVALID_WINDOW_HANDLE => unreachable,
180 .INVALID_PARAMETER => unreachable,
181 else => |err| return windows.unexpectedError(err),
182 }
183}
184
185pub extern "user32" fn TranslateMessage(lpMsg: *const MSG) callconv(WINAPI) BOOL;
186pub fn translateMessage(lpMsg: *const MSG) bool {
187 return if (TranslateMessage(lpMsg) == 0) false else true;
188}
189
190pub extern "user32" fn DispatchMessageA(lpMsg: *const MSG) callconv(WINAPI) LRESULT;
191pub fn dispatchMessageA(lpMsg: *const MSG) LRESULT {
192 return DispatchMessageA(lpMsg);
193}
194
195pub extern "user32" fn DispatchMessageW(lpMsg: *const MSG) callconv(WINAPI) LRESULT;
196pub var pfnDispatchMessageW: @TypeOf(DispatchMessageW) = undefined;
197pub fn dispatchMessageW(lpMsg: *const MSG) LRESULT {
198 const function = selectSymbol(DispatchMessageW, pfnDispatchMessageW, .win2k);
199 return function(lpMsg);
200}
105201
106pub const WNDPROC = fn (HWND, UINT, WPARAM, LPARAM) callconv(WINAPI) LRESULT;
202pub extern "user32" fn PostQuitMessage(nExitCode: i32) callconv(WINAPI) void;
203pub fn postQuitMessage(nExitCode: i32) void {
204 PostQuitMessage(nExitCode);
205}
206
207pub extern "user32" fn DefWindowProcA(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(WINAPI) LRESULT;
208pub fn defWindowProcA(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) LRESULT {
209 return DefWindowProcA(hWnd, Msg, wParam, lParam);
210}
211
212pub extern "user32" fn DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(WINAPI) LRESULT;
213pub var pfnDefWindowProcW: @TypeOf(DefWindowProcW) = undefined;
214pub fn defWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) LRESULT {
215 const function = selectSymbol(DefWindowProcW, pfnDefWindowProcW, .win2k);
216 return function(hWnd, Msg, wParam, lParam);
217}
218
219// === Windows ===
220
221pub const CS_VREDRAW = 0x0001;
222pub const CS_HREDRAW = 0x0002;
223pub const CS_DBLCLKS = 0x0008;
224pub const CS_OWNDC = 0x0020;
225pub const CS_CLASSDC = 0x0040;
226pub const CS_PARENTDC = 0x0080;
227pub const CS_NOCLOSE = 0x0200;
228pub const CS_SAVEBITS = 0x0800;
229pub const CS_BYTEALIGNCLIENT = 0x1000;
230pub const CS_BYTEALIGNWINDOW = 0x2000;
231pub const CS_GLOBALCLASS = 0x4000;
107232
108233pub const WNDCLASSEXA = extern struct {
109234 cbSize: UINT = @sizeOf(WNDCLASSEXA),
110235 style: UINT,
111236 lpfnWndProc: WNDPROC,
112 cbClsExtra: i32,
113 cbWndExtra: i32,
237 cbClsExtra: i32 = 0,
238 cbWndExtra: i32 = 0,
114239 hInstance: HINSTANCE,
115240 hIcon: ?HICON,
116241 hCursor: ?HCURSOR,
117242 hbrBackground: ?HBRUSH,
118 lpszMenuName: ?LPCSTR,
119 lpszClassName: LPCSTR,
243 lpszMenuName: ?[*:0]const u8,
244 lpszClassName: [*:0]const u8,
120245 hIconSm: ?HICON,
121246};
122247
123pub const POINT = extern struct {
124 x: c_long, y: c_long
248pub const WNDCLASSEXW = extern struct {
249 cbSize: UINT = @sizeOf(WNDCLASSEXW),
250 style: UINT,
251 lpfnWndProc: WNDPROC,
252 cbClsExtra: i32 = 0,
253 cbWndExtra: i32 = 0,
254 hInstance: HINSTANCE,
255 hIcon: ?HICON,
256 hCursor: ?HCURSOR,
257 hbrBackground: ?HBRUSH,
258 lpszMenuName: ?[*:0]const u16,
259 lpszClassName: [*:0]const u16,
260 hIconSm: ?HICON,
125261};
126262
127pub const MSG = extern struct {
128 hWnd: ?HWND,
129 message: UINT,
130 wParam: WPARAM,
131 lParam: LPARAM,
132 time: DWORD,
133 pt: POINT,
134 lPrivate: DWORD,
135};
263pub extern "user32" fn RegisterClassExA(*const WNDCLASSEXA) callconv(WINAPI) ATOM;
264pub fn registerClassExA(window_class: *const WNDCLASSEXA) !ATOM {
265 const atom = RegisterClassExA(window_class);
266 if (atom != 0) return atom;
267 switch (GetLastError()) {
268 .CLASS_ALREADY_EXISTS => return error.AlreadyExists,
269 .INVALID_PARAMETER => unreachable,
270 else => |err| return windows.unexpectedError(err),
271 }
272}
136273
137pub extern "user32" fn CreateWindowExA(
138 dwExStyle: DWORD,
139 lpClassName: LPCSTR,
140 lpWindowName: LPCSTR,
141 dwStyle: DWORD,
142 X: i32,
143 Y: i32,
144 nWidth: i32,
145 nHeight: i32,
146 hWindParent: ?HWND,
147 hMenu: ?HMENU,
148 hInstance: HINSTANCE,
149 lpParam: ?LPVOID,
150) callconv(WINAPI) ?HWND;
274pub extern "user32" fn RegisterClassExW(*const WNDCLASSEXW) callconv(WINAPI) ATOM;
275pub var pfnRegisterClassExW: @TypeOf(RegisterClassExW) = undefined;
276pub fn registerClassExW(window_class: *const WNDCLASSEXW) !ATOM {
277 const function = selectSymbol(RegisterClassExW, pfnRegisterClassExW, .win2k);
278 const atom = function(window_class);
279 if (atom != 0) return atom;
280 switch (GetLastError()) {
281 .CLASS_ALREADY_EXISTS => return error.AlreadyExists,
282 .CALL_NOT_IMPLEMENTED => unreachable,
283 .INVALID_PARAMETER => unreachable,
284 else => |err| return windows.unexpectedError(err),
285 }
286}
287
288pub extern "user32" fn UnregisterClassA(lpClassName: [*:0]const u8, hInstance: HINSTANCE) callconv(WINAPI) BOOL;
289pub fn unregisterClassA(lpClassName: [*:0]const u8, hInstance: HINSTANCE) !void {
290 if (UnregisterClassA(lpClassName, hInstance) == 0) {
291 switch (GetLastError()) {
292 .CLASS_DOES_NOT_EXIST => return error.ClassDoesNotExist,
293 else => |err| return windows.unexpectedError(err),
294 }
295 }
296}
297
298pub extern "user32" fn UnregisterClassW(lpClassName: [*:0]const u16, hInstance: HINSTANCE) callconv(WINAPI) BOOL;
299pub var pfnUnregisterClassW: @TypeOf(UnregisterClassW) = undefined;
300pub fn unregisterClassW(lpClassName: [*:0]const u16, hInstance: HINSTANCE) !void {
301 const function = selectSymbol(UnregisterClassW, pfnUnregisterClassW, .win2k);
302 if (function(lpClassName, hInstance) == 0) {
303 switch (GetLastError()) {
304 .CLASS_DOES_NOT_EXIST => return error.ClassDoesNotExist,
305 else => |err| return windows.unexpectedError(err),
306 }
307 }
308}
309
310pub const WS_OVERLAPPED = 0x00000000;
311pub const WS_POPUP = 0x80000000;
312pub const WS_CHILD = 0x40000000;
313pub const WS_MINIMIZE = 0x20000000;
314pub const WS_VISIBLE = 0x10000000;
315pub const WS_DISABLED = 0x08000000;
316pub const WS_CLIPSIBLINGS = 0x04000000;
317pub const WS_CLIPCHILDREN = 0x02000000;
318pub const WS_MAXIMIZE = 0x01000000;
319pub const WS_CAPTION = WS_BORDER | WS_DLGFRAME;
320pub const WS_BORDER = 0x00800000;
321pub const WS_DLGFRAME = 0x00400000;
322pub const WS_VSCROLL = 0x00200000;
323pub const WS_HSCROLL = 0x00100000;
324pub const WS_SYSMENU = 0x00080000;
325pub const WS_THICKFRAME = 0x00040000;
326pub const WS_GROUP = 0x00020000;
327pub const WS_TABSTOP = 0x00010000;
328pub const WS_MINIMIZEBOX = 0x00020000;
329pub const WS_MAXIMIZEBOX = 0x00010000;
330pub const WS_TILED = WS_OVERLAPPED;
331pub const WS_ICONIC = WS_MINIMIZE;
332pub const WS_SIZEBOX = WS_THICKFRAME;
333pub const WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;
334pub const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
335pub const WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU;
336pub const WS_CHILDWINDOW = WS_CHILD;
337
338pub const WS_EX_DLGMODALFRAME = 0x00000001;
339pub const WS_EX_NOPARENTNOTIFY = 0x00000004;
340pub const WS_EX_TOPMOST = 0x00000008;
341pub const WS_EX_ACCEPTFILES = 0x00000010;
342pub const WS_EX_TRANSPARENT = 0x00000020;
343pub const WS_EX_MDICHILD = 0x00000040;
344pub const WS_EX_TOOLWINDOW = 0x00000080;
345pub const WS_EX_WINDOWEDGE = 0x00000100;
346pub const WS_EX_CLIENTEDGE = 0x00000200;
347pub const WS_EX_CONTEXTHELP = 0x00000400;
348pub const WS_EX_RIGHT = 0x00001000;
349pub const WS_EX_LEFT = 0x00000000;
350pub const WS_EX_RTLREADING = 0x00002000;
351pub const WS_EX_LTRREADING = 0x00000000;
352pub const WS_EX_LEFTSCROLLBAR = 0x00004000;
353pub const WS_EX_RIGHTSCROLLBAR = 0x00000000;
354pub const WS_EX_CONTROLPARENT = 0x00010000;
355pub const WS_EX_STATICEDGE = 0x00020000;
356pub const WS_EX_APPWINDOW = 0x00040000;
357pub const WS_EX_LAYERED = 0x00080000;
358pub const WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;
359pub const WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
360
361pub const CW_USEDEFAULT = @bitCast(i32, @as(u32, 0x80000000));
362
363pub extern "user32" fn CreateWindowExA(dwExStyle: DWORD, lpClassName: [*:0]const u8, lpWindowName: [*:0]const u8, dwStyle: DWORD, X: i32, Y: i32, nWidth: i32, nHeight: i32, hWindParent: ?HWND, hMenu: ?HMENU, hInstance: HINSTANCE, lpParam: ?LPVOID) callconv(WINAPI) ?HWND;
364pub fn createWindowExA(dwExStyle: u32, lpClassName: [*:0]const u8, lpWindowName: [*:0]const u8, dwStyle: u32, X: i32, Y: i32, nWidth: i32, nHeight: i32, hWindParent: ?HWND, hMenu: ?HMENU, hInstance: HINSTANCE, lpParam: ?*c_void) !HWND {
365 const window = CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWindParent, hMenu, hInstance, lpParam);
366 if (window) |win| return win;
367
368 switch (GetLastError()) {
369 .CLASS_DOES_NOT_EXIST => return error.ClassDoesNotExist,
370 .INVALID_PARAMETER => unreachable,
371 else => |err| return windows.unexpectedError(err),
372 }
373}
374
375pub extern "user32" fn CreateWindowExW(dwExStyle: DWORD, lpClassName: [*:0]const u16, lpWindowName: [*:0]const u16, dwStyle: DWORD, X: i32, Y: i32, nWidth: i32, nHeight: i32, hWindParent: ?HWND, hMenu: ?HMENU, hInstance: HINSTANCE, lpParam: ?LPVOID) callconv(WINAPI) ?HWND;
376pub var pfnCreateWindowExW: @TypeOf(RegisterClassExW) = undefined;
377pub fn createWindowExW(dwExStyle: u32, lpClassName: [*:0]const u16, lpWindowName: [*:0]const u16, dwStyle: u32, X: i32, Y: i32, nWidth: i32, nHeight: i32, hWindParent: ?HWND, hMenu: ?HMENU, hInstance: HINSTANCE, lpParam: ?*c_void) !HWND {
378 const function = selectSymbol(CreateWindowExW, pfnCreateWindowExW, .win2k);
379 const window = function(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWindParent, hMenu, hInstance, lpParam);
380 if (window) |win| return win;
381
382 switch (GetLastError()) {
383 .CLASS_DOES_NOT_EXIST => return error.ClassDoesNotExist,
384 .INVALID_PARAMETER => unreachable,
385 else => |err| return windows.unexpectedError(err),
386 }
387}
388
389pub extern "user32" fn DestroyWindow(hWnd: HWND) callconv(WINAPI) BOOL;
390pub fn destroyWindow(hWnd: HWND) !void {
391 if (DestroyWindow(hWnd) == 0) {
392 switch (GetLastError()) {
393 .INVALID_WINDOW_HANDLE => unreachable,
394 .INVALID_PARAMETER => unreachable,
395 else => |err| return windows.unexpectedError(err),
396 }
397 }
398}
399
400pub const SW_HIDE = 0;
401pub const SW_SHOWNORMAL = 1;
402pub const SW_NORMAL = 1;
403pub const SW_SHOWMINIMIZED = 2;
404pub const SW_SHOWMAXIMIZED = 3;
405pub const SW_MAXIMIZE = 3;
406pub const SW_SHOWNOACTIVATE = 4;
407pub const SW_SHOW = 5;
408pub const SW_MINIMIZE = 6;
409pub const SW_SHOWMINNOACTIVE = 7;
410pub const SW_SHOWNA = 8;
411pub const SW_RESTORE = 9;
412pub const SW_SHOWDEFAULT = 10;
413pub const SW_FORCEMINIMIZE = 11;
414pub const SW_MAX = 11;
415
416pub extern "user32" fn ShowWindow(hWnd: HWND, nCmdShow: i32) callconv(WINAPI) BOOL;
417pub fn showWindow(hWnd: HWND, nCmdShow: i32) bool {
418 return (ShowWindow(hWnd, nCmdShow) == TRUE);
419}
420
421pub extern "user32" fn UpdateWindow(hWnd: HWND) callconv(WINAPI) BOOL;
422pub fn updateWindow(hWnd: HWND) !void {
423 if (ShowWindow(hWnd, nCmdShow) == 0) {
424 switch (GetLastError()) {
425 .INVALID_WINDOW_HANDLE => unreachable,
426 .INVALID_PARAMETER => unreachable,
427 else => |err| return windows.unexpectedError(err),
428 }
429 }
430}
431
432pub extern "user32" fn AdjustWindowRectEx(lpRect: *RECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD) callconv(WINAPI) BOOL;
433pub fn adjustWindowRectEx(lpRect: *RECT, dwStyle: u32, bMenu: bool, dwExStyle: u32) !void {
434 assert(dwStyle & WS_OVERLAPPED == 0);
435
436 if (AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle) == 0) {
437 switch (GetLastError()) {
438 .INVALID_PARAMETER => unreachable,
439 else => |err| return windows.unexpectedError(err),
440 }
441 }
442}
443
444pub const GWL_WNDPROC = -4;
445pub const GWL_HINSTANCE = -6;
446pub const GWL_HWNDPARENT = -8;
447pub const GWL_STYLE = -16;
448pub const GWL_EXSTYLE = -20;
449pub const GWL_USERDATA = -21;
450pub const GWL_ID = -12;
451
452pub extern "user32" fn GetWindowLongA(hWnd: HWND, nIndex: i32) callconv(WINAPI) LONG;
453pub fn getWindowLongA(hWnd: HWND, nIndex: i32) !i32 {
454 const value = GetWindowLongA(hWnd, nIndex);
455 if (value != 0) return value;
456
457 switch (GetLastError()) {
458 .SUCCESS => return 0,
459 .INVALID_WINDOW_HANDLE => unreachable,
460 .INVALID_PARAMETER => unreachable,
461 else => |err| return windows.unexpectedError(err),
462 }
463}
464
465pub extern "user32" fn GetWindowLongW(hWnd: HWND, nIndex: i32) callconv(WINAPI) LONG;
466pub var pfnGetWindowLongW: @TypeOf(GetWindowLongW) = undefined;
467pub fn getWindowLongW(hWnd: HWND, nIndex: i32) !i32 {
468 const function = selectSymbol(GetWindowLongW, pfnGetWindowLongW, .win2k);
469
470 const value = function(hWnd, nIndex);
471 if (value != 0) return value;
472
473 switch (GetLastError()) {
474 .SUCCESS => return 0,
475 .INVALID_WINDOW_HANDLE => unreachable,
476 .INVALID_PARAMETER => unreachable,
477 else => |err| return windows.unexpectedError(err),
478 }
479}
480
481pub extern "user32" fn GetWindowLongPtrA(hWnd: HWND, nIndex: i32) callconv(WINAPI) LONG_PTR;
482pub fn getWindowLongPtrA(hWnd: HWND, nIndex: i32) !isize {
483 // "When compiling for 32-bit Windows, GetWindowLongPtr is defined as a call to the GetWindowLong function."
484 // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
485 if (@sizeOf(LONG_PTR) == 4) return getWindowLongA(hWnd, nIndex);
486
487 const value = GetWindowLongPtrA(hWnd, nIndex);
488 if (value != 0) return value;
489
490 switch (GetLastError()) {
491 .SUCCESS => return 0,
492 .INVALID_WINDOW_HANDLE => unreachable,
493 .INVALID_PARAMETER => unreachable,
494 else => |err| return windows.unexpectedError(err),
495 }
496}
497
498pub extern "user32" fn GetWindowLongPtrW(hWnd: HWND, nIndex: i32) callconv(WINAPI) LONG_PTR;
499pub var pfnGetWindowLongPtrW: @TypeOf(GetWindowLongPtrW) = undefined;
500pub fn getWindowLongPtrW(hWnd: HWND, nIndex: i32) !isize {
501 if (@sizeOf(LONG_PTR) == 4) return getWindowLongW(hWnd, nIndex);
502 const function = selectSymbol(GetWindowLongPtrW, pfnGetWindowLongPtrW, .win2k);
503
504 const value = function(hWnd, nIndex);
505 if (value != 0) return value;
506
507 switch (GetLastError()) {
508 .SUCCESS => return 0,
509 .INVALID_WINDOW_HANDLE => unreachable,
510 .INVALID_PARAMETER => unreachable,
511 else => |err| return windows.unexpectedError(err),
512 }
513}
514
515pub extern "user32" fn SetWindowLongA(hWnd: HWND, nIndex: i32, dwNewLong: LONG) callconv(WINAPI) LONG;
516pub fn setWindowLongA(hWnd: HWND, nIndex: i32, dwNewLong: i32) !i32 {
517 // [...] you should clear the last error information by calling SetLastError with 0 before calling SetWindowLong.
518 // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga
519 SetLastError(.SUCCESS);
520
521 const value = SetWindowLongA(hWnd, nIndex, dwNewLong);
522 if (value != 0) return value;
523
524 switch (GetLastError()) {
525 .SUCCESS => return 0,
526 .INVALID_WINDOW_HANDLE => unreachable,
527 .INVALID_PARAMETER => unreachable,
528 else => |err| return windows.unexpectedError(err),
529 }
530}
531
532pub extern "user32" fn SetWindowLongW(hWnd: HWND, nIndex: i32, dwNewLong: LONG) callconv(WINAPI) LONG;
533pub var pfnSetWindowLongW: @TypeOf(SetWindowLongW) = undefined;
534pub fn setWindowLongW(hWnd: HWND, nIndex: i32, dwNewLong: i32) !i32 {
535 const function = selectSymbol(SetWindowLongW, pfnSetWindowLongW, .win2k);
536
537 SetLastError(.SUCCESS);
538 const value = function(hWnd, nIndex, dwNewLong);
539 if (value != 0) return value;
540
541 switch (GetLastError()) {
542 .SUCCESS => return 0,
543 .INVALID_WINDOW_HANDLE => unreachable,
544 .INVALID_PARAMETER => unreachable,
545 else => |err| return windows.unexpectedError(err),
546 }
547}
548
549pub extern "user32" fn SetWindowLongPtrA(hWnd: HWND, nIndex: i32, dwNewLong: LONG_PTR) callconv(WINAPI) LONG_PTR;
550pub fn setWindowLongPtrA(hWnd: HWND, nIndex: i32, dwNewLong: isize) !isize {
551 // "When compiling for 32-bit Windows, GetWindowLongPtr is defined as a call to the GetWindowLong function."
552 // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
553 if (@sizeOf(LONG_PTR) == 4) return setWindowLongA(hWnd, nIndex, dwNewLong);
554
555 SetLastError(.SUCCESS);
556 const value = SetWindowLongPtrA(hWnd, nIndex, dwNewLong);
557 if (value != 0) return value;
558
559 switch (GetLastError()) {
560 .SUCCESS => return 0,
561 .INVALID_WINDOW_HANDLE => unreachable,
562 .INVALID_PARAMETER => unreachable,
563 else => |err| return windows.unexpectedError(err),
564 }
565}
566
567pub extern "user32" fn SetWindowLongPtrW(hWnd: HWND, nIndex: i32, dwNewLong: LONG_PTR) callconv(WINAPI) LONG_PTR;
568pub var pfnSetWindowLongPtrW: @TypeOf(SetWindowLongPtrW) = undefined;
569pub fn setWindowLongPtrW(hWnd: HWND, nIndex: i32, dwNewLong: isize) !isize {
570 if (@sizeOf(LONG_PTR) == 4) return setWindowLongW(hWnd, nIndex, dwNewLong);
571 const function = selectSymbol(SetWindowLongPtrW, pfnSetWindowLongPtrW, .win2k);
572
573 SetLastError(.SUCCESS);
574 const value = function(hWnd, nIndex, dwNewLong);
575 if (value != 0) return value;
576
577 switch (GetLastError()) {
578 .SUCCESS => return 0,
579 .INVALID_WINDOW_HANDLE => unreachable,
580 .INVALID_PARAMETER => unreachable,
581 else => |err| return windows.unexpectedError(err),
582 }
583}
151584
152pub extern "user32" fn RegisterClassExA(*const WNDCLASSEXA) callconv(WINAPI) c_ushort;
153pub extern "user32" fn DefWindowProcA(HWND, Msg: UINT, WPARAM, LPARAM) callconv(WINAPI) LRESULT;
154pub extern "user32" fn ShowWindow(hWnd: ?HWND, nCmdShow: i32) callconv(WINAPI) bool;
155pub extern "user32" fn UpdateWindow(hWnd: ?HWND) callconv(WINAPI) bool;
156585pub extern "user32" fn GetDC(hWnd: ?HWND) callconv(WINAPI) ?HDC;
586pub fn getDC(hWnd: ?HWND) !HDC {
587 const hdc = GetDC(hWnd);
588 if (hdc) |h| return h;
157589
158pub extern "user32" fn PeekMessageA(
159 lpMsg: ?*MSG,
160 hWnd: ?HWND,
161 wMsgFilterMin: UINT,
162 wMsgFilterMax: UINT,
163 wRemoveMsg: UINT,
164) callconv(WINAPI) bool;
590 switch (GetLastError()) {
591 .INVALID_WINDOW_HANDLE => unreachable,
592 .INVALID_PARAMETER => unreachable,
593 else => |err| return windows.unexpectedError(err),
594 }
595}
165596
166pub extern "user32" fn GetMessageA(
167 lpMsg: ?*MSG,
168 hWnd: ?HWND,
169 wMsgFilterMin: UINT,
170 wMsgFilterMax: UINT,
171) callconv(WINAPI) bool;
597pub extern "user32" fn ReleaseDC(hWnd: ?HWND, hDC: HDC) callconv(WINAPI) i32;
598pub fn releaseDC(hWnd: ?HWND, hDC: HDC) bool {
599 return if (ReleaseDC(hWnd, hDC) == 1) true else false;
600}
172601
173pub extern "user32" fn TranslateMessage(lpMsg: *const MSG) callconv(WINAPI) bool;
174pub extern "user32" fn DispatchMessageA(lpMsg: *const MSG) callconv(WINAPI) LRESULT;
175pub extern "user32" fn PostQuitMessage(nExitCode: i32) callconv(WINAPI) void;
602// === Modal dialogue boxes ===
603
604pub const MB_OK = 0x00000000;
605pub const MB_OKCANCEL = 0x00000001;
606pub const MB_ABORTRETRYIGNORE = 0x00000002;
607pub const MB_YESNOCANCEL = 0x00000003;
608pub const MB_YESNO = 0x00000004;
609pub const MB_RETRYCANCEL = 0x00000005;
610pub const MB_CANCELTRYCONTINUE = 0x00000006;
611pub const MB_ICONHAND = 0x00000010;
612pub const MB_ICONQUESTION = 0x00000020;
613pub const MB_ICONEXCLAMATION = 0x00000030;
614pub const MB_ICONASTERISK = 0x00000040;
615pub const MB_USERICON = 0x00000080;
616pub const MB_ICONWARNING = MB_ICONEXCLAMATION;
617pub const MB_ICONERROR = MB_ICONHAND;
618pub const MB_ICONINFORMATION = MB_ICONASTERISK;
619pub const MB_ICONSTOP = MB_ICONHAND;
620pub const MB_DEFBUTTON1 = 0x00000000;
621pub const MB_DEFBUTTON2 = 0x00000100;
622pub const MB_DEFBUTTON3 = 0x00000200;
623pub const MB_DEFBUTTON4 = 0x00000300;
624pub const MB_APPLMODAL = 0x00000000;
625pub const MB_SYSTEMMODAL = 0x00001000;
626pub const MB_TASKMODAL = 0x00002000;
627pub const MB_HELP = 0x00004000;
628pub const MB_NOFOCUS = 0x00008000;
629pub const MB_SETFOREGROUND = 0x00010000;
630pub const MB_DEFAULT_DESKTOP_ONLY = 0x00020000;
631pub const MB_TOPMOST = 0x00040000;
632pub const MB_RIGHT = 0x00080000;
633pub const MB_RTLREADING = 0x00100000;
634pub const MB_TYPEMASK = 0x0000000F;
635pub const MB_ICONMASK = 0x000000F0;
636pub const MB_DEFMASK = 0x00000F00;
637pub const MB_MODEMASK = 0x00003000;
638pub const MB_MISCMASK = 0x0000C000;
639
640pub const IDOK = 1;
641pub const IDCANCEL = 2;
642pub const IDABORT = 3;
643pub const IDRETRY = 4;
644pub const IDIGNORE = 5;
645pub const IDYES = 6;
646pub const IDNO = 7;
647pub const IDCLOSE = 8;
648pub const IDHELP = 9;
649pub const IDTRYAGAIN = 10;
650pub const IDCONTINUE = 11;
651
652pub extern "user32" fn MessageBoxA(hWnd: ?HWND, lpText: [*:0]const u8, lpCaption: [*:0]const u8, uType: UINT) callconv(WINAPI) i32;
653pub fn messageBoxA(hWnd: ?HWND, lpText: [*:0]const u8, lpCaption: [*:0]const u8, uType: u32) !i32 {
654 const value = MessageBoxA(hWnd, lpText, lpCaption, uType);
655 if (value != 0) return value;
656 switch (GetLastError()) {
657 .INVALID_WINDOW_HANDLE => unreachable,
658 .INVALID_PARAMETER => unreachable,
659 else => |err| return windows.unexpectedError(err),
660 }
661}
662
663pub extern "user32" fn MessageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: ?[*:0]const u16, uType: UINT) callconv(WINAPI) i32;
664pub var pfnMessageBoxW: @TypeOf(MessageBoxW) = undefined;
665pub fn messageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: [*:0]const u16, uType: u32) !i32 {
666 const function = selectSymbol(pfnMessageBoxW, MessageBoxW, .win2k);
667 const value = function(hWnd, lpText, lpCaption, uType);
668 if (value != 0) return value;
669 switch (GetLastError()) {
670 .INVALID_WINDOW_HANDLE => unreachable,
671 .INVALID_PARAMETER => unreachable,
672 else => |err| return windows.unexpectedError(err),
673 }
674}