2 * Unit tests for window message handling
4 * Copyright 1999 Ove Kaaven
5 * Copyright 2003 Dimitrie O. Paun
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "wine/test.h"
36 FIXME: add tests for these
37 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
38 WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
39 WS_THICKFRAME: thick border
40 WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
41 WS_BORDER (default for overlapped windows): single black border
42 none (default for child (and popup?) windows): no border
46 sent
=0x1, posted
=0x2, parent
=0x4, wparam
=0x8, lparam
=0x10,
51 UINT message
; /* the WM_* code */
52 msg_flags_t flags
; /* message props */
53 WPARAM wParam
; /* expacted value of wParam */
54 LPARAM lParam
; /* expacted value of lParam */
57 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
58 static struct message WmCreateOverlappedSeq
[] = {
59 { WM_GETMINMAXINFO
, sent
},
60 { WM_NCCREATE
, sent
},
61 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
65 /* ShowWindow (for overlapped window) (16/32) */
66 static struct message WmShowOverlappedSeq
[] = {
67 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
68 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*FIXME: SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW*/ 0 },
69 /* FIXME: WM_QUERYNEWPALETTE, if in 256-color mode */
70 { WM_WINDOWPOSCHANGING
, sent
|wparam
, /*FIXME: SWP_NOMOVE|SWP_NOSIZE*/ 0 },
71 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
72 { WM_NCACTIVATE
, sent
|wparam
, 1 },
73 { WM_GETTEXT
, sent
|defwinproc
},
74 { WM_ACTIVATE
, sent
|wparam
, 1 },
75 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
76 { WM_NCPAINT
, sent
|wparam
, 1 },
77 { WM_GETTEXT
, sent
|defwinproc
},
78 { WM_ERASEBKGND
, sent
},
79 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_SHOWWINDOW
},
85 /* DestroyWindow (for overlapped window) (32) */
86 static struct message WmDestroyOverlappedSeq
[] = {
87 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
88 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
89 { WM_NCACTIVATE
, sent
|wparam
, 0 },
90 { WM_ACTIVATE
, sent
|wparam
, 0 },
91 { WM_ACTIVATEAPP
, sent
|wparam
, 0 },
92 { WM_KILLFOCUS
, sent
|wparam
, 0 },
94 { WM_NCDESTROY
, sent
},
97 /* CreateWindow (for child window, not initially visible) */
98 static struct message WmCreateChildSeq
[] = {
99 { WM_NCCREATE
, sent
},
100 /* child is inserted into parent's child list after WM_NCCREATE returns */
101 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
105 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, 1 },
108 /* ShowWindow (for child window) */
109 static struct message WmShowChildSeq
[] = {
110 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
111 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
112 { WM_ERASEBKGND
, sent
|parent
},
113 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
116 /* DestroyWindow (for child window) */
117 static struct message WmDestroyChildSeq
[] = {
118 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, 2 },
119 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
120 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
121 { WM_ERASEBKGND
, sent
|parent
},
122 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
123 { WM_DESTROY
, sent
},
124 { WM_NCDESTROY
, sent
},
127 /* Moving the mouse in nonclient area */
128 static struct message WmMouseMoveInNonClientAreaSeq
[] = { /* FIXME: add */
129 { WM_NCHITTEST
, sent
},
130 { WM_SETCURSOR
, sent
},
131 { WM_NCMOUSEMOVE
, posted
},
134 /* Moving the mouse in client area */
135 static struct message WmMouseMoveInClientAreaSeq
[] = { /* FIXME: add */
136 { WM_NCHITTEST
, sent
},
137 { WM_SETCURSOR
, sent
},
138 { WM_MOUSEMOVE
, posted
},
141 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
142 static struct message WmDragTitleBarSeq
[] = { /* FIXME: add */
143 { WM_NCLBUTTONDOWN
, sent
|wparam
, HTCAPTION
},
144 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, SC_MOVE
+2 },
145 { WM_GETMINMAXINFO
, sent
|defwinproc
},
146 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
147 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
148 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
149 { WM_MOVE
, sent
|defwinproc
},
150 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
153 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
154 static struct message WmDragThinkBordersBarSeq
[] = { /* FIXME: add */
155 { WM_NCLBUTTONDOWN
, sent
|wparam
, 0xd },
156 { WM_SYSCOMMAND
, sent
|defwinproc
|wparam
, 0xf004 },
157 { WM_GETMINMAXINFO
, sent
|defwinproc
},
158 { WM_ENTERSIZEMOVE
, sent
|defwinproc
},
159 { WM_SIZING
, sent
|defwinproc
|wparam
, 4}, /* one for each mouse movement */
160 { WM_WINDOWPOSCHANGING
, sent
|defwinproc
},
161 { WM_GETMINMAXINFO
, sent
|defwinproc
},
162 { WM_NCCALCSIZE
, sent
|defwinproc
|wparam
, 1 },
163 { WM_NCPAINT
, sent
|defwinproc
|wparam
, 1 },
164 { WM_GETTEXT
, sent
|defwinproc
},
165 { WM_ERASEBKGND
, sent
|defwinproc
},
166 { WM_WINDOWPOSCHANGED
, sent
|defwinproc
},
167 { WM_MOVE
, sent
|defwinproc
},
168 { WM_SIZE
, sent
|defwinproc
},
169 { WM_EXITSIZEMOVE
, sent
|defwinproc
},
172 /* Resizing child window with MoveWindow (32) */
173 static struct message WmResizingChildWithMoveWindowSeq
[] = {
174 { WM_WINDOWPOSCHANGING
, sent
},
175 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
176 { WM_ERASEBKGND
, sent
},
177 { WM_WINDOWPOSCHANGED
, sent
},
178 { WM_MOVE
, sent
|defwinproc
},
179 { WM_SIZE
, sent
|defwinproc
},
182 /* Clicking on inactive button */
183 static struct message WmClickInactiveButtonSeq
[] = { /* FIXME: add */
184 { WM_NCHITTEST
, sent
},
185 { WM_PARENTNOTIFY
, sent
|parent
|wparam
, WM_LBUTTONDOWN
},
186 { WM_MOUSEACTIVATE
, sent
},
187 { WM_MOUSEACTIVATE
, sent
|parent
|defwinproc
},
188 { WM_SETCURSOR
, sent
},
189 { WM_SETCURSOR
, sent
|parent
|defwinproc
},
190 { WM_LBUTTONDOWN
, posted
},
191 { WM_KILLFOCUS
, posted
|parent
},
192 { WM_SETFOCUS
, posted
},
193 { WM_CTLCOLORBTN
, posted
|parent
},
194 { BM_SETSTATE
, posted
},
195 { WM_CTLCOLORBTN
, posted
|parent
},
196 { WM_LBUTTONUP
, posted
},
197 { BM_SETSTATE
, posted
},
198 { WM_CTLCOLORBTN
, posted
|parent
},
199 { WM_COMMAND
, posted
|parent
},
202 /* Reparenting a button (16/32) */
203 /* The last child (button) reparented gets topmost for its new parent. */
204 static struct message WmReparentButtonSeq
[] = { /* FIXME: add */
205 { WM_SHOWWINDOW
, sent
|wparam
, 0 },
206 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
207 { WM_ERASEBKGND
, sent
|parent
},
208 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_HIDEWINDOW
|SWP_NOACTIVATE
|SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
},
209 { WM_WINDOWPOSCHANGING
, sent
|wparam
, SWP_NOSIZE
|SWP_NOZORDER
},
210 { WM_CHILDACTIVATE
, sent
},
211 { WM_WINDOWPOSCHANGED
, sent
|wparam
, SWP_NOSIZE
|SWP_NOREDRAW
|SWP_NOZORDER
},
212 { WM_MOVE
, sent
|defwinproc
},
213 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
216 /* Creation of a modal dialog (32) */
217 static struct message WmCreateModalDialogSeq
[] = { /* FIXME: add */
218 { WM_CANCELMODE
, sent
|parent
},
219 { WM_KILLFOCUS
, sent
|parent
},
220 { WM_ENABLE
, sent
|parent
|wparam
, 0 },
221 /* (window proc creation messages not tracked yet, because...) */
222 { WM_SETFONT
, sent
},
223 { WM_INITDIALOG
, sent
},
224 /* (...the window proc message hook was installed here, IsVisible still FALSE) */
225 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
226 { WM_GETTEXT
, sent
|defwinproc
},
227 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
228 { WM_WINDOWPOSCHANGING
, sent
},
229 { WM_WINDOWPOSCHANGING
, sent
|parent
},
230 { WM_NCACTIVATE
, sent
|wparam
, 1 },
231 { WM_ACTIVATE
, sent
|wparam
, 1 },
232 /* (setting focus) */
233 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
234 { WM_WINDOWPOSCHANGING
, sent
},
235 { WM_NCPAINT
, sent
},
236 { WM_GETTEXT
, sent
|defwinproc
},
237 { WM_ERASEBKGND
, sent
},
238 { WM_CTLCOLORDLG
, sent
|defwinproc
},
239 { WM_WINDOWPOSCHANGED
, sent
},
241 /* FIXME: (bunch of WM_CTLCOLOR* for each control) */
242 { WM_PAINT
, sent
|parent
},
243 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0},
244 { WM_SETCURSOR
, sent
|parent
},
247 /* Destruction of a modal dialog (32) */
248 static struct message WmDestroyModalDialogSeq
[] = { /* FIXME: add */
249 /* (inside dialog proc: EndDialog is called) */
250 { WM_ENABLE
, sent
|parent
|wparam
, 1 },
251 { WM_SETFOCUS
, sent
},
252 { WM_WINDOWPOSCHANGING
, sent
},
253 { WM_NCPAINT
, sent
|parent
},
254 { WM_GETTEXT
, sent
|defwinproc
},
255 { WM_ERASEBKGND
, sent
|parent
},
256 { WM_WINDOWPOSCHANGED
, sent
},
257 { WM_NCACTIVATE
, sent
|wparam
, 0 },
258 { WM_ACTIVATE
, sent
|wparam
, 0 },
259 { WM_WINDOWPOSCHANGING
, sent
},
260 { WM_WINDOWPOSCHANGING
, sent
|parent
},
261 { WM_NCACTIVATE
, sent
|parent
|wparam
, 1 },
262 { WM_GETTEXT
, sent
|defwinproc
},
263 { WM_ACTIVATE
, sent
|parent
|wparam
, 1 },
264 { WM_KILLFOCUS
, sent
},
265 { WM_SETFOCUS
, sent
|parent
},
266 { WM_DESTROY
, sent
},
267 { WM_NCDESTROY
, sent
},
270 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
271 static struct message WmCreateModalDialogResizeSeq
[] = { /* FIXME: add */
272 /* (inside dialog proc, handling WM_INITDIALOG) */
273 { WM_WINDOWPOSCHANGING
, sent
},
274 { WM_NCCALCSIZE
, sent
},
275 { WM_NCACTIVATE
, sent
|parent
|wparam
, 0 },
276 { WM_GETTEXT
, sent
|defwinproc
},
277 { WM_ACTIVATE
, sent
|parent
|wparam
, 0 },
278 { WM_WINDOWPOSCHANGING
, sent
},
279 { WM_WINDOWPOSCHANGING
, sent
|parent
},
280 { WM_NCACTIVATE
, sent
|wparam
, 1 },
281 { WM_ACTIVATE
, sent
|wparam
, 1 },
282 { WM_WINDOWPOSCHANGED
, sent
},
283 { WM_SIZE
, sent
|defwinproc
},
284 /* (setting focus) */
285 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
286 { WM_WINDOWPOSCHANGING
, sent
},
287 { WM_NCPAINT
, sent
},
288 { WM_GETTEXT
, sent
|defwinproc
},
289 { WM_ERASEBKGND
, sent
},
290 { WM_CTLCOLORDLG
, sent
|defwinproc
},
291 { WM_WINDOWPOSCHANGED
, sent
},
293 /* (bunch of WM_CTLCOLOR* for each control) */
294 { WM_PAINT
, sent
|parent
},
295 { WM_ENTERIDLE
, sent
|parent
|wparam
, 0 },
296 { WM_SETCURSOR
, sent
|parent
},
299 /* SetMenu for NonVisible windows with size change*/
300 static struct message WmSetMenuNonVisibleSizeChangeSeq
[] = {
301 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
302 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
303 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
308 /* SetMenu for NonVisible windows with no size change */
309 static struct message WmSetMenuNonVisibleNoSizeChangeSeq
[] = {
310 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
311 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
312 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
315 /* SetMenu for Visible windows with size change */
316 static struct message WmSetMenuVisibleSizeChangeSeq
[] = {
317 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
318 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
319 { WM_NCPAINT
, sent
|wparam
, 1 },
320 { WM_GETTEXT
, sent
},
321 { WM_ACTIVATE
, sent
},
322 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
327 /* SetMenu for Visible windows with no size change */
328 static struct message WmSetMenuVisibleNoSizeChangeSeq
[] = {
329 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
330 { WM_NCCALCSIZE
, sent
|wparam
, 1 },
331 { WM_NCPAINT
, sent
|wparam
, 1 },
332 { WM_GETTEXT
, sent
},
333 { WM_ACTIVATE
, sent
},
334 { WM_WINDOWPOSCHANGED
, sent
|wparam
, 0 },
338 static int sequence_cnt
, sequence_size
;
339 static struct message
* sequence
;
341 static void add_message(struct message msg
)
344 sequence
= malloc ( (sequence_size
= 10) * sizeof (struct message
) );
345 if (sequence_cnt
== sequence_size
)
346 sequence
= realloc ( sequence
, (sequence_size
*= 2) * sizeof (struct message
) );
348 sequence
[sequence_cnt
++] = msg
;
351 static void flush_sequence()
355 sequence_cnt
= sequence_size
= 0;
358 static void ok_sequence(struct message
*expected
, const char *context
)
360 static struct message end_of_sequence
= { 0, 0, 0, 0 };
361 struct message
*actual
= sequence
;
363 add_message(end_of_sequence
);
365 /* naive sequence comparison. Would be nice to use a regexp engine here */
366 while (expected
->message
|| actual
->message
)
368 if (expected
->message
== actual
->message
)
370 if (expected
->flags
& wparam
)
371 ok (expected
->wParam
== actual
->wParam
,
372 "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
373 context
, expected
->message
, expected
->wParam
, actual
->wParam
);
374 if (expected
->flags
& lparam
)
375 ok (expected
->lParam
== actual
->lParam
,
376 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
377 context
, expected
->message
, expected
->lParam
, actual
->lParam
);
378 /* FIXME: should we check defwinproc? */
379 ok ((expected
->flags
& (sent
|posted
)) == (actual
->flags
& (sent
|posted
)),
380 "%s: the msg 0x%04x should have been %s\n",
381 context
, expected
->message
, (expected
->flags
& posted
) ? "posted" : "sent");
382 ok ((expected
->flags
& parent
) == (actual
->flags
& parent
),
383 "%s: the msg 0x%04x was expected in %s\n",
384 context
, expected
->message
, (expected
->flags
& parent
) ? "parent" : "child");
388 else if (expected
->message
&& ((expected
+ 1)->message
== actual
->message
) )
391 ok (FALSE
, "%s: the msg 0x%04x was not received\n", context
, expected
->message
);
395 else if (actual
->message
&& (expected
->message
== (actual
+ 1)->message
) )
398 ok (FALSE
, "%s: the msg 0x%04x was not expected\n", context
, actual
->message
);
405 ok (FALSE
, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
406 context
, expected
->message
, actual
->message
);
416 /* test if we receive the right sequence of messages */
417 static void test_messages(void)
419 HWND hwnd
, hparent
, hchild
;
420 HWND hchild2
, hbutton
;
423 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
424 100, 100, 200, 200, 0, 0, 0, NULL
);
425 ok (hwnd
!= 0, "Failed to create overlapped window\n");
426 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped");
428 ShowWindow(hwnd
, TRUE
);
429 ok_sequence(WmShowOverlappedSeq
, "ShowWindow:overlapped");
432 ok_sequence(WmDestroyOverlappedSeq
, "DestroyWindow:overlapped");
434 hparent
= CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW
,
435 100, 100, 200, 200, 0, 0, 0, NULL
);
436 ok (hparent
!= 0, "Failed to create parent window\n");
439 hchild
= CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW
,
440 0, 0, 10, 10, hparent
, 0, 0, NULL
);
441 ok (hchild
!= 0, "Failed to create child window\n");
442 ok_sequence(WmCreateChildSeq
, "CreateWindow:child");
444 hchild2
= CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILDWINDOW
,
445 100, 100, 50, 50, hparent
, 0, 0, NULL
);
446 ok (hchild2
!= 0, "Failed to create child2 window\n");
449 hbutton
= CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW
,
450 0, 100, 50, 50, hchild
, 0, 0, NULL
);
451 ok (hbutton
!= 0, "Failed to create button window\n");
454 ShowWindow(hchild
, TRUE
);
455 ok_sequence(WmShowChildSeq
, "ShowWindow:child");
457 MoveWindow(hchild
, 10, 10, 20, 20, TRUE
);
458 ok_sequence(WmResizingChildWithMoveWindowSeq
, "MoveWindow:child");
460 DestroyWindow(hchild
);
461 ok_sequence(WmDestroyChildSeq
, "DestroyWindow:child");
462 DestroyWindow(hchild2
);
463 DestroyWindow(hbutton
);
464 DestroyWindow(hparent
);
467 /* Message sequence for SetMenu */
468 hmenu
= CreateMenu();
469 ok (hmenu
!= 0, "Failed to create menu\n");
470 ok (InsertMenuA(hmenu
, -1, MF_BYPOSITION
, 0x1000, "foo"), "InsertMenu failed\n");
471 hwnd
= CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW
,
472 100, 100, 200, 200, 0, hmenu
, 0, NULL
);
473 ok_sequence(WmCreateOverlappedSeq
, "CreateWindow:overlapped");
474 ok (SetMenu(hwnd
, 0), "SetMenu");
475 ok_sequence(WmSetMenuNonVisibleSizeChangeSeq
, "SetMenu:NonVisibleSizeChange");
476 ok (SetMenu(hwnd
, 0), "SetMenu");
477 ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq
, "SetMenu:NonVisibleNoSizeChange");
478 ShowWindow(hwnd
, TRUE
);
480 ok (SetMenu(hwnd
, 0), "SetMenu");
481 ok_sequence(WmSetMenuVisibleNoSizeChangeSeq
, "SetMenu:VisibleNoSizeChange");
482 ok (SetMenu(hwnd
, hmenu
), "SetMenu");
483 ok_sequence(WmSetMenuVisibleSizeChangeSeq
, "SetMenu:VisibleSizeChange");
488 static LRESULT WINAPI
MsgCheckProcA(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
490 struct message msg
= { message
, sent
|wparam
|lparam
, wParam
, lParam
};
493 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
496 static BOOL
RegisterWindowClasses(void)
501 cls
.lpfnWndProc
= MsgCheckProcA
;
504 cls
.hInstance
= GetModuleHandleA(0);
506 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
507 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
508 cls
.lpszMenuName
= NULL
;
509 cls
.lpszClassName
= "TestWindowClass";
511 if(!RegisterClassA(&cls
)) return FALSE
;
514 cls
.lpfnWndProc
= DefWindowProcA
;
517 cls
.hInstance
= GetModuleHandleA(0);
519 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
520 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
521 cls
.lpszMenuName
= NULL
;
522 cls
.lpszClassName
= "TestParentClass";
524 if(!RegisterClassA(&cls
)) return FALSE
;
527 cls
.lpfnWndProc
= DefWindowProcA
;
530 cls
.hInstance
= GetModuleHandleA(0);
532 cls
.hCursor
= LoadCursorA(0, (LPSTR
)IDC_ARROW
);
533 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
534 cls
.lpszMenuName
= NULL
;
535 cls
.lpszClassName
= "SimpleWindowClass";
537 if(!RegisterClassA(&cls
)) return FALSE
;
544 if (!RegisterWindowClasses()) assert(0);