1 /* Windows GUI Behaviour Tester
3 * Copyright 1999 Ove Kåven
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /* checks to include */
28 #define LOGGING /* can be undefined under Wine and use -debugmsg +message instead */
29 #define MAIN_STYLE WS_OVERLAPPEDWINDOW|WS_HSCROLL
30 #define MAIN_EXSTYLE 0
31 #undef TEST_DESTROY_MAIN
38 /************************/
39 /*** GLOBAL VARIABLES ***/
40 /************************/
44 HWND hListBox
,hMainWnd
,hSubWnd
;
45 HWND hButton
[4]={0,0,0,0};
46 HWND hDialog
=0,hGroup
=0,hSubDlg
=0;
47 WNDPROC wndButton
[4],wndDialog
,wndGroup
,wndSubDlg
;
48 BOOL Clicked
=0,Ready
=0;
50 #define STATE_CREATE 0
51 #define STATE_DESTROY 1
53 #define STATE_UPDATE 3
54 #define STATE_DIALOG 4
56 #define STATE_DIRECT 6
57 #define STATE_DISPATCH 7
58 #define STATE_RECURS 8
71 static char wclassname
[] = "GUITestClass";
72 static char wcclassname
[] = "GUITestChildClass";
73 static char winname
[] = "GUITest";
75 /**************************/
76 /*** LOGGING FACILITIES ***/
77 /**************************/
83 #define MSG(x) {x,#x},
84 #define MSG2(x,y) {y,#x},
87 /* we get these in CreateWindow */
94 /* we get these in ShowWindow */
96 MSG(WM_WINDOWPOSCHANGING
)
97 MSG(WM_QUERYNEWPALETTE
)
105 MSG(WM_WINDOWPOSCHANGED
)
109 /* we get these in DestroyWindow */
114 /* we get these directly sent */
117 MSG(WM_MOUSEACTIVATE
)
118 MSG(WM_CHILDACTIVATE
)
128 MSG(WM_LBUTTONDBLCLK
)
129 MSG(WM_NCLBUTTONDOWN
)
131 MSG(WM_NCLBUTTONDBLCLK
)
140 MSG(WM_CTLCOLORSTATIC
)
145 /* moving and sizing */
146 MSG2(WM_ENTERSIZEMOVE
,0x0231)
147 MSG2(WM_EXITSIZEMOVE
,0x0232)
152 /* menus/dialog boxes */
164 /* getting these from Wine but not from Windows */
165 MSG2(WM_SETVISIBLE
,0x0009) /* unheard of in BC++ 4.52 */
167 MSG(WM_CAPTURECHANGED
)
172 struct MSGNAMES ButMsgs
[]={
178 char*MsgName(UINT msg
,HWND hWnd
)
181 static char buffer
[64],wclass
[64];
182 GetClassName(hWnd
,wclass
,sizeof(wclass
));
184 #define MSGSEARCH(msgs) { \
185 for (i=0; msgs[i].name&&msgs[i].msg!=msg; i++); \
186 if (msgs[i].name) return msgs[i].name; \
189 if (!stricmp(wclass
,"Button")) MSGSEARCH(ButMsgs
);
193 sprintf(buffer
,"WM_USER+%04x{%s}",msg
-WM_USER
,wclass
);
196 /* message not found */
197 sprintf(buffer
,"%04x{%s}",msg
,wclass
);
201 char*WndName(HWND hWnd
,int state
)
203 static char buffer
[16];
204 if (!hWnd
) return "0000";
205 if (hWnd
==hMainWnd
|| (state
==STATE_CREATE
&& !hMainWnd
)) return "main";
206 if (hWnd
==hSubWnd
|| (state
==STATE_CREATE
&& !hSubWnd
)) return "chld";
207 if (hWnd
==hDialog
|| (state
==STATE_DIALOG
&& !hDialog
)) return "tdlg";
208 if (hWnd
==hGroup
) return "tgrp";
209 if (hWnd
==hButton
[0]) return "but1";
210 if (hWnd
==hButton
[1]) return "but2";
211 if (hWnd
==hButton
[2]) return "but3";
212 if (hWnd
==hButton
[3]) return "but4";
213 if (hWnd
==hSubDlg
|| (state
==STATE_CREATE
&& !hSubDlg
)) return "sdlg";
215 int id
=GetDlgCtrlID(hWnd
);
217 sprintf(buffer
,"dlgitem(%d)",id
);
221 sprintf(buffer
,"%04x",hWnd
);
225 void Log(const char*fmt
)
228 if (!Clicked
) SendMessage(hListBox
,LB_ADDSTRING
,0,(LPARAM
)fmt
);
232 void Logf(const char*fmt
,...)
235 static char buffer
[256];
238 vsprintf(buffer
,fmt
,par
);
243 void LogChildOrder(HWND hWnd
)
245 HWND hWndChild
= GetWindow(hWnd
,GW_CHILD
);
246 static char buffer
[256];
248 strcpy(buffer
,"child list:");
250 strcat(strcat(buffer
," "),WndName(hWndChild
,State
));
251 hWndChild
=GetWindow(hWndChild
,GW_HWNDNEXT
);
256 void LogMessage(int state
,HWND hWnd
,UINT msg
,WPARAM wParam
,LPARAM lParam
,char*name
)
258 static char buffer
[256];
259 DWORD tick
=GetTickCount()-StartTime
;
260 char*msgname
=MsgName(msg
,hWnd
);
261 if (!name
) name
=WndName(hWnd
,state
);
266 Logf("%04d[%s(%d):%s]%s(%s,%08x)",tick
,StateName
[state
],Rec
,
267 name
,msgname
,WndName((HWND
)wParam
,State
),lParam
);
273 Logf("%04d[%s(%d):%s]%s(%08x,%s)",tick
,StateName
[state
],Rec
,
274 name
,msgname
,wParam
,WndName((HWND
)lParam
,State
));
279 Logf("%04d[%s(%d):%s]%s(%08x,%04x:%s)",tick
,StateName
[state
],Rec
,
280 name
,msgname
,wParam
,HIWORD(lParam
),WndName((HWND
)LOWORD(lParam
),State
));
283 case WM_WINDOWPOSCHANGING
:
284 case WM_WINDOWPOSCHANGED
:
286 WINDOWPOS
*pos
=(WINDOWPOS
*)lParam
;
288 Logf("%04d[%s(%d):%s]%s(%08x,%p)",tick
,StateName
[state
],Rec
,
289 name
,msgname
,wParam
,pos
);
291 Logf("%04d[%s(%d):%s]%s(%04x,%p)",tick
,StateName
[state
],Rec
,
292 name
,msgname
,wParam
,pos
);
294 strcpy(buffer
,"FLAGS:");
295 if (pos
->flags
&SWP_DRAWFRAME
) strcat(buffer
," DRAWFRAME");
296 if (pos
->flags
&SWP_HIDEWINDOW
) strcat(buffer
," HIDEWINDOW");
297 if (pos
->flags
&SWP_NOACTIVATE
) strcat(buffer
," NOACTIVATE");
298 if (pos
->flags
&SWP_NOCOPYBITS
) strcat(buffer
," NOCOPYBITS");
299 if (pos
->flags
&SWP_NOMOVE
) strcat(buffer
," NOMOVE");
300 if (pos
->flags
&SWP_NOOWNERZORDER
) strcat(buffer
," NOOWNERZORDER");
301 if (pos
->flags
&SWP_NOSIZE
) strcat(buffer
," NOSIZE");
302 if (pos
->flags
&SWP_NOREDRAW
) strcat(buffer
," NOREDRAW");
303 if (pos
->flags
&SWP_NOZORDER
) strcat(buffer
," NOZORDER");
304 if (pos
->flags
&SWP_SHOWWINDOW
) strcat(buffer
," SHOWWINDOW");
311 switch (wParam
&0xFFF0) {
312 #define CASE(x) case SC_##x: cmd=#x; break;
332 Logf("%04d[%s(%d):%s]%s(%s+%x,%08x)",tick
,StateName
[state
],Rec
,
333 name
,msgname
,cmd
,wParam
&0xF,lParam
);
334 } else goto GENERIC_MSG
;
341 switch (LOWORD(wParam
)) {
342 #define CASE(x) case SB_##x: cmd=#x; break;
343 #define CASE2(h,v) case SB_##h: if (msg==WM_HSCROLL) cmd=#h; else cmd=#v; break;
346 CASE2(LINELEFT
,LINEUP
)
347 CASE2(LINERIGHT
,LINEDOWN
)
348 CASE2(PAGELEFT
,PAGEUP
)
349 CASE2(PAGERIGHT
,PAGEDOWN
)
357 Logf("%04d[%s(%d):%s]%s(%s,%04x,%s)",tick
,StateName
[state
],Rec
,
358 name
,msgname
,cmd
,HIWORD(wParam
),WndName((HWND
)lParam
,State
));
360 Logf("%04d[%s(%d):%s]%s(%04x,%04x,%s)",tick
,StateName
[state
],Rec
,
361 name
,msgname
,cmd
,LOWORD(lParam
),WndName((HWND
)HIWORD(lParam
),State
));
363 } else goto GENERIC_MSG
;
369 Logf("%04d[%s(%d):%s]%s(%08x,%08x)",tick
,StateName
[state
],Rec
,
370 name
,msgname
,wParam
,lParam
);
372 Logf("%04d[%s(%d):%s]%s(%04x,%08x)",tick
,StateName
[state
],Rec
,
373 name
,msgname
,wParam
,lParam
);
378 /***************************/
379 /*** GRAPHICS FACILITIES ***/
380 /***************************/
382 void Paint(HWND hWnd
)
386 dc
=BeginPaint(hWnd
,&ps
);
390 void FillPattern(HWND hWnd
,HDC pdc
)
392 HDC dc
=pdc
?pdc
:GetDC(hWnd
);
396 Logf("failed to acquire DC for window %s",WndName(hWnd
,State
));
399 Logf("acquired DC for %s window %s, painting",
400 IsWindowVisible(hWnd
)?"visible":"invisible",WndName(hWnd
,State
));
402 GetClientRect(hWnd
,&rect
);
403 oldbrush
=SelectObject(dc
,GetStockObject(LTGRAY_BRUSH
));
404 PatBlt(dc
,0,0,rect
.right
,rect
.bottom
,PATCOPY
);
405 SelectObject(dc
,oldbrush
);
406 if (!pdc
) ReleaseDC(hWnd
,dc
);
409 void PaintPattern(HWND hWnd
)
413 dc
=BeginPaint(hWnd
,&ps
);
414 FillPattern(hWnd
,dc
);
418 /*************************/
419 /*** WINDOW PROCEDURES ***/
420 /*************************/
423 LRESULT FAR CALLBACK _export
MainWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
429 State
=STATE_RECURS
; Rec
++;
430 if (!Clicked
) LogMessage(OldState
,hWnd
,msg
,wParam
,lParam
,NULL
);
433 lResult
=DefWindowProc(hWnd
,msg
,wParam
,lParam
);
438 SetParent(hListBox
,hWnd
);
439 GetClientRect(hWnd
,&rect
);
440 MoveWindow(hListBox
,0,0,rect
.right
,rect
.bottom
,TRUE
);
441 ShowWindow(hListBox
,SW_SHOW
);
447 GetClientRect(hWnd
,&rect
);
449 MoveWindow(hListBox
,0,0,rect
.right
,rect
.bottom
,TRUE
);
451 MoveWindow(hSubWnd
,0,rect
.bottom
/2,rect
.right
,rect
.bottom
-(rect
.bottom
/2),TRUE
);
460 lResult
=DefWindowProc(hWnd
,msg
,wParam
,lParam
);
462 State
=OldState
; Rec
--;
467 LRESULT FAR CALLBACK _export
SubWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
473 State
=STATE_RECURS
; Rec
++;
474 if (!Clicked
) LogMessage(OldState
,hWnd
,msg
,wParam
,lParam
,NULL
);
480 lResult
=DefWindowProc(hWnd
,msg
,wParam
,lParam
);
482 State
=OldState
; Rec
--;
486 BOOL FAR CALLBACK _export
SubDialogProc(HWND hWndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
488 /* SUBCLASSED CONTROLS */
489 LRESULT FAR CALLBACK _export
SubClassWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
496 if (hWnd
==hButton
[0]) But
=0; else
497 if (hWnd
==hButton
[1]) But
=1; else
498 if (hWnd
==hButton
[2]) But
=2; else
499 if (hWnd
==hButton
[3]) But
=3;
501 State
=STATE_RECURS
; Rec
++;
503 LogMessage(OldState
,hWnd
,msg
,wParam
,lParam
,NULL
);
505 lResult
=CallWindowProc((FARPROC
)wndButton
[But
],hWnd
,msg
,wParam
,lParam
);
506 if (msg
==WM_LBUTTONUP
) {
507 LogChildOrder(GetParent(hWnd
));
510 else if (hWnd
==hDialog
) {
511 lResult
=CallWindowProc((FARPROC
)wndDialog
,hWnd
,msg
,wParam
,lParam
);
513 else if (hWnd
==hSubDlg
) {
514 lResult
=CallWindowProc((FARPROC
)wndSubDlg
,hWnd
,msg
,wParam
,lParam
);
516 else if (hWnd
==hGroup
) {
517 lResult
=CallWindowProc((FARPROC
)wndGroup
,hWnd
,msg
,wParam
,lParam
);
518 if (msg
==WM_SETFOCUS
) {
519 /* create subdialog */
522 SetRect(&rect
,0,0,1,1);
523 InvalidateRect(hWnd
,&rect
,FALSE
);
526 #ifdef TEST_SUBDIALOG
528 hSubDlg
=CreateDialog(hInst
,MAKEINTRESOURCE(2),hWnd
,(FARPROC
)SubDialogProc
);
532 GetWindowRect(GetParent(hWnd
),&rect
);
534 SetWindowPos(GetParent(hWnd
),0,0,0,
535 rect
.right
-rect
.left
,rect
.bottom
-rect
.top
,
536 SWP_NOMOVE
|SWP_NOZORDER
);
543 State
=OldState
; Rec
--;
547 /* MAIN DIALOG PROCEDURE */
548 BOOL FAR CALLBACK _export
TestDialogProc(HWND hWndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
555 State
=STATE_RECURS
; Rec
++;
556 if (!Clicked
) LogMessage(OldState
,hWndDlg
,msg
,wParam
,lParam
,"dlgp");
560 /* subclass dialog window proc */
561 wndDialog
= (WNDPROC
)SetWindowLong(hDialog
,GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
562 Logf("dialog visible=%s",IsWindowVisible(hWndDlg
)?"TRUE":"FALSE");
563 /* subclass OK button */
564 hButton
[3] = GetDlgItem(hWndDlg
,IDOK
);
565 wndButton
[3] = (WNDPROC
)SetWindowLong(hButton
[3],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
566 /* subclass group box */
567 hGroup
= GetDlgItem(hWndDlg
,IDC_GROUPBOX1
);
568 wndGroup
= (WNDPROC
)SetWindowLong(hGroup
,GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
571 GetWindowRect(hWndDlg
,&rect
);
573 SetWindowPos(hWndDlg
,0,0,0,
574 rect
.right
-rect
.left
,rect
.bottom
-rect
.top
,
575 SWP_NOMOVE
|SWP_NOZORDER
);
576 // ShowWindow(GetDlgItem(hWndDlg,IDCANCEL),SW_HIDE);
579 bResult
=TRUE
; /* we don't do SetFocus */
582 PaintPattern(hWndDlg
);
586 EndDialog(hWndDlg
,LOWORD(wParam
));
590 EndDialog(hWndDlg
,IDCANCEL
);
597 State
=OldState
; Rec
--;
601 /* SUBDIALOG PROCEDURE */
602 BOOL FAR CALLBACK _export
SubDialogProc(HWND hWndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
609 State
=STATE_RECURS
; Rec
++;
610 if (!Clicked
) LogMessage(OldState
,hWndDlg
,msg
,wParam
,lParam
,NULL
);
614 /* subclass dialog window proc */
615 wndSubDlg
= (WNDPROC
)SetWindowLong(hDialog
,GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
617 bResult
=TRUE
; /* we don't do SetFocus */
623 State
=OldState
; Rec
--;
627 /********************/
628 /*** MAIN PROGRAM ***/
629 /********************/
635 wclass
.style
= CS_HREDRAW
|CS_VREDRAW
;
636 wclass
.lpfnWndProc
= MainWindowProc
;
637 wclass
.cbClsExtra
= 0;
638 wclass
.cbWndExtra
= 0;
639 wclass
.hInstance
= hInst
;
640 wclass
.hIcon
= LoadIcon(hInst
,MAKEINTRESOURCE(1));
641 wclass
.hCursor
= LoadCursor(0,IDC_ARROW
);
642 wclass
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
643 wclass
.lpszMenuName
= NULL
;
644 wclass
.lpszClassName
= wclassname
;
645 if (!RegisterClass(&wclass
)) return FALSE
;
646 wclass
.lpfnWndProc
= SubWindowProc
;
647 wclass
.lpszClassName
= wcclassname
;
648 if (!RegisterClass(&wclass
)) return FALSE
;
652 int PASCAL
WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
,
653 LPSTR lpszCmdLine
, int nCmdShow
)
663 StartTime
=GetTickCount();
664 hListBox
= CreateWindow("LISTBOX","Messages",WS_BORDER
|WS_VSCROLL
|WS_CHILD
|
665 LBS_HASSTRINGS
|LBS_NOTIFY
|LBS_WANTKEYBOARDINPUT
,
666 0,0,0,0,GetDesktopWindow(),0,hInst
,0);
668 MessageBox(0,"Could not create list box","Error",MB_OK
);
672 hMainWnd
= CreateWindowEx(MAIN_EXSTYLE
,wclassname
,winname
,MAIN_STYLE
,
673 CW_USEDEFAULT
,0,400,300,0,0,hInst
,0);
674 if (!hMainWnd
) return 0;
676 ShowWindow(hMainWnd
,nCmdShow
);
677 #ifdef TEST_DESTROY_MAIN
679 DestroyWindow(hMainWnd
);
681 while (GetMessage(&msg
,0,0,0)) {
682 TranslateMessage(&msg
);
683 State
=STATE_DISPATCH
;
684 DispatchMessage(&msg
);
688 hMainWnd
= CreateWindowEx(MAIN_EXSTYLE
,wclassname
,winname
,MAIN_STYLE
,
689 CW_USEDEFAULT
,0,400,300,0,0,hInst
,0);
690 if (!hMainWnd
) return 0;
692 ShowWindow(hMainWnd
,nCmdShow
);
694 /* update, so no WM_PAINTs are pending */
696 // UpdateWindow(hMainWnd);
698 /* fill client area with a pattern */
699 FillPattern(hMainWnd
,0);
700 /* create subwindow */
702 GetClientRect(hMainWnd
,&rect
);
703 hSubWnd
= CreateWindow(wcclassname
,winname
,WS_CHILD
|WS_BORDER
|WS_CLIPSIBLINGS
,
704 0,rect
.bottom
/2,rect
.right
,rect
.bottom
-(rect
.bottom
/2),hMainWnd
,0,hInst
,0);
705 if (!hSubWnd
) return 0;
707 hButton
[0] = CreateWindow("BUTTON","1",WS_CHILD
|WS_CLIPSIBLINGS
|WS_VISIBLE
,
708 8,8,48,20,hMainWnd
,0,hInst
,0);
709 hButton
[1] = CreateWindow("BUTTON","2",WS_CHILD
|WS_CLIPSIBLINGS
|WS_VISIBLE
,
710 32,12,48,20,hMainWnd
,0,hInst
,0);
711 hButton
[2] = CreateWindow("BUTTON","3",WS_CHILD
|WS_CLIPSIBLINGS
|WS_VISIBLE
,
712 56,16,48,20,hMainWnd
,0,hInst
,0);
714 wndButton
[0] = (WNDPROC
)SetWindowLong(hButton
[0],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
715 wndButton
[1] = (WNDPROC
)SetWindowLong(hButton
[1],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
716 wndButton
[2] = (WNDPROC
)SetWindowLong(hButton
[2],GWL_WNDPROC
,(LONG
)SubClassWindowProc
);
719 UpdateWindow(hButton
[0]);
720 LogChildOrder(hMainWnd
);
721 Logf("but1 visible=%d",IsWindowVisible(hButton
[0]));
723 /* now reparent the button to our (invisible) subwindow */
725 /* in different order, seeing who gets topmost */
726 SetParent(hButton
[0],hSubWnd
);
727 SetParent(hButton
[2],hSubWnd
);
728 SetParent(hButton
[1],hSubWnd
);
729 LogChildOrder(hSubWnd
);
730 /* the button should now be invisible */
731 Logf("but1 visible=%d",IsWindowVisible(hButton
[0]));
732 /* see if we can draw on them */
733 FillPattern(hButton
[0],0);
737 ShowWindow(hSubWnd
,SW_SHOWNORMAL
);
739 UpdateWindow(hSubWnd
);
740 FillPattern(hSubWnd
,0);
741 // InvalidateRect(hMainWnd,NULL,TRUE);
742 Logf("but1 visible=%d",IsWindowVisible(hButton
[0]));
747 DialogBox(hInst
,MAKEINTRESOURCE(1),hMainWnd
,(FARPROC
)TestDialogProc
);
752 CHOOSECOLOR cc
={sizeof(cc
),0,hInst
,0,arr
,0};
758 while (GetMessage(&msg
,0,0,0)) {
759 TranslateMessage(&msg
);
760 State
=STATE_DISPATCH
;
761 DispatchMessage(&msg
);