1 /* Windows GUI Behaviour Tester */
11 /* checks to include */
12 #define LOGGING /* can be undefined under Wine and use -debugmsg +message instead */
13 #define MAIN_STYLE WS_OVERLAPPEDWINDOW
14 #undef TEST_DESTROY_MAIN
21 /************************/
22 /*** GLOBAL VARIABLES ***/
23 /************************/
27 HWND hListBox
,hMainWnd
,hSubWnd
;
28 HWND hButton
[4]={0,0,0,0};
29 HWND hDialog
=0,hGroup
=0,hSubDlg
=0;
30 WNDPROC wndButton
[4],wndDialog
,wndGroup
,wndSubDlg
;
31 BOOL Clicked
=0,Ready
=0;
33 #define STATE_CREATE 0
34 #define STATE_DESTROY 1
36 #define STATE_UPDATE 3
37 #define STATE_DIALOG 4
39 #define STATE_DIRECT 6
40 #define STATE_DISPATCH 7
41 #define STATE_RECURS 8
54 static char wclassname
[] = "GUITestClass";
55 static char wcclassname
[] = "GUITestChildClass";
56 static char winname
[] = "GUITest";
58 /**************************/
59 /*** LOGGING FACILITIES ***/
60 /**************************/
66 #define MSG(x) {x,#x},
67 #define MSG2(x,y) {y,#x},
70 /* we get these in CreateWindow */
77 /* we get these in ShowWindow */
79 MSG(WM_WINDOWPOSCHANGING
)
80 MSG(WM_QUERYNEWPALETTE
)
88 MSG(WM_WINDOWPOSCHANGED
)
92 /* we get these in DestroyWindow */
97 /* we get these directly sent */
100 MSG(WM_MOUSEACTIVATE
)
101 MSG(WM_CHILDACTIVATE
)
111 MSG(WM_NCLBUTTONDOWN
)
121 MSG(WM_CTLCOLORSTATIC
)
126 /* moving and sizing */
127 MSG2(WM_ENTERSIZEMOVE
,0x0231)
128 MSG2(WM_EXITSIZEMOVE
,0x0232)
133 /* menus/dialog boxes */
141 /* getting these from Wine but not from Windows */
142 MSG2(WM_SETVISIBLE
,0x0009) /* unheard of in BC++ 4.52 */
144 MSG(WM_CAPTURECHANGED
)
149 struct MSGNAMES ButMsgs
[]={
155 char*MsgName(UINT msg
,HWND hWnd
)
158 static char buffer
[64],wclass
[64];
159 GetClassName(hWnd
,wclass
,sizeof(wclass
));
161 #define MSGSEARCH(msgs) { \
162 for (i=0; msgs[i].name&&msgs[i].msg!=msg; i++); \
163 if (msgs[i].name) return msgs[i].name; \
166 if (!stricmp(wclass
,"Button")) MSGSEARCH(ButMsgs
);
170 sprintf(buffer
,"WM_USER+%04x{%s}",msg
-WM_USER
,wclass
);
173 /* message not found */
174 sprintf(buffer
,"%04x{%s}",msg
,wclass
);
178 char*WndName(HWND hWnd
,int state
=State
)
180 static char buffer
[16];
181 if (!hWnd
) return "0000";
182 if (hWnd
==hMainWnd
|| (state
==STATE_CREATE
&& !hMainWnd
)) return "main";
183 if (hWnd
==hSubWnd
|| (state
==STATE_CREATE
&& !hSubWnd
)) return "chld";
184 if (hWnd
==hDialog
|| (state
==STATE_DIALOG
&& !hDialog
)) return "tdlg";
185 if (hWnd
==hGroup
) return "tgrp";
186 if (hWnd
==hButton
[0]) return "but1";
187 if (hWnd
==hButton
[1]) return "but2";
188 if (hWnd
==hButton
[2]) return "but3";
189 if (hWnd
==hButton
[3]) return "but4";
190 if (hWnd
==hSubDlg
|| (state
==STATE_CREATE
&& !hSubDlg
)) return "sdlg";
192 int id
=GetDlgCtrlID(hWnd
);
194 sprintf(buffer
,"dlgitem(%d)",id
);
198 sprintf(buffer
,"%04x",hWnd
);
202 void Log(const char*fmt
)
205 if (!Clicked
) SendMessage(hListBox
,LB_ADDSTRING
,0,(LPARAM
)fmt
);
209 void Logf(const char*fmt
,...)
212 static char buffer
[256];
215 vsprintf(buffer
,fmt
,par
);
220 void LogChildOrder(HWND hWnd
)
222 HWND hWndChild
= GetWindow(hWnd
,GW_CHILD
);
224 static char buffer
[256];
226 strcpy(buffer
,"child list:");
228 strcat(strcat(buffer
," "),WndName(hWndChild
));
229 hWndChild
=GetWindow(hWndChild
,GW_HWNDNEXT
);
234 void LogMessage(int state
,HWND hWnd
,UINT msg
,WPARAM wParam
,LPARAM lParam
,char*name
=NULL
)
236 static char buffer
[256];
237 DWORD tick
=GetTickCount()-StartTime
;
238 char*msgname
=MsgName(msg
,hWnd
);
239 if (!name
) name
=WndName(hWnd
,state
);
244 Logf("%04d[%s(%d):%s]%s(%s,%08x)",tick
,StateName
[state
],Rec
,
245 name
,msgname
,WndName((HWND
)wParam
),lParam
);
251 Logf("%04d[%s(%d):%s]%s(%08x,%s)",tick
,StateName
[state
],Rec
,
252 name
,msgname
,wParam
,WndName((HWND
)lParam
));
257 Logf("%04d[%s(%d):%s]%s(%08x,%04x:%s)",tick
,StateName
[state
],Rec
,
258 name
,msgname
,wParam
,HIWORD(lParam
),WndName((HWND
)LOWORD(lParam
)));
261 case WM_WINDOWPOSCHANGING
:
262 case WM_WINDOWPOSCHANGED
:
264 WINDOWPOS
*pos
=(WINDOWPOS
*)lParam
;
266 Logf("%04d[%s(%d):%s]%s(%08x,%p)",tick
,StateName
[state
],Rec
,
267 name
,msgname
,wParam
,pos
);
269 Logf("%04d[%s(%d):%s]%s(%04x,%p)",tick
,StateName
[state
],Rec
,
270 name
,msgname
,wParam
,pos
);
272 strcpy(buffer
,"FLAGS:");
273 if (pos
->flags
&SWP_DRAWFRAME
) strcat(buffer
," DRAWFRAME");
274 if (pos
->flags
&SWP_HIDEWINDOW
) strcat(buffer
," HIDEWINDOW");
275 if (pos
->flags
&SWP_NOACTIVATE
) strcat(buffer
," NOACTIVATE");
276 if (pos
->flags
&SWP_NOCOPYBITS
) strcat(buffer
," NOCOPYBITS");
277 if (pos
->flags
&SWP_NOMOVE
) strcat(buffer
," NOMOVE");
278 if (pos
->flags
&SWP_NOOWNERZORDER
) strcat(buffer
," NOOWNERZORDER");
279 if (pos
->flags
&SWP_NOSIZE
) strcat(buffer
," NOSIZE");
280 if (pos
->flags
&SWP_NOREDRAW
) strcat(buffer
," NOREDRAW");
281 if (pos
->flags
&SWP_NOZORDER
) strcat(buffer
," NOZORDER");
282 if (pos
->flags
&SWP_SHOWWINDOW
) strcat(buffer
," SHOWWINDOW");
288 Logf("%04d[%s(%d):%s]%s(%08x,%08x)",tick
,StateName
[state
],Rec
,
289 name
,msgname
,wParam
,lParam
);
291 Logf("%04d[%s(%d):%s]%s(%04x,%08x)",tick
,StateName
[state
],Rec
,
292 name
,msgname
,wParam
,lParam
);
297 /***************************/
298 /*** GRAPHICS FACILITIES ***/
299 /***************************/
301 void Paint(HWND hWnd
)
305 dc
=BeginPaint(hWnd
,&ps
);
309 void FillPattern(HWND hWnd
,HDC pdc
=0)
311 HDC dc
=pdc
?pdc
:GetDC(hWnd
);
315 Logf("failed to acquire DC for window %s",WndName(hWnd
));
318 Logf("acquired DC for %s window %s, painting",
319 IsWindowVisible(hWnd
)?"visible":"invisible",WndName(hWnd
));
321 GetClientRect(hWnd
,&rect
);
322 oldbrush
=SelectObject(dc
,GetStockObject(LTGRAY_BRUSH
));
323 PatBlt(dc
,0,0,rect
.right
,rect
.bottom
,PATCOPY
);
324 SelectObject(dc
,oldbrush
);
325 if (!pdc
) ReleaseDC(hWnd
,dc
);
328 void PaintPattern(HWND hWnd
)
332 dc
=BeginPaint(hWnd
,&ps
);
333 FillPattern(hWnd
,dc
);
337 /*************************/
338 /*** WINDOW PROCEDURES ***/
339 /*************************/
342 LRESULT FAR CALLBACK _export
MainWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
348 State
=STATE_RECURS
; Rec
++;
349 if (!Clicked
) LogMessage(OldState
,hWnd
,msg
,wParam
,lParam
);
352 lResult
=DefWindowProc(hWnd
,msg
,wParam
,lParam
);
357 SetParent(hListBox
,hWnd
);
358 GetClientRect(hWnd
,&rect
);
359 MoveWindow(hListBox
,0,0,rect
.right
,rect
.bottom
,TRUE
);
360 ShowWindow(hListBox
,SW_SHOW
);
366 GetClientRect(hWnd
,&rect
);
368 MoveWindow(hListBox
,0,0,rect
.right
,rect
.bottom
,TRUE
);
370 MoveWindow(hSubWnd
,0,rect
.bottom
/2,rect
.right
,rect
.bottom
-(rect
.bottom
/2),TRUE
);
379 lResult
=DefWindowProc(hWnd
,msg
,wParam
,lParam
);
381 State
=OldState
; Rec
--;
386 LRESULT FAR CALLBACK _export
SubWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
392 State
=STATE_RECURS
; Rec
++;
393 if (!Clicked
) LogMessage(OldState
,hWnd
,msg
,wParam
,lParam
);
399 lResult
=DefWindowProc(hWnd
,msg
,wParam
,lParam
);
401 State
=OldState
; Rec
--;
405 BOOL FAR CALLBACK _export
SubDialogProc(HWND hWndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
407 /* SUBCLASSED CONTROLS */
408 LRESULT FAR CALLBACK _export
SubClassWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
415 if (hWnd
==hButton
[0]) But
=0; else
416 if (hWnd
==hButton
[1]) But
=1; else
417 if (hWnd
==hButton
[2]) But
=2; else
418 if (hWnd
==hButton
[3]) But
=3;
420 State
=STATE_RECURS
; Rec
++;
422 LogMessage(OldState
,hWnd
,msg
,wParam
,lParam
);
424 lResult
=CallWindowProc((FARPROC
)wndButton
[But
],hWnd
,msg
,wParam
,lParam
);
425 if (msg
==WM_LBUTTONUP
) {
426 LogChildOrder(GetParent(hWnd
));
429 else if (hWnd
==hDialog
) {
430 lResult
=CallWindowProc((FARPROC
)wndDialog
,hWnd
,msg
,wParam
,lParam
);
432 else if (hWnd
==hSubDlg
) {
433 lResult
=CallWindowProc((FARPROC
)wndSubDlg
,hWnd
,msg
,wParam
,lParam
);
435 else if (hWnd
==hGroup
) {
436 lResult
=CallWindowProc((FARPROC
)wndGroup
,hWnd
,msg
,wParam
,lParam
);
437 if (msg
==WM_SETFOCUS
) {
438 /* create subdialog */
441 SetRect(&rect
,0,0,1,1);
442 InvalidateRect(hWnd
,&rect
,FALSE
);
445 #ifdef TEST_SUBDIALOG
447 hSubDlg
=CreateDialog(hInst
,MAKEINTRESOURCE(2),hWnd
,(FARPROC
)SubDialogProc
);
451 GetWindowRect(GetParent(hWnd
),&rect
);
453 SetWindowPos(GetParent(hWnd
),0,0,0,
454 rect
.right
-rect
.left
,rect
.bottom
-rect
.top
,
455 SWP_NOMOVE
|SWP_NOZORDER
);
462 State
=OldState
; Rec
--;
466 /* MAIN DIALOG PROCEDURE */
467 BOOL FAR CALLBACK _export
TestDialogProc(HWND hWndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
474 State
=STATE_RECURS
; Rec
++;
475 if (!Clicked
) LogMessage(OldState
,hWndDlg
,msg
,wParam
,lParam
,"dlgp");
479 /* subclass dialog window proc */
480 wndDialog
= (WNDPROC
)SetWindowLong(hDialog
,GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
481 Logf("dialog visible=%s",IsWindowVisible(hWndDlg
)?"TRUE":"FALSE");
482 /* subclass OK button */
483 hButton
[3] = GetDlgItem(hWndDlg
,IDOK
);
484 wndButton
[3] = (WNDPROC
)SetWindowLong(hButton
[3],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
485 /* subclass group box */
486 hGroup
= GetDlgItem(hWndDlg
,IDC_GROUPBOX1
);
487 wndGroup
= (WNDPROC
)SetWindowLong(hGroup
,GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
490 GetWindowRect(hWndDlg
,&rect
);
492 SetWindowPos(hWndDlg
,0,0,0,
493 rect
.right
-rect
.left
,rect
.bottom
-rect
.top
,
494 SWP_NOMOVE
|SWP_NOZORDER
);
495 // ShowWindow(GetDlgItem(hWndDlg,IDCANCEL),SW_HIDE);
498 bResult
=TRUE
; /* we don't do SetFocus */
501 PaintPattern(hWndDlg
);
505 EndDialog(hWndDlg
,LOWORD(wParam
));
509 EndDialog(hWndDlg
,IDCANCEL
);
516 State
=OldState
; Rec
--;
520 /* SUBDIALOG PROCEDURE */
521 BOOL FAR CALLBACK _export
SubDialogProc(HWND hWndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
528 State
=STATE_RECURS
; Rec
++;
529 if (!Clicked
) LogMessage(OldState
,hWndDlg
,msg
,wParam
,lParam
);
533 /* subclass dialog window proc */
534 wndSubDlg
= (WNDPROC
)SetWindowLong(hDialog
,GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
536 bResult
=TRUE
; /* we don't do SetFocus */
542 State
=OldState
; Rec
--;
546 /********************/
547 /*** MAIN PROGRAM ***/
548 /********************/
554 wclass
.style
= CS_HREDRAW
|CS_VREDRAW
;
555 wclass
.lpfnWndProc
= MainWindowProc
;
556 wclass
.cbClsExtra
= 0;
557 wclass
.cbWndExtra
= 0;
558 wclass
.hInstance
= hInst
;
559 wclass
.hIcon
= LoadIcon(hInst
,MAKEINTRESOURCE(1));
560 wclass
.hCursor
= LoadCursor(0,IDC_ARROW
);
561 wclass
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
562 wclass
.lpszMenuName
= NULL
;
563 wclass
.lpszClassName
= wclassname
;
564 if (!RegisterClass(&wclass
)) return FALSE
;
565 wclass
.lpfnWndProc
= SubWindowProc
;
566 wclass
.lpszClassName
= wcclassname
;
567 if (!RegisterClass(&wclass
)) return FALSE
;
571 int PASCAL
WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
,
572 LPSTR lpszCmdLine
, int nCmdShow
)
582 StartTime
=GetTickCount();
583 hListBox
= CreateWindow("LISTBOX","Messages",WS_BORDER
|WS_VSCROLL
|WS_CHILD
|
584 LBS_HASSTRINGS
|LBS_NOTIFY
|LBS_WANTKEYBOARDINPUT
,
585 0,0,0,0,GetDesktopWindow(),0,hInst
,0);
587 MessageBox(0,"Could not create list box","Error",MB_OK
);
591 hMainWnd
= CreateWindow(wclassname
,winname
,MAIN_STYLE
,
592 CW_USEDEFAULT
,0,400,300,0,0,hInst
,0);
593 if (!hMainWnd
) return 0;
595 ShowWindow(hMainWnd
,nCmdShow
);
596 #ifdef TEST_DESTROY_MAIN
598 DestroyWindow(hMainWnd
);
600 while (GetMessage(&msg
,0,0,0)) {
601 TranslateMessage(&msg
);
602 State
=STATE_DISPATCH
;
603 DispatchMessage(&msg
);
607 hMainWnd
= CreateWindow(wclassname
,winname
,MAIN_STYLE
,
608 CW_USEDEFAULT
,0,400,300,0,0,hInst
,0);
609 if (!hMainWnd
) return 0;
611 ShowWindow(hMainWnd
,nCmdShow
);
613 /* update, so no WM_PAINTs are pending */
615 // UpdateWindow(hMainWnd);
617 /* fill client area with a pattern */
618 FillPattern(hMainWnd
);
619 /* create subwindow */
621 GetClientRect(hMainWnd
,&rect
);
622 hSubWnd
= CreateWindow(wcclassname
,winname
,WS_CHILD
|WS_BORDER
|WS_CLIPSIBLINGS
,
623 0,rect
.bottom
/2,rect
.right
,rect
.bottom
-(rect
.bottom
/2),hMainWnd
,0,hInst
,0);
624 if (!hSubWnd
) return 0;
626 hButton
[0] = CreateWindow("BUTTON","1",WS_CHILD
|WS_CLIPSIBLINGS
|WS_VISIBLE
,
627 8,8,48,20,hMainWnd
,0,hInst
,0);
628 hButton
[1] = CreateWindow("BUTTON","2",WS_CHILD
|WS_CLIPSIBLINGS
|WS_VISIBLE
,
629 32,12,48,20,hMainWnd
,0,hInst
,0);
630 hButton
[2] = CreateWindow("BUTTON","3",WS_CHILD
|WS_CLIPSIBLINGS
|WS_VISIBLE
,
631 56,16,48,20,hMainWnd
,0,hInst
,0);
633 wndButton
[0] = (WNDPROC
)SetWindowLong(hButton
[0],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
634 wndButton
[1] = (WNDPROC
)SetWindowLong(hButton
[1],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
635 wndButton
[2] = (WNDPROC
)SetWindowLong(hButton
[2],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
638 UpdateWindow(hButton
[0]);
639 LogChildOrder(hMainWnd
);
640 Logf("but1 visible=%d",IsWindowVisible(hButton
[0]));
642 /* now reparent the button to our (invisible) subwindow */
644 /* in different order, seeing who gets topmost */
645 SetParent(hButton
[0],hSubWnd
);
646 SetParent(hButton
[2],hSubWnd
);
647 SetParent(hButton
[1],hSubWnd
);
648 LogChildOrder(hSubWnd
);
649 /* the button should now be invisible */
650 Logf("but1 visible=%d",IsWindowVisible(hButton
[0]));
651 /* see if we can draw on them */
652 FillPattern(hButton
[0]);
656 ShowWindow(hSubWnd
,SW_SHOWNORMAL
);
658 UpdateWindow(hSubWnd
);
659 FillPattern(hSubWnd
);
660 // InvalidateRect(hMainWnd,NULL,TRUE);
661 Logf("but1 visible=%d",IsWindowVisible(hButton
[0]));
666 DialogBox(hInst
,MAKEINTRESOURCE(1),hMainWnd
,(FARPROC
)TestDialogProc
);
671 CHOOSECOLOR cc
={sizeof(cc
),0,hInst
,0,arr
,0};
677 while (GetMessage(&msg
,0,0,0)) {
678 TranslateMessage(&msg
);
679 State
=STATE_DISPATCH
;
680 DispatchMessage(&msg
);