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|WS_HSCROLL
14 #define MAIN_EXSTYLE 0
15 #undef TEST_DESTROY_MAIN
22 /************************/
23 /*** GLOBAL VARIABLES ***/
24 /************************/
28 HWND hListBox,hMainWnd,hSubWnd;
29 HWND hButton[4]={0,0,0,0};
30 HWND hDialog=0,hGroup=0,hSubDlg=0;
31 WNDPROC wndButton[4],wndDialog,wndGroup,wndSubDlg;
32 BOOL Clicked=0,Ready=0;
34 #define STATE_CREATE 0
35 #define STATE_DESTROY 1
37 #define STATE_UPDATE 3
38 #define STATE_DIALOG 4
40 #define STATE_DIRECT 6
41 #define STATE_DISPATCH 7
42 #define STATE_RECURS 8
55 static char wclassname[] = "GUITestClass";
56 static char wcclassname[] = "GUITestChildClass";
57 static char winname[] = "GUITest";
59 /**************************/
60 /*** LOGGING FACILITIES ***/
61 /**************************/
67 #define MSG(x) {x,#x},
68 #define MSG2(x,y) {y,#x},
71 /* we get these in CreateWindow */
78 /* we get these in ShowWindow */
80 MSG(WM_WINDOWPOSCHANGING)
81 MSG(WM_QUERYNEWPALETTE)
89 MSG(WM_WINDOWPOSCHANGED)
93 /* we get these in DestroyWindow */
98 /* we get these directly sent */
101 MSG(WM_MOUSEACTIVATE)
102 MSG(WM_CHILDACTIVATE)
112 MSG(WM_LBUTTONDBLCLK)
113 MSG(WM_NCLBUTTONDOWN)
115 MSG(WM_NCLBUTTONDBLCLK)
124 MSG(WM_CTLCOLORSTATIC)
129 /* moving and sizing */
130 MSG2(WM_ENTERSIZEMOVE,0x0231)
131 MSG2(WM_EXITSIZEMOVE,0x0232)
136 /* menus/dialog boxes */
148 /* getting these from Wine but not from Windows */
149 MSG2(WM_SETVISIBLE,0x0009) /* unheard of in BC++ 4.52 */
151 MSG(WM_CAPTURECHANGED)
156 struct MSGNAMES ButMsgs[]={
162 char*MsgName(UINT msg,HWND hWnd)
165 static char buffer[64],wclass[64];
166 GetClassName(hWnd,wclass,sizeof(wclass));
168 #define MSGSEARCH(msgs) { \
169 for (i=0; msgs[i].name&&msgs[i].msg!=msg; i++); \
170 if (msgs[i].name) return msgs[i].name; \
173 if (!stricmp(wclass,"Button")) MSGSEARCH(ButMsgs);
177 sprintf(buffer,"WM_USER+%04x{%s}",msg-WM_USER,wclass);
180 /* message not found */
181 sprintf(buffer,"%04x{%s}",msg,wclass);
185 char*WndName(HWND hWnd,int state)
187 static char buffer[16];
188 if (!hWnd) return "0000";
189 if (hWnd==hMainWnd || (state==STATE_CREATE && !hMainWnd)) return "main";
190 if (hWnd==hSubWnd || (state==STATE_CREATE && !hSubWnd)) return "chld";
191 if (hWnd==hDialog || (state==STATE_DIALOG && !hDialog)) return "tdlg";
192 if (hWnd==hGroup) return "tgrp";
193 if (hWnd==hButton[0]) return "but1";
194 if (hWnd==hButton[1]) return "but2";
195 if (hWnd==hButton[2]) return "but3";
196 if (hWnd==hButton[3]) return "but4";
197 if (hWnd==hSubDlg || (state==STATE_CREATE && !hSubDlg)) return "sdlg";
199 int id=GetDlgCtrlID(hWnd);
201 sprintf(buffer,"dlgitem(%d)",id);
205 sprintf(buffer,"%04x",hWnd);
209 void Log(const char*fmt)
212 if (!Clicked) SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)fmt);
216 void Logf(const char*fmt,...)
219 static char buffer[256];
222 vsprintf(buffer,fmt,par);
227 void LogChildOrder(HWND hWnd)
229 HWND hWndChild = GetWindow(hWnd,GW_CHILD);
230 static char buffer[256];
232 strcpy(buffer,"child list:");
234 strcat(strcat(buffer," "),WndName(hWndChild,State));
235 hWndChild=GetWindow(hWndChild,GW_HWNDNEXT);
240 void LogMessage(int state,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,char*name)
242 static char buffer[256];
243 DWORD tick=GetTickCount()-StartTime;
244 char*msgname=MsgName(msg,hWnd);
245 if (!name) name=WndName(hWnd,state);
250 Logf("%04d[%s(%d):%s]%s(%s,%08x)",tick,StateName[state],Rec,
251 name,msgname,WndName((HWND)wParam,State),lParam);
257 Logf("%04d[%s(%d):%s]%s(%08x,%s)",tick,StateName[state],Rec,
258 name,msgname,wParam,WndName((HWND)lParam,State));
263 Logf("%04d[%s(%d):%s]%s(%08x,%04x:%s)",tick,StateName[state],Rec,
264 name,msgname,wParam,HIWORD(lParam),WndName((HWND)LOWORD(lParam),State));
267 case WM_WINDOWPOSCHANGING:
268 case WM_WINDOWPOSCHANGED:
270 WINDOWPOS*pos=(WINDOWPOS*)lParam;
272 Logf("%04d[%s(%d):%s]%s(%08x,%p)",tick,StateName[state],Rec,
273 name,msgname,wParam,pos);
275 Logf("%04d[%s(%d):%s]%s(%04x,%p)",tick,StateName[state],Rec,
276 name,msgname,wParam,pos);
278 strcpy(buffer,"FLAGS:");
279 if (pos->flags&SWP_DRAWFRAME) strcat(buffer," DRAWFRAME");
280 if (pos->flags&SWP_HIDEWINDOW) strcat(buffer," HIDEWINDOW");
281 if (pos->flags&SWP_NOACTIVATE) strcat(buffer," NOACTIVATE");
282 if (pos->flags&SWP_NOCOPYBITS) strcat(buffer," NOCOPYBITS");
283 if (pos->flags&SWP_NOMOVE) strcat(buffer," NOMOVE");
284 if (pos->flags&SWP_NOOWNERZORDER) strcat(buffer," NOOWNERZORDER");
285 if (pos->flags&SWP_NOSIZE) strcat(buffer," NOSIZE");
286 if (pos->flags&SWP_NOREDRAW) strcat(buffer," NOREDRAW");
287 if (pos->flags&SWP_NOZORDER) strcat(buffer," NOZORDER");
288 if (pos->flags&SWP_SHOWWINDOW) strcat(buffer," SHOWWINDOW");
295 switch (wParam&0xFFF0) {
296 #define CASE(x) case SC_##x: cmd=#x; break;
316 Logf("%04d[%s(%d):%s]%s(%s+%x,%08x)",tick,StateName[state],Rec,
317 name,msgname,cmd,wParam&0xF,lParam);
318 } else goto GENERIC_MSG;
325 switch (LOWORD(wParam)) {
326 #define CASE(x) case SB_##x: cmd=#x; break;
327 #define CASE2(h,v) case SB_##h: if (msg==WM_HSCROLL) cmd=#h; else cmd=#v; break;
330 CASE2(LINELEFT,LINEUP)
331 CASE2(LINERIGHT,LINEDOWN)
332 CASE2(PAGELEFT,PAGEUP)
333 CASE2(PAGERIGHT,PAGEDOWN)
341 Logf("%04d[%s(%d):%s]%s(%s,%04x,%s)",tick,StateName[state],Rec,
342 name,msgname,cmd,HIWORD(wParam),WndName((HWND)lParam,State));
344 Logf("%04d[%s(%d):%s]%s(%04x,%04x,%s)",tick,StateName[state],Rec,
345 name,msgname,cmd,LOWORD(lParam),WndName((HWND)HIWORD(lParam),State));
347 } else goto GENERIC_MSG;
353 Logf("%04d[%s(%d):%s]%s(%08x,%08x)",tick,StateName[state],Rec,
354 name,msgname,wParam,lParam);
356 Logf("%04d[%s(%d):%s]%s(%04x,%08x)",tick,StateName[state],Rec,
357 name,msgname,wParam,lParam);
362 /***************************/
363 /*** GRAPHICS FACILITIES ***/
364 /***************************/
366 void Paint(HWND hWnd)
370 dc=BeginPaint(hWnd,&ps);
374 void FillPattern(HWND hWnd,HDC pdc)
376 HDC dc=pdc?pdc:GetDC(hWnd);
380 Logf("failed to acquire DC for window %s",WndName(hWnd,State));
383 Logf("acquired DC for %s window %s, painting",
384 IsWindowVisible(hWnd)?"visible":"invisible",WndName(hWnd,State));
386 GetClientRect(hWnd,&rect);
387 oldbrush=SelectObject(dc,GetStockObject(LTGRAY_BRUSH));
388 PatBlt(dc,0,0,rect.right,rect.bottom,PATCOPY);
389 SelectObject(dc,oldbrush);
390 if (!pdc) ReleaseDC(hWnd,dc);
393 void PaintPattern(HWND hWnd)
397 dc=BeginPaint(hWnd,&ps);
398 FillPattern(hWnd,dc);
402 /*************************/
403 /*** WINDOW PROCEDURES ***/
404 /*************************/
407 LRESULT FAR CALLBACK _export MainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
413 State=STATE_RECURS; Rec++;
414 if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL);
417 lResult=DefWindowProc(hWnd,msg,wParam,lParam);
422 SetParent(hListBox,hWnd);
423 GetClientRect(hWnd,&rect);
424 MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE);
425 ShowWindow(hListBox,SW_SHOW);
431 GetClientRect(hWnd,&rect);
433 MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE);
435 MoveWindow(hSubWnd,0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),TRUE);
444 lResult=DefWindowProc(hWnd,msg,wParam,lParam);
446 State=OldState; Rec--;
451 LRESULT FAR CALLBACK _export SubWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
457 State=STATE_RECURS; Rec++;
458 if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL);
464 lResult=DefWindowProc(hWnd,msg,wParam,lParam);
466 State=OldState; Rec--;
470 BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
472 /* SUBCLASSED CONTROLS */
473 LRESULT FAR CALLBACK _export SubClassWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
480 if (hWnd==hButton[0]) But=0; else
481 if (hWnd==hButton[1]) But=1; else
482 if (hWnd==hButton[2]) But=2; else
483 if (hWnd==hButton[3]) But=3;
485 State=STATE_RECURS; Rec++;
487 LogMessage(OldState,hWnd,msg,wParam,lParam,NULL);
489 lResult=CallWindowProc((FARPROC)wndButton[But],hWnd,msg,wParam,lParam);
490 if (msg==WM_LBUTTONUP) {
491 LogChildOrder(GetParent(hWnd));
494 else if (hWnd==hDialog) {
495 lResult=CallWindowProc((FARPROC)wndDialog,hWnd,msg,wParam,lParam);
497 else if (hWnd==hSubDlg) {
498 lResult=CallWindowProc((FARPROC)wndSubDlg,hWnd,msg,wParam,lParam);
500 else if (hWnd==hGroup) {
501 lResult=CallWindowProc((FARPROC)wndGroup,hWnd,msg,wParam,lParam);
502 if (msg==WM_SETFOCUS) {
503 /* create subdialog */
506 SetRect(&rect,0,0,1,1);
507 InvalidateRect(hWnd,&rect,FALSE);
510 #ifdef TEST_SUBDIALOG
512 hSubDlg=CreateDialog(hInst,MAKEINTRESOURCE(2),hWnd,(FARPROC)SubDialogProc);
516 GetWindowRect(GetParent(hWnd),&rect);
518 SetWindowPos(GetParent(hWnd),0,0,0,
519 rect.right-rect.left,rect.bottom-rect.top,
520 SWP_NOMOVE|SWP_NOZORDER);
527 State=OldState; Rec--;
531 /* MAIN DIALOG PROCEDURE */
532 BOOL FAR CALLBACK _export TestDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
539 State=STATE_RECURS; Rec++;
540 if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,"dlgp");
544 /* subclass dialog window proc */
545 wndDialog = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc);
546 Logf("dialog visible=%s",IsWindowVisible(hWndDlg)?"TRUE":"FALSE");
547 /* subclass OK button */
548 hButton[3] = GetDlgItem(hWndDlg,IDOK);
549 wndButton[3] = (WNDPROC)SetWindowLong(hButton[3],GWL_WNDPROC,(LONG)SubClassWindowProc);
550 /* subclass group box */
551 hGroup = GetDlgItem(hWndDlg,IDC_GROUPBOX1);
552 wndGroup = (WNDPROC)SetWindowLong(hGroup,GWL_WNDPROC,(LONG)SubClassWindowProc);
555 GetWindowRect(hWndDlg,&rect);
557 SetWindowPos(hWndDlg,0,0,0,
558 rect.right-rect.left,rect.bottom-rect.top,
559 SWP_NOMOVE|SWP_NOZORDER);
560 // ShowWindow(GetDlgItem(hWndDlg,IDCANCEL),SW_HIDE);
563 bResult=TRUE; /* we don't do SetFocus */
566 PaintPattern(hWndDlg);
570 EndDialog(hWndDlg,LOWORD(wParam));
574 EndDialog(hWndDlg,IDCANCEL);
581 State=OldState; Rec--;
585 /* SUBDIALOG PROCEDURE */
586 BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
593 State=STATE_RECURS; Rec++;
594 if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,NULL);
598 /* subclass dialog window proc */
599 wndSubDlg = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc);
601 bResult=TRUE; /* we don't do SetFocus */
607 State=OldState; Rec--;
611 /********************/
612 /*** MAIN PROGRAM ***/
613 /********************/
619 wclass.style = CS_HREDRAW|CS_VREDRAW;
620 wclass.lpfnWndProc = MainWindowProc;
621 wclass.cbClsExtra = 0;
622 wclass.cbWndExtra = 0;
623 wclass.hInstance = hInst;
624 wclass.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(1));
625 wclass.hCursor = LoadCursor(0,IDC_ARROW);
626 wclass.hbrBackground = GetStockObject(WHITE_BRUSH);
627 wclass.lpszMenuName = NULL;
628 wclass.lpszClassName = wclassname;
629 if (!RegisterClass(&wclass)) return FALSE;
630 wclass.lpfnWndProc = SubWindowProc;
631 wclass.lpszClassName = wcclassname;
632 if (!RegisterClass(&wclass)) return FALSE;
636 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
637 LPSTR lpszCmdLine, int nCmdShow)
647 StartTime=GetTickCount();
648 hListBox = CreateWindow("LISTBOX","Messages",WS_BORDER|WS_VSCROLL|WS_CHILD|
649 LBS_HASSTRINGS|LBS_NOTIFY|LBS_WANTKEYBOARDINPUT,
650 0,0,0,0,GetDesktopWindow(),0,hInst,0);
652 MessageBox(0,"Could not create list box","Error",MB_OK);
656 hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE,
657 CW_USEDEFAULT,0,400,300,0,0,hInst,0);
658 if (!hMainWnd) return 0;
660 ShowWindow(hMainWnd,nCmdShow);
661 #ifdef TEST_DESTROY_MAIN
663 DestroyWindow(hMainWnd);
665 while (GetMessage(&msg,0,0,0)) {
666 TranslateMessage(&msg);
667 State=STATE_DISPATCH;
668 DispatchMessage(&msg);
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);
678 /* update, so no WM_PAINTs are pending */
680 // UpdateWindow(hMainWnd);
682 /* fill client area with a pattern */
683 FillPattern(hMainWnd,0);
684 /* create subwindow */
686 GetClientRect(hMainWnd,&rect);
687 hSubWnd = CreateWindow(wcclassname,winname,WS_CHILD|WS_BORDER|WS_CLIPSIBLINGS,
688 0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),hMainWnd,0,hInst,0);
689 if (!hSubWnd) return 0;
691 hButton[0] = CreateWindow("BUTTON","1",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE,
692 8,8,48,20,hMainWnd,0,hInst,0);
693 hButton[1] = CreateWindow("BUTTON","2",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE,
694 32,12,48,20,hMainWnd,0,hInst,0);
695 hButton[2] = CreateWindow("BUTTON","3",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE,
696 56,16,48,20,hMainWnd,0,hInst,0);
698 wndButton[0] = (WNDPROC)SetWindowLong(hButton[0],GWL_WNDPROC,(LONG)SubClassWindowProc);
699 wndButton[1] = (WNDPROC)SetWindowLong(hButton[1],GWL_WNDPROC,(LONG)SubClassWindowProc);
700 wndButton[2] = (WNDPROC)SetWindowLong(hButton[2],GWL_WNDPROC,(LONG)SubClassWindowProc);
703 UpdateWindow(hButton[0]);
704 LogChildOrder(hMainWnd);
705 Logf("but1 visible=%d",IsWindowVisible(hButton[0]));
707 /* now reparent the button to our (invisible) subwindow */
709 /* in different order, seeing who gets topmost */
710 SetParent(hButton[0],hSubWnd);
711 SetParent(hButton[2],hSubWnd);
712 SetParent(hButton[1],hSubWnd);
713 LogChildOrder(hSubWnd);
714 /* the button should now be invisible */
715 Logf("but1 visible=%d",IsWindowVisible(hButton[0]));
716 /* see if we can draw on them */
717 FillPattern(hButton[0],0);
721 ShowWindow(hSubWnd,SW_SHOWNORMAL);
723 UpdateWindow(hSubWnd);
724 FillPattern(hSubWnd,0);
725 // InvalidateRect(hMainWnd,NULL,TRUE);
726 Logf("but1 visible=%d",IsWindowVisible(hButton[0]));
731 DialogBox(hInst,MAKEINTRESOURCE(1),hMainWnd,(FARPROC)TestDialogProc);
736 CHOOSECOLOR cc={sizeof(cc),0,hInst,0,arr,0};
742 while (GetMessage(&msg,0,0,0)) {
743 TranslateMessage(&msg);
744 State=STATE_DISPATCH;
745 DispatchMessage(&msg);