Added check for sys/mman.h.
[wine] / libtest / guitest.c
1 /* Windows GUI Behaviour Tester
2  *
3  * Copyright 1999 Ove Kåven
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <windows.h>
24
25 #include "guitest.rh"
26
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
32 #define SHOW_SUB
33 #undef TEST_DIALOG
34 #define RESIZE_DIALOG
35 #undef TEST_SUBDIALOG
36 #undef TEST_COMMCTL
37
38 /************************/
39 /*** GLOBAL VARIABLES ***/
40 /************************/
41
42 HINSTANCE hInst;
43 DWORD StartTime;
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;
49 int State=0,Rec=0;
50 #define STATE_CREATE 0
51 #define STATE_DESTROY 1
52 #define STATE_SHOW 2
53 #define STATE_UPDATE 3
54 #define STATE_DIALOG 4
55 #define STATE_TEST 5
56 #define STATE_DIRECT 6
57 #define STATE_DISPATCH 7
58 #define STATE_RECURS 8
59 char*StateName[]={
60  "Creat",
61  "Destr",
62  "Show ",
63  "Updat",
64  "Dialg",
65  "Test ",
66  "Call ",
67  "Disp ",
68  "RCall"
69 };
70
71 static char wclassname[] = "GUITestClass";
72 static char wcclassname[] = "GUITestChildClass";
73 static char winname[] = "GUITest";
74
75 /**************************/
76 /*** LOGGING FACILITIES ***/
77 /**************************/
78
79 struct MSGNAMES {
80  int msg;
81  char*name;
82 } MsgNames[]={
83 #define MSG(x) {x,#x},
84 #define MSG2(x,y) {y,#x},
85 #define ENDMSG {0}
86
87 /* we get these in CreateWindow */
88 MSG(WM_GETMINMAXINFO)
89 MSG(WM_NCCREATE)
90 MSG(WM_NCCALCSIZE)
91 MSG(WM_CREATE)
92 MSG(WM_PARENTNOTIFY)
93
94 /* we get these in ShowWindow */
95 MSG(WM_SHOWWINDOW)
96 MSG(WM_WINDOWPOSCHANGING)
97 MSG(WM_QUERYNEWPALETTE)
98 MSG(WM_ACTIVATEAPP)
99 MSG(WM_NCACTIVATE)
100 MSG(WM_GETTEXT)
101 MSG(WM_ACTIVATE)
102 MSG(WM_SETFOCUS)
103 MSG(WM_NCPAINT)
104 MSG(WM_ERASEBKGND)
105 MSG(WM_WINDOWPOSCHANGED)
106 MSG(WM_SIZE)
107 MSG(WM_MOVE)
108
109 /* we get these in DestroyWindow */
110 MSG(WM_KILLFOCUS)
111 MSG(WM_DESTROY)
112 MSG(WM_NCDESTROY)
113
114 /* we get these directly sent */
115 MSG(WM_NCHITTEST)
116 MSG(WM_SETCURSOR)
117 MSG(WM_MOUSEACTIVATE)
118 MSG(WM_CHILDACTIVATE)
119 MSG(WM_COMMAND)
120 MSG(WM_SYSCOMMAND)
121
122 /* posted events */
123 MSG(WM_MOUSEMOVE)
124 MSG(WM_NCMOUSEMOVE)
125 MSG(WM_PAINT)
126 MSG(WM_LBUTTONDOWN)
127 MSG(WM_LBUTTONUP)
128 MSG(WM_LBUTTONDBLCLK)
129 MSG(WM_NCLBUTTONDOWN)
130 MSG(WM_NCLBUTTONUP)
131 MSG(WM_NCLBUTTONDBLCLK)
132
133 MSG(WM_KEYDOWN)
134 MSG(WM_KEYUP)
135 MSG(WM_CHAR)
136
137 #ifdef WIN32
138 MSG(WM_CTLCOLORBTN)
139 MSG(WM_CTLCOLORDLG)
140 MSG(WM_CTLCOLORSTATIC)
141 #else
142 MSG(WM_CTLCOLOR)
143 #endif
144
145 /* moving and sizing */
146 MSG2(WM_ENTERSIZEMOVE,0x0231)
147 MSG2(WM_EXITSIZEMOVE,0x0232)
148 #ifdef WIN32
149 MSG(WM_SIZING)
150 #endif
151
152 /* menus/dialog boxes */
153 MSG(WM_CANCELMODE)
154 MSG(WM_ENABLE)
155 MSG(WM_SETFONT)
156 MSG(WM_INITDIALOG)
157 MSG(WM_GETDLGCODE)
158 MSG(WM_ENTERIDLE)
159
160 /* scroll bars */
161 MSG(WM_HSCROLL)
162 MSG(WM_VSCROLL)
163
164 /* getting these from Wine but not from Windows */
165 MSG2(WM_SETVISIBLE,0x0009) /* unheard of in BC++ 4.52 */
166 #ifdef WIN32
167 MSG(WM_CAPTURECHANGED)
168 #endif
169
170 ENDMSG};
171
172 struct MSGNAMES ButMsgs[]={
173 MSG(BM_SETSTATE)
174 MSG(BM_SETSTYLE)
175
176 ENDMSG};
177
178 char*MsgName(UINT msg,HWND hWnd)
179 {
180  int i;
181  static char buffer[64],wclass[64];
182  GetClassName(hWnd,wclass,sizeof(wclass));
183
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; \
187  }
188
189  if (!stricmp(wclass,"Button")) MSGSEARCH(ButMsgs);
190  MSGSEARCH(MsgNames);
191  /* WM_USER */
192  if (msg>=WM_USER) {
193   sprintf(buffer,"WM_USER+%04x{%s}",msg-WM_USER,wclass);
194   return buffer;
195  }
196  /* message not found */
197  sprintf(buffer,"%04x{%s}",msg,wclass);
198  return buffer;
199 }
200
201 char*WndName(HWND hWnd,int state)
202 {
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";
214  if (hDialog) {
215   int id=GetDlgCtrlID(hWnd);
216   if (id) {
217    sprintf(buffer,"dlgitem(%d)",id);
218    return buffer;
219   }
220  }
221  sprintf(buffer,"%04x",hWnd);
222  return buffer;
223 }
224
225 void Log(const char*fmt)
226 {
227 #ifdef LOGGING
228  if (!Clicked) SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)fmt);
229 #endif
230 }
231
232 void Logf(const char*fmt,...)
233 {
234  va_list par;
235  static char buffer[256];
236
237  va_start(par,fmt);
238  vsprintf(buffer,fmt,par);
239  va_end(par);
240  Log(buffer);
241 }
242
243 void LogChildOrder(HWND hWnd)
244 {
245  HWND hWndChild = GetWindow(hWnd,GW_CHILD);
246  static char buffer[256];
247
248  strcpy(buffer,"child list:");
249  while (hWndChild) {
250   strcat(strcat(buffer," "),WndName(hWndChild,State));
251   hWndChild=GetWindow(hWndChild,GW_HWNDNEXT);
252  }
253  Log(buffer);
254 }
255
256 void LogMessage(int state,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,char*name)
257 {
258  static char buffer[256];
259  DWORD tick=GetTickCount()-StartTime;
260  char*msgname=MsgName(msg,hWnd);
261  if (!name) name=WndName(hWnd,state);
262  switch (msg) {
263   case WM_SETFOCUS:
264   case WM_KILLFOCUS:
265   case WM_SETCURSOR:
266    Logf("%04d[%s(%d):%s]%s(%s,%08x)",tick,StateName[state],Rec,
267         name,msgname,WndName((HWND)wParam,State),lParam);
268    break;
269 #ifdef WIN32
270   case WM_ENTERIDLE:
271   case WM_CTLCOLORBTN:
272   case WM_CTLCOLORDLG:
273    Logf("%04d[%s(%d):%s]%s(%08x,%s)",tick,StateName[state],Rec,
274         name,msgname,wParam,WndName((HWND)lParam,State));
275    break;
276 #else
277   case WM_ENTERIDLE:
278   case WM_CTLCOLOR:
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));
281    break;
282 #endif
283   case WM_WINDOWPOSCHANGING:
284   case WM_WINDOWPOSCHANGED:
285    {
286     WINDOWPOS*pos=(WINDOWPOS*)lParam;
287 #ifdef WIN32
288          Logf("%04d[%s(%d):%s]%s(%08x,%p)",tick,StateName[state],Rec,
289                         name,msgname,wParam,pos);
290 #else
291          Logf("%04d[%s(%d):%s]%s(%04x,%p)",tick,StateName[state],Rec,
292                         name,msgname,wParam,pos);
293 #endif
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");
305          Log(buffer);
306         }
307         break;
308   case WM_SYSCOMMAND:
309         {
310          char*cmd=NULL;
311          switch (wParam&0xFFF0) {
312 #define CASE(x) case SC_##x: cmd=#x; break;
313           CASE(CLOSE)
314           CASE(DEFAULT)
315           CASE(HOTKEY)
316           CASE(HSCROLL)
317           CASE(KEYMENU)
318           CASE(MAXIMIZE)
319           CASE(MINIMIZE)
320           CASE(MOUSEMENU)
321           CASE(MOVE)
322           CASE(NEXTWINDOW)
323           CASE(PREVWINDOW)
324           CASE(RESTORE)
325           CASE(SCREENSAVE)
326           CASE(SIZE)
327           CASE(TASKLIST)
328           CASE(VSCROLL)
329 #undef CASE
330          }
331          if (cmd) {
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;
335         }
336         break;
337   case WM_HSCROLL:
338   case WM_VSCROLL:
339         {
340          char*cmd=NULL;
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;
344           CASE(BOTTOM)
345           CASE(ENDSCROLL)
346           CASE2(LINELEFT,LINEUP)
347           CASE2(LINERIGHT,LINEDOWN)
348           CASE2(PAGELEFT,PAGEUP)
349           CASE2(PAGERIGHT,PAGEDOWN)
350           CASE(THUMBPOSITION)
351           CASE(THUMBTRACK)
352      CASE(TOP)
353 #undef CASE
354          }
355          if (cmd) {
356 #ifdef WIN32
357           Logf("%04d[%s(%d):%s]%s(%s,%04x,%s)",tick,StateName[state],Rec,
358                          name,msgname,cmd,HIWORD(wParam),WndName((HWND)lParam,State));
359 #else
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));
362 #endif
363          } else goto GENERIC_MSG;
364         }
365         break;
366   default:
367 GENERIC_MSG:
368 #ifdef WIN32
369         Logf("%04d[%s(%d):%s]%s(%08x,%08x)",tick,StateName[state],Rec,
370                   name,msgname,wParam,lParam);
371 #else
372         Logf("%04d[%s(%d):%s]%s(%04x,%08x)",tick,StateName[state],Rec,
373                   name,msgname,wParam,lParam);
374 #endif
375  }
376 }
377
378 /***************************/
379 /*** GRAPHICS FACILITIES ***/
380 /***************************/
381
382 void Paint(HWND hWnd)
383 {
384  HDC dc;
385  PAINTSTRUCT ps;
386  dc=BeginPaint(hWnd,&ps);
387  EndPaint(hWnd,&ps);
388 }
389
390 void FillPattern(HWND hWnd,HDC pdc)
391 {
392  HDC dc=pdc?pdc:GetDC(hWnd);
393  HBRUSH oldbrush;
394  RECT rect;
395  if (!dc) {
396   Logf("failed to acquire DC for window %s",WndName(hWnd,State));
397   return;
398  } else {
399   Logf("acquired DC for %s window %s, painting",
400        IsWindowVisible(hWnd)?"visible":"invisible",WndName(hWnd,State));
401  }
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);
407 }
408
409 void PaintPattern(HWND hWnd)
410 {
411  HDC dc;
412  PAINTSTRUCT ps;
413  dc=BeginPaint(hWnd,&ps);
414  FillPattern(hWnd,dc);
415  EndPaint(hWnd,&ps);
416 }
417
418 /*************************/
419 /*** WINDOW PROCEDURES ***/
420 /*************************/
421
422 /* MAIN WINDOW */
423 LRESULT FAR CALLBACK _export MainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
424 {
425  LRESULT lResult=0;
426  RECT rect;
427  int OldState=State;
428
429  State=STATE_RECURS; Rec++;
430  if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL);
431  switch (msg) {
432   case WM_NCHITTEST:
433    lResult=DefWindowProc(hWnd,msg,wParam,lParam);
434    break;
435   case WM_LBUTTONDOWN:
436   case WM_CHAR:
437    if (!Clicked) {
438     SetParent(hListBox,hWnd);
439     GetClientRect(hWnd,&rect);
440     MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE);
441     ShowWindow(hListBox,SW_SHOW);
442     SetFocus(hListBox);
443     Clicked=TRUE;
444    }
445    break;
446   case WM_SIZE:
447    GetClientRect(hWnd,&rect);
448    if (Clicked) {
449     MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE);
450    }
451    MoveWindow(hSubWnd,0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),TRUE);
452    break;
453   case WM_PAINT:
454    Paint(hWnd);
455    break;
456   case WM_DESTROY:
457    PostQuitMessage(0);
458    break;
459   default:
460    lResult=DefWindowProc(hWnd,msg,wParam,lParam);
461  }
462  State=OldState; Rec--;
463  return lResult;
464 }
465
466 /* CHILD WINDOW */
467 LRESULT FAR CALLBACK _export SubWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
468 {
469  LRESULT lResult=0;
470  RECT rect;
471  int OldState=State;
472
473  State=STATE_RECURS; Rec++;
474  if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL);
475  switch (msg) {
476   case WM_PAINT:
477    Paint(hWnd);
478    break;
479   default:
480    lResult=DefWindowProc(hWnd,msg,wParam,lParam);
481  }
482  State=OldState; Rec--;
483  return lResult;
484 }
485
486 BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
487
488 /* SUBCLASSED CONTROLS */
489 LRESULT FAR CALLBACK _export SubClassWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
490 {
491  LRESULT lResult=0;
492  RECT rect;
493  int OldState=State;
494  int But=-1;
495
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;
500
501  State=STATE_RECURS; Rec++;
502  if (!Clicked) {
503   LogMessage(OldState,hWnd,msg,wParam,lParam,NULL);
504   if (But!=-1) {
505    lResult=CallWindowProc((FARPROC)wndButton[But],hWnd,msg,wParam,lParam);
506    if (msg==WM_LBUTTONUP) {
507     LogChildOrder(GetParent(hWnd));
508    }
509   }
510   else if (hWnd==hDialog) {
511    lResult=CallWindowProc((FARPROC)wndDialog,hWnd,msg,wParam,lParam);
512   }
513   else if (hWnd==hSubDlg) {
514    lResult=CallWindowProc((FARPROC)wndSubDlg,hWnd,msg,wParam,lParam);
515   }
516   else if (hWnd==hGroup) {
517    lResult=CallWindowProc((FARPROC)wndGroup,hWnd,msg,wParam,lParam);
518    if (msg==WM_SETFOCUS) {
519     /* create subdialog */
520     if (hSubDlg) {
521 #if 0
522      SetRect(&rect,0,0,1,1);
523      InvalidateRect(hWnd,&rect,FALSE);
524 #endif
525     } else {
526 #ifdef TEST_SUBDIALOG
527      State=STATE_CREATE;
528      hSubDlg=CreateDialog(hInst,MAKEINTRESOURCE(2),hWnd,(FARPROC)SubDialogProc);
529      State=STATE_RECURS;
530 #else
531 #ifdef RESIZE_DIALOG
532      GetWindowRect(GetParent(hWnd),&rect);
533      rect.right++;
534      SetWindowPos(GetParent(hWnd),0,0,0,
535                   rect.right-rect.left,rect.bottom-rect.top,
536                   SWP_NOMOVE|SWP_NOZORDER);
537 #endif
538 #endif
539     }
540    }
541   }
542  }
543  State=OldState; Rec--;
544  return lResult;
545 }
546
547 /* MAIN DIALOG PROCEDURE */
548 BOOL FAR CALLBACK _export TestDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
549 {
550  BOOL bResult=0;
551  RECT rect;
552  int OldState=State;
553  int But=-1;
554
555  State=STATE_RECURS; Rec++;
556  if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,"dlgp");
557  switch (msg) {
558   case WM_INITDIALOG:
559    hDialog = hWndDlg;
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);
569
570 #ifdef RESIZE_DIALOG
571    GetWindowRect(hWndDlg,&rect);
572    rect.right--;
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);
577 #endif
578
579    bResult=TRUE; /* we don't do SetFocus */
580    break;
581   case WM_PAINT:
582    PaintPattern(hWndDlg);
583    bResult=TRUE;
584    break;
585   case WM_COMMAND:
586    EndDialog(hWndDlg,LOWORD(wParam));
587    bResult=TRUE;
588    break;
589   case WM_CLOSE:
590    EndDialog(hWndDlg,IDCANCEL);
591    bResult=TRUE;
592    break;
593   case WM_NCDESTROY:
594    hDialog = 0;
595    break;
596  }
597  State=OldState; Rec--;
598  return bResult;
599 }
600
601 /* SUBDIALOG PROCEDURE */
602 BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
603 {
604  BOOL bResult=0;
605  RECT rect;
606  int OldState=State;
607  int But=-1;
608
609  State=STATE_RECURS; Rec++;
610  if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,NULL);
611  switch (msg) {
612   case WM_INITDIALOG:
613    hSubDlg = hWndDlg;
614    /* subclass dialog window proc */
615    wndSubDlg = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc);
616
617    bResult=TRUE; /* we don't do SetFocus */
618    break;
619   case WM_NCDESTROY:
620    hSubDlg = 0;
621    break;
622  }
623  State=OldState; Rec--;
624  return bResult;
625 }
626
627 /********************/
628 /*** MAIN PROGRAM ***/
629 /********************/
630
631 BOOL AppInit(void)
632 {
633  WNDCLASS wclass;
634
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;
649  return TRUE;
650 }
651
652 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
653                    LPSTR lpszCmdLine, int nCmdShow)
654 {
655  MSG msg;
656  RECT rect;
657
658  hInst = hInstance;
659  if (!hPrevInstance)
660   if (!AppInit())
661    return 0;
662
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);
667  if (!hListBox) {
668   MessageBox(0,"Could not create list box","Error",MB_OK);
669  }
670
671  State=STATE_CREATE;
672  hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE,
673                            CW_USEDEFAULT,0,400,300,0,0,hInst,0);
674  if (!hMainWnd) return 0;
675  State=STATE_SHOW;
676  ShowWindow(hMainWnd,nCmdShow);
677 #ifdef TEST_DESTROY_MAIN
678  State=STATE_DESTROY;
679  DestroyWindow(hMainWnd);
680  State=STATE_DIRECT;
681  while (GetMessage(&msg,0,0,0)) {
682   TranslateMessage(&msg);
683   State=STATE_DISPATCH;
684   DispatchMessage(&msg);
685   State=STATE_DIRECT;
686  }
687  State=STATE_CREATE;
688  hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE,
689                            CW_USEDEFAULT,0,400,300,0,0,hInst,0);
690  if (!hMainWnd) return 0;
691  State=STATE_SHOW;
692  ShowWindow(hMainWnd,nCmdShow);
693 #endif
694 /* update, so no WM_PAINTs are pending */
695  State=STATE_UPDATE;
696 // UpdateWindow(hMainWnd);
697  Ready=TRUE;
698 /* fill client area with a pattern */
699  FillPattern(hMainWnd,0);
700 /* create subwindow */
701  State=STATE_CREATE;
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;
706 /* create buttons */
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);
713 /* subclass them */
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);
717 /* show them */
718  State=STATE_UPDATE;
719  UpdateWindow(hButton[0]);
720  LogChildOrder(hMainWnd);
721  Logf("but1 visible=%d",IsWindowVisible(hButton[0]));
722
723 /* now reparent the button to our (invisible) subwindow */
724  State=STATE_TEST;
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);
734
735 #ifdef SHOW_SUB
736  State=STATE_SHOW;
737  ShowWindow(hSubWnd,SW_SHOWNORMAL);
738  State=STATE_UPDATE;
739  UpdateWindow(hSubWnd);
740  FillPattern(hSubWnd,0);
741 // InvalidateRect(hMainWnd,NULL,TRUE);
742  Logf("but1 visible=%d",IsWindowVisible(hButton[0]));
743 #endif
744
745 #ifdef TEST_DIALOG
746  State=STATE_DIALOG;
747  DialogBox(hInst,MAKEINTRESOURCE(1),hMainWnd,(FARPROC)TestDialogProc);
748 #endif
749 #ifdef TEST_COMMCTL
750  {
751   DWORD arr[16];
752   CHOOSECOLOR cc={sizeof(cc),0,hInst,0,arr,0};
753   ChooseColor(&cc);
754  }
755 #endif
756
757  State=STATE_DIRECT;
758  while (GetMessage(&msg,0,0,0)) {
759   TranslateMessage(&msg);
760   State=STATE_DISPATCH;
761   DispatchMessage(&msg);
762   State=STATE_DIRECT;
763  }
764  return 0;
765 }
766
767