| /* Windows GUI Behaviour Tester */ | 
 | /* by Ove Kåven */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <stdarg.h> | 
 | #include <windows.h> | 
 |  | 
 | #include "guitest.rh" | 
 |  | 
 | /* checks to include */ | 
 | #define LOGGING /* can be undefined under Wine and use -debugmsg +message instead */ | 
 | #define MAIN_STYLE WS_OVERLAPPEDWINDOW|WS_HSCROLL | 
 | #define MAIN_EXSTYLE 0 | 
 | #undef TEST_DESTROY_MAIN | 
 | #define SHOW_SUB | 
 | #undef TEST_DIALOG | 
 | #define RESIZE_DIALOG | 
 | #undef TEST_SUBDIALOG | 
 | #undef TEST_COMMCTL | 
 |  | 
 | /************************/ | 
 | /*** GLOBAL VARIABLES ***/ | 
 | /************************/ | 
 |  | 
 | HINSTANCE hInst; | 
 | DWORD StartTime; | 
 | HWND hListBox,hMainWnd,hSubWnd; | 
 | HWND hButton[4]={0,0,0,0}; | 
 | HWND hDialog=0,hGroup=0,hSubDlg=0; | 
 | WNDPROC wndButton[4],wndDialog,wndGroup,wndSubDlg; | 
 | BOOL Clicked=0,Ready=0; | 
 | int State=0,Rec=0; | 
 | #define STATE_CREATE 0 | 
 | #define STATE_DESTROY 1 | 
 | #define STATE_SHOW 2 | 
 | #define STATE_UPDATE 3 | 
 | #define STATE_DIALOG 4 | 
 | #define STATE_TEST 5 | 
 | #define STATE_DIRECT 6 | 
 | #define STATE_DISPATCH 7 | 
 | #define STATE_RECURS 8 | 
 | char*StateName[]={ | 
 |  "Creat", | 
 |  "Destr", | 
 |  "Show ", | 
 |  "Updat", | 
 |  "Dialg", | 
 |  "Test ", | 
 |  "Call ", | 
 |  "Disp ", | 
 |  "RCall" | 
 | }; | 
 |  | 
 | static char wclassname[] = "GUITestClass"; | 
 | static char wcclassname[] = "GUITestChildClass"; | 
 | static char winname[] = "GUITest"; | 
 |  | 
 | /**************************/ | 
 | /*** LOGGING FACILITIES ***/ | 
 | /**************************/ | 
 |  | 
 | struct MSGNAMES { | 
 |  int msg; | 
 |  char*name; | 
 | } MsgNames[]={ | 
 | #define MSG(x) {x,#x}, | 
 | #define MSG2(x,y) {y,#x}, | 
 | #define ENDMSG {0} | 
 |  | 
 | /* we get these in CreateWindow */ | 
 | MSG(WM_GETMINMAXINFO) | 
 | MSG(WM_NCCREATE) | 
 | MSG(WM_NCCALCSIZE) | 
 | MSG(WM_CREATE) | 
 | MSG(WM_PARENTNOTIFY) | 
 |  | 
 | /* we get these in ShowWindow */ | 
 | MSG(WM_SHOWWINDOW) | 
 | MSG(WM_WINDOWPOSCHANGING) | 
 | MSG(WM_QUERYNEWPALETTE) | 
 | MSG(WM_ACTIVATEAPP) | 
 | MSG(WM_NCACTIVATE) | 
 | MSG(WM_GETTEXT) | 
 | MSG(WM_ACTIVATE) | 
 | MSG(WM_SETFOCUS) | 
 | MSG(WM_NCPAINT) | 
 | MSG(WM_ERASEBKGND) | 
 | MSG(WM_WINDOWPOSCHANGED) | 
 | MSG(WM_SIZE) | 
 | MSG(WM_MOVE) | 
 |  | 
 | /* we get these in DestroyWindow */ | 
 | MSG(WM_KILLFOCUS) | 
 | MSG(WM_DESTROY) | 
 | MSG(WM_NCDESTROY) | 
 |  | 
 | /* we get these directly sent */ | 
 | MSG(WM_NCHITTEST) | 
 | MSG(WM_SETCURSOR) | 
 | MSG(WM_MOUSEACTIVATE) | 
 | MSG(WM_CHILDACTIVATE) | 
 | MSG(WM_COMMAND) | 
 | MSG(WM_SYSCOMMAND) | 
 |  | 
 | /* posted events */ | 
 | MSG(WM_MOUSEMOVE) | 
 | MSG(WM_NCMOUSEMOVE) | 
 | MSG(WM_PAINT) | 
 | MSG(WM_LBUTTONDOWN) | 
 | MSG(WM_LBUTTONUP) | 
 | MSG(WM_LBUTTONDBLCLK) | 
 | MSG(WM_NCLBUTTONDOWN) | 
 | MSG(WM_NCLBUTTONUP) | 
 | MSG(WM_NCLBUTTONDBLCLK) | 
 |  | 
 | MSG(WM_KEYDOWN) | 
 | MSG(WM_KEYUP) | 
 | MSG(WM_CHAR) | 
 |  | 
 | #ifdef WIN32 | 
 | MSG(WM_CTLCOLORBTN) | 
 | MSG(WM_CTLCOLORDLG) | 
 | MSG(WM_CTLCOLORSTATIC) | 
 | #else | 
 | MSG(WM_CTLCOLOR) | 
 | #endif | 
 |  | 
 | /* moving and sizing */ | 
 | MSG2(WM_ENTERSIZEMOVE,0x0231) | 
 | MSG2(WM_EXITSIZEMOVE,0x0232) | 
 | #ifdef WIN32 | 
 | MSG(WM_SIZING) | 
 | #endif | 
 |  | 
 | /* menus/dialog boxes */ | 
 | MSG(WM_CANCELMODE) | 
 | MSG(WM_ENABLE) | 
 | MSG(WM_SETFONT) | 
 | MSG(WM_INITDIALOG) | 
 | MSG(WM_GETDLGCODE) | 
 | MSG(WM_ENTERIDLE) | 
 |  | 
 | /* scroll bars */ | 
 | MSG(WM_HSCROLL) | 
 | MSG(WM_VSCROLL) | 
 |  | 
 | /* getting these from Wine but not from Windows */ | 
 | MSG2(WM_SETVISIBLE,0x0009) /* unheard of in BC++ 4.52 */ | 
 | #ifdef WIN32 | 
 | MSG(WM_CAPTURECHANGED) | 
 | #endif | 
 |  | 
 | ENDMSG}; | 
 |  | 
 | struct MSGNAMES ButMsgs[]={ | 
 | MSG(BM_SETSTATE) | 
 | MSG(BM_SETSTYLE) | 
 |  | 
 | ENDMSG}; | 
 |  | 
 | char*MsgName(UINT msg,HWND hWnd) | 
 | { | 
 |  int i; | 
 |  static char buffer[64],wclass[64]; | 
 |  GetClassName(hWnd,wclass,sizeof(wclass)); | 
 |  | 
 | #define MSGSEARCH(msgs) { \ | 
 |   for (i=0; msgs[i].name&&msgs[i].msg!=msg; i++); \ | 
 |   if (msgs[i].name) return msgs[i].name; \ | 
 |  } | 
 |  | 
 |  if (!stricmp(wclass,"Button")) MSGSEARCH(ButMsgs); | 
 |  MSGSEARCH(MsgNames); | 
 |  /* WM_USER */ | 
 |  if (msg>=WM_USER) { | 
 |   sprintf(buffer,"WM_USER+%04x{%s}",msg-WM_USER,wclass); | 
 |   return buffer; | 
 |  } | 
 |  /* message not found */ | 
 |  sprintf(buffer,"%04x{%s}",msg,wclass); | 
 |  return buffer; | 
 | } | 
 |  | 
 | char*WndName(HWND hWnd,int state) | 
 | { | 
 |  static char buffer[16]; | 
 |  if (!hWnd) return "0000"; | 
 |  if (hWnd==hMainWnd || (state==STATE_CREATE && !hMainWnd)) return "main"; | 
 |  if (hWnd==hSubWnd || (state==STATE_CREATE && !hSubWnd)) return "chld"; | 
 |  if (hWnd==hDialog || (state==STATE_DIALOG && !hDialog)) return "tdlg"; | 
 |  if (hWnd==hGroup) return "tgrp"; | 
 |  if (hWnd==hButton[0]) return "but1"; | 
 |  if (hWnd==hButton[1]) return "but2"; | 
 |  if (hWnd==hButton[2]) return "but3"; | 
 |  if (hWnd==hButton[3]) return "but4"; | 
 |  if (hWnd==hSubDlg || (state==STATE_CREATE && !hSubDlg)) return "sdlg"; | 
 |  if (hDialog) { | 
 |   int id=GetDlgCtrlID(hWnd); | 
 |   if (id) { | 
 |    sprintf(buffer,"dlgitem(%d)",id); | 
 |    return buffer; | 
 |   } | 
 |  } | 
 |  sprintf(buffer,"%04x",hWnd); | 
 |  return buffer; | 
 | } | 
 |  | 
 | void Log(const char*fmt) | 
 | { | 
 | #ifdef LOGGING | 
 |  if (!Clicked) SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)fmt); | 
 | #endif | 
 | } | 
 |  | 
 | void Logf(const char*fmt,...) | 
 | { | 
 |  va_list par; | 
 |  static char buffer[256]; | 
 |  | 
 |  va_start(par,fmt); | 
 |  vsprintf(buffer,fmt,par); | 
 |  va_end(par); | 
 |  Log(buffer); | 
 | } | 
 |  | 
 | void LogChildOrder(HWND hWnd) | 
 | { | 
 |  HWND hWndChild = GetWindow(hWnd,GW_CHILD); | 
 |  static char buffer[256]; | 
 |  | 
 |  strcpy(buffer,"child list:"); | 
 |  while (hWndChild) { | 
 |   strcat(strcat(buffer," "),WndName(hWndChild,State)); | 
 |   hWndChild=GetWindow(hWndChild,GW_HWNDNEXT); | 
 |  } | 
 |  Log(buffer); | 
 | } | 
 |  | 
 | void LogMessage(int state,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,char*name) | 
 | { | 
 |  static char buffer[256]; | 
 |  DWORD tick=GetTickCount()-StartTime; | 
 |  char*msgname=MsgName(msg,hWnd); | 
 |  if (!name) name=WndName(hWnd,state); | 
 |  switch (msg) { | 
 |   case WM_SETFOCUS: | 
 |   case WM_KILLFOCUS: | 
 |   case WM_SETCURSOR: | 
 |    Logf("%04d[%s(%d):%s]%s(%s,%08x)",tick,StateName[state],Rec, | 
 |         name,msgname,WndName((HWND)wParam,State),lParam); | 
 |    break; | 
 | #ifdef WIN32 | 
 |   case WM_ENTERIDLE: | 
 |   case WM_CTLCOLORBTN: | 
 |   case WM_CTLCOLORDLG: | 
 |    Logf("%04d[%s(%d):%s]%s(%08x,%s)",tick,StateName[state],Rec, | 
 |         name,msgname,wParam,WndName((HWND)lParam,State)); | 
 |    break; | 
 | #else | 
 |   case WM_ENTERIDLE: | 
 |   case WM_CTLCOLOR: | 
 |    Logf("%04d[%s(%d):%s]%s(%08x,%04x:%s)",tick,StateName[state],Rec, | 
 |         name,msgname,wParam,HIWORD(lParam),WndName((HWND)LOWORD(lParam),State)); | 
 |    break; | 
 | #endif | 
 |   case WM_WINDOWPOSCHANGING: | 
 |   case WM_WINDOWPOSCHANGED: | 
 |    { | 
 |     WINDOWPOS*pos=(WINDOWPOS*)lParam; | 
 | #ifdef WIN32 | 
 | 	 Logf("%04d[%s(%d):%s]%s(%08x,%p)",tick,StateName[state],Rec, | 
 | 			name,msgname,wParam,pos); | 
 | #else | 
 | 	 Logf("%04d[%s(%d):%s]%s(%04x,%p)",tick,StateName[state],Rec, | 
 | 			name,msgname,wParam,pos); | 
 | #endif | 
 | 	 strcpy(buffer,"FLAGS:"); | 
 | 	 if (pos->flags&SWP_DRAWFRAME) strcat(buffer," DRAWFRAME"); | 
 | 	 if (pos->flags&SWP_HIDEWINDOW) strcat(buffer," HIDEWINDOW"); | 
 | 	 if (pos->flags&SWP_NOACTIVATE) strcat(buffer," NOACTIVATE"); | 
 | 	 if (pos->flags&SWP_NOCOPYBITS) strcat(buffer," NOCOPYBITS"); | 
 | 	 if (pos->flags&SWP_NOMOVE) strcat(buffer," NOMOVE"); | 
 | 	 if (pos->flags&SWP_NOOWNERZORDER) strcat(buffer," NOOWNERZORDER"); | 
 | 	 if (pos->flags&SWP_NOSIZE) strcat(buffer," NOSIZE"); | 
 | 	 if (pos->flags&SWP_NOREDRAW) strcat(buffer," NOREDRAW"); | 
 | 	 if (pos->flags&SWP_NOZORDER) strcat(buffer," NOZORDER"); | 
 | 	 if (pos->flags&SWP_SHOWWINDOW) strcat(buffer," SHOWWINDOW"); | 
 | 	 Log(buffer); | 
 | 	} | 
 | 	break; | 
 |   case WM_SYSCOMMAND: | 
 | 	{ | 
 | 	 char*cmd=NULL; | 
 | 	 switch (wParam&0xFFF0) { | 
 | #define CASE(x) case SC_##x: cmd=#x; break; | 
 | 	  CASE(CLOSE) | 
 | 	  CASE(DEFAULT) | 
 | 	  CASE(HOTKEY) | 
 | 	  CASE(HSCROLL) | 
 | 	  CASE(KEYMENU) | 
 | 	  CASE(MAXIMIZE) | 
 | 	  CASE(MINIMIZE) | 
 | 	  CASE(MOUSEMENU) | 
 | 	  CASE(MOVE) | 
 | 	  CASE(NEXTWINDOW) | 
 | 	  CASE(PREVWINDOW) | 
 | 	  CASE(RESTORE) | 
 | 	  CASE(SCREENSAVE) | 
 | 	  CASE(SIZE) | 
 | 	  CASE(TASKLIST) | 
 | 	  CASE(VSCROLL) | 
 | #undef CASE | 
 | 	 } | 
 | 	 if (cmd) { | 
 | 	  Logf("%04d[%s(%d):%s]%s(%s+%x,%08x)",tick,StateName[state],Rec, | 
 | 			 name,msgname,cmd,wParam&0xF,lParam); | 
 | 	 } else goto GENERIC_MSG; | 
 | 	} | 
 | 	break; | 
 |   case WM_HSCROLL: | 
 |   case WM_VSCROLL: | 
 | 	{ | 
 | 	 char*cmd=NULL; | 
 | 	 switch (LOWORD(wParam)) { | 
 | #define CASE(x) case SB_##x: cmd=#x; break; | 
 | #define CASE2(h,v) case SB_##h: if (msg==WM_HSCROLL) cmd=#h; else cmd=#v; break; | 
 | 	  CASE(BOTTOM) | 
 | 	  CASE(ENDSCROLL) | 
 | 	  CASE2(LINELEFT,LINEUP) | 
 | 	  CASE2(LINERIGHT,LINEDOWN) | 
 | 	  CASE2(PAGELEFT,PAGEUP) | 
 | 	  CASE2(PAGERIGHT,PAGEDOWN) | 
 | 	  CASE(THUMBPOSITION) | 
 | 	  CASE(THUMBTRACK) | 
 |      CASE(TOP) | 
 | #undef CASE | 
 | 	 } | 
 | 	 if (cmd) { | 
 | #ifdef WIN32 | 
 | 	  Logf("%04d[%s(%d):%s]%s(%s,%04x,%s)",tick,StateName[state],Rec, | 
 | 			 name,msgname,cmd,HIWORD(wParam),WndName((HWND)lParam,State)); | 
 | #else | 
 | 	  Logf("%04d[%s(%d):%s]%s(%04x,%04x,%s)",tick,StateName[state],Rec, | 
 | 			 name,msgname,cmd,LOWORD(lParam),WndName((HWND)HIWORD(lParam),State)); | 
 | #endif | 
 | 	 } else goto GENERIC_MSG; | 
 | 	} | 
 | 	break; | 
 |   default: | 
 | GENERIC_MSG: | 
 | #ifdef WIN32 | 
 | 	Logf("%04d[%s(%d):%s]%s(%08x,%08x)",tick,StateName[state],Rec, | 
 | 		  name,msgname,wParam,lParam); | 
 | #else | 
 | 	Logf("%04d[%s(%d):%s]%s(%04x,%08x)",tick,StateName[state],Rec, | 
 | 		  name,msgname,wParam,lParam); | 
 | #endif | 
 |  } | 
 | } | 
 |  | 
 | /***************************/ | 
 | /*** GRAPHICS FACILITIES ***/ | 
 | /***************************/ | 
 |  | 
 | void Paint(HWND hWnd) | 
 | { | 
 |  HDC dc; | 
 |  PAINTSTRUCT ps; | 
 |  dc=BeginPaint(hWnd,&ps); | 
 |  EndPaint(hWnd,&ps); | 
 | } | 
 |  | 
 | void FillPattern(HWND hWnd,HDC pdc) | 
 | { | 
 |  HDC dc=pdc?pdc:GetDC(hWnd); | 
 |  HBRUSH oldbrush; | 
 |  RECT rect; | 
 |  if (!dc) { | 
 |   Logf("failed to acquire DC for window %s",WndName(hWnd,State)); | 
 |   return; | 
 |  } else { | 
 |   Logf("acquired DC for %s window %s, painting", | 
 |        IsWindowVisible(hWnd)?"visible":"invisible",WndName(hWnd,State)); | 
 |  } | 
 |  GetClientRect(hWnd,&rect); | 
 |  oldbrush=SelectObject(dc,GetStockObject(LTGRAY_BRUSH)); | 
 |  PatBlt(dc,0,0,rect.right,rect.bottom,PATCOPY); | 
 |  SelectObject(dc,oldbrush); | 
 |  if (!pdc) ReleaseDC(hWnd,dc); | 
 | } | 
 |  | 
 | void PaintPattern(HWND hWnd) | 
 | { | 
 |  HDC dc; | 
 |  PAINTSTRUCT ps; | 
 |  dc=BeginPaint(hWnd,&ps); | 
 |  FillPattern(hWnd,dc); | 
 |  EndPaint(hWnd,&ps); | 
 | } | 
 |  | 
 | /*************************/ | 
 | /*** WINDOW PROCEDURES ***/ | 
 | /*************************/ | 
 |  | 
 | /* MAIN WINDOW */ | 
 | LRESULT FAR CALLBACK _export MainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |  LRESULT lResult=0; | 
 |  RECT rect; | 
 |  int OldState=State; | 
 |  | 
 |  State=STATE_RECURS; Rec++; | 
 |  if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL); | 
 |  switch (msg) { | 
 |   case WM_NCHITTEST: | 
 |    lResult=DefWindowProc(hWnd,msg,wParam,lParam); | 
 |    break; | 
 |   case WM_LBUTTONDOWN: | 
 |   case WM_CHAR: | 
 |    if (!Clicked) { | 
 |     SetParent(hListBox,hWnd); | 
 |     GetClientRect(hWnd,&rect); | 
 |     MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE); | 
 |     ShowWindow(hListBox,SW_SHOW); | 
 |     SetFocus(hListBox); | 
 |     Clicked=TRUE; | 
 |    } | 
 |    break; | 
 |   case WM_SIZE: | 
 |    GetClientRect(hWnd,&rect); | 
 |    if (Clicked) { | 
 |     MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE); | 
 |    } | 
 |    MoveWindow(hSubWnd,0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),TRUE); | 
 |    break; | 
 |   case WM_PAINT: | 
 |    Paint(hWnd); | 
 |    break; | 
 |   case WM_DESTROY: | 
 |    PostQuitMessage(0); | 
 |    break; | 
 |   default: | 
 |    lResult=DefWindowProc(hWnd,msg,wParam,lParam); | 
 |  } | 
 |  State=OldState; Rec--; | 
 |  return lResult; | 
 | } | 
 |  | 
 | /* CHILD WINDOW */ | 
 | LRESULT FAR CALLBACK _export SubWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |  LRESULT lResult=0; | 
 |  RECT rect; | 
 |  int OldState=State; | 
 |  | 
 |  State=STATE_RECURS; Rec++; | 
 |  if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL); | 
 |  switch (msg) { | 
 |   case WM_PAINT: | 
 |    Paint(hWnd); | 
 |    break; | 
 |   default: | 
 |    lResult=DefWindowProc(hWnd,msg,wParam,lParam); | 
 |  } | 
 |  State=OldState; Rec--; | 
 |  return lResult; | 
 | } | 
 |  | 
 | BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam); | 
 |  | 
 | /* SUBCLASSED CONTROLS */ | 
 | LRESULT FAR CALLBACK _export SubClassWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |  LRESULT lResult=0; | 
 |  RECT rect; | 
 |  int OldState=State; | 
 |  int But=-1; | 
 |  | 
 |  if (hWnd==hButton[0]) But=0; else | 
 |  if (hWnd==hButton[1]) But=1; else | 
 |  if (hWnd==hButton[2]) But=2; else | 
 |  if (hWnd==hButton[3]) But=3; | 
 |  | 
 |  State=STATE_RECURS; Rec++; | 
 |  if (!Clicked) { | 
 |   LogMessage(OldState,hWnd,msg,wParam,lParam,NULL); | 
 |   if (But!=-1) { | 
 |    lResult=CallWindowProc((FARPROC)wndButton[But],hWnd,msg,wParam,lParam); | 
 |    if (msg==WM_LBUTTONUP) { | 
 |     LogChildOrder(GetParent(hWnd)); | 
 |    } | 
 |   } | 
 |   else if (hWnd==hDialog) { | 
 |    lResult=CallWindowProc((FARPROC)wndDialog,hWnd,msg,wParam,lParam); | 
 |   } | 
 |   else if (hWnd==hSubDlg) { | 
 |    lResult=CallWindowProc((FARPROC)wndSubDlg,hWnd,msg,wParam,lParam); | 
 |   } | 
 |   else if (hWnd==hGroup) { | 
 |    lResult=CallWindowProc((FARPROC)wndGroup,hWnd,msg,wParam,lParam); | 
 |    if (msg==WM_SETFOCUS) { | 
 |     /* create subdialog */ | 
 |     if (hSubDlg) { | 
 | #if 0 | 
 |      SetRect(&rect,0,0,1,1); | 
 |      InvalidateRect(hWnd,&rect,FALSE); | 
 | #endif | 
 |     } else { | 
 | #ifdef TEST_SUBDIALOG | 
 |      State=STATE_CREATE; | 
 |      hSubDlg=CreateDialog(hInst,MAKEINTRESOURCE(2),hWnd,(FARPROC)SubDialogProc); | 
 |      State=STATE_RECURS; | 
 | #else | 
 | #ifdef RESIZE_DIALOG | 
 |      GetWindowRect(GetParent(hWnd),&rect); | 
 |      rect.right++; | 
 |      SetWindowPos(GetParent(hWnd),0,0,0, | 
 |                   rect.right-rect.left,rect.bottom-rect.top, | 
 |                   SWP_NOMOVE|SWP_NOZORDER); | 
 | #endif | 
 | #endif | 
 |     } | 
 |    } | 
 |   } | 
 |  } | 
 |  State=OldState; Rec--; | 
 |  return lResult; | 
 | } | 
 |  | 
 | /* MAIN DIALOG PROCEDURE */ | 
 | BOOL FAR CALLBACK _export TestDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |  BOOL bResult=0; | 
 |  RECT rect; | 
 |  int OldState=State; | 
 |  int But=-1; | 
 |  | 
 |  State=STATE_RECURS; Rec++; | 
 |  if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,"dlgp"); | 
 |  switch (msg) { | 
 |   case WM_INITDIALOG: | 
 |    hDialog = hWndDlg; | 
 |    /* subclass dialog window proc */ | 
 |    wndDialog = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 |    Logf("dialog visible=%s",IsWindowVisible(hWndDlg)?"TRUE":"FALSE"); | 
 |    /* subclass OK button */ | 
 |    hButton[3] = GetDlgItem(hWndDlg,IDOK); | 
 |    wndButton[3] = (WNDPROC)SetWindowLong(hButton[3],GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 |    /* subclass group box */ | 
 |    hGroup = GetDlgItem(hWndDlg,IDC_GROUPBOX1); | 
 |    wndGroup = (WNDPROC)SetWindowLong(hGroup,GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 |  | 
 | #ifdef RESIZE_DIALOG | 
 |    GetWindowRect(hWndDlg,&rect); | 
 |    rect.right--; | 
 |    SetWindowPos(hWndDlg,0,0,0, | 
 |                 rect.right-rect.left,rect.bottom-rect.top, | 
 |                 SWP_NOMOVE|SWP_NOZORDER); | 
 | //   ShowWindow(GetDlgItem(hWndDlg,IDCANCEL),SW_HIDE); | 
 | #endif | 
 |  | 
 |    bResult=TRUE; /* we don't do SetFocus */ | 
 |    break; | 
 |   case WM_PAINT: | 
 |    PaintPattern(hWndDlg); | 
 |    bResult=TRUE; | 
 |    break; | 
 |   case WM_COMMAND: | 
 |    EndDialog(hWndDlg,LOWORD(wParam)); | 
 |    bResult=TRUE; | 
 |    break; | 
 |   case WM_CLOSE: | 
 |    EndDialog(hWndDlg,IDCANCEL); | 
 |    bResult=TRUE; | 
 |    break; | 
 |   case WM_NCDESTROY: | 
 |    hDialog = 0; | 
 |    break; | 
 |  } | 
 |  State=OldState; Rec--; | 
 |  return bResult; | 
 | } | 
 |  | 
 | /* SUBDIALOG PROCEDURE */ | 
 | BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |  BOOL bResult=0; | 
 |  RECT rect; | 
 |  int OldState=State; | 
 |  int But=-1; | 
 |  | 
 |  State=STATE_RECURS; Rec++; | 
 |  if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,NULL); | 
 |  switch (msg) { | 
 |   case WM_INITDIALOG: | 
 |    hSubDlg = hWndDlg; | 
 |    /* subclass dialog window proc */ | 
 |    wndSubDlg = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 |  | 
 |    bResult=TRUE; /* we don't do SetFocus */ | 
 |    break; | 
 |   case WM_NCDESTROY: | 
 |    hSubDlg = 0; | 
 |    break; | 
 |  } | 
 |  State=OldState; Rec--; | 
 |  return bResult; | 
 | } | 
 |  | 
 | /********************/ | 
 | /*** MAIN PROGRAM ***/ | 
 | /********************/ | 
 |  | 
 | BOOL AppInit(void) | 
 | { | 
 |  WNDCLASS wclass; | 
 |  | 
 |  wclass.style = CS_HREDRAW|CS_VREDRAW; | 
 |  wclass.lpfnWndProc = MainWindowProc; | 
 |  wclass.cbClsExtra = 0; | 
 |  wclass.cbWndExtra = 0; | 
 |  wclass.hInstance = hInst; | 
 |  wclass.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(1)); | 
 |  wclass.hCursor = LoadCursor(0,IDC_ARROW); | 
 |  wclass.hbrBackground = GetStockObject(WHITE_BRUSH); | 
 |  wclass.lpszMenuName = NULL; | 
 |  wclass.lpszClassName = wclassname; | 
 |  if (!RegisterClass(&wclass)) return FALSE; | 
 |  wclass.lpfnWndProc = SubWindowProc; | 
 |  wclass.lpszClassName = wcclassname; | 
 |  if (!RegisterClass(&wclass)) return FALSE; | 
 |  return TRUE; | 
 | } | 
 |  | 
 | int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | 
 |                    LPSTR lpszCmdLine, int nCmdShow) | 
 | { | 
 |  MSG msg; | 
 |  RECT rect; | 
 |  | 
 |  hInst = hInstance; | 
 |  if (!hPrevInstance) | 
 |   if (!AppInit()) | 
 |    return 0; | 
 |  | 
 |  StartTime=GetTickCount(); | 
 |  hListBox = CreateWindow("LISTBOX","Messages",WS_BORDER|WS_VSCROLL|WS_CHILD| | 
 |                                               LBS_HASSTRINGS|LBS_NOTIFY|LBS_WANTKEYBOARDINPUT, | 
 |                          0,0,0,0,GetDesktopWindow(),0,hInst,0); | 
 |  if (!hListBox) { | 
 |   MessageBox(0,"Could not create list box","Error",MB_OK); | 
 |  } | 
 |  | 
 |  State=STATE_CREATE; | 
 |  hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE, | 
 |                            CW_USEDEFAULT,0,400,300,0,0,hInst,0); | 
 |  if (!hMainWnd) return 0; | 
 |  State=STATE_SHOW; | 
 |  ShowWindow(hMainWnd,nCmdShow); | 
 | #ifdef TEST_DESTROY_MAIN | 
 |  State=STATE_DESTROY; | 
 |  DestroyWindow(hMainWnd); | 
 |  State=STATE_DIRECT; | 
 |  while (GetMessage(&msg,0,0,0)) { | 
 |   TranslateMessage(&msg); | 
 |   State=STATE_DISPATCH; | 
 |   DispatchMessage(&msg); | 
 |   State=STATE_DIRECT; | 
 |  } | 
 |  State=STATE_CREATE; | 
 |  hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE, | 
 |                            CW_USEDEFAULT,0,400,300,0,0,hInst,0); | 
 |  if (!hMainWnd) return 0; | 
 |  State=STATE_SHOW; | 
 |  ShowWindow(hMainWnd,nCmdShow); | 
 | #endif | 
 | /* update, so no WM_PAINTs are pending */ | 
 |  State=STATE_UPDATE; | 
 | // UpdateWindow(hMainWnd); | 
 |  Ready=TRUE; | 
 | /* fill client area with a pattern */ | 
 |  FillPattern(hMainWnd,0); | 
 | /* create subwindow */ | 
 |  State=STATE_CREATE; | 
 |  GetClientRect(hMainWnd,&rect); | 
 |  hSubWnd = CreateWindow(wcclassname,winname,WS_CHILD|WS_BORDER|WS_CLIPSIBLINGS, | 
 |                         0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),hMainWnd,0,hInst,0); | 
 |  if (!hSubWnd) return 0; | 
 | /* create buttons */ | 
 |  hButton[0] = CreateWindow("BUTTON","1",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE, | 
 |                            8,8,48,20,hMainWnd,0,hInst,0); | 
 |  hButton[1] = CreateWindow("BUTTON","2",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE, | 
 |                            32,12,48,20,hMainWnd,0,hInst,0); | 
 |  hButton[2] = CreateWindow("BUTTON","3",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE, | 
 |                            56,16,48,20,hMainWnd,0,hInst,0); | 
 | /* subclass them */ | 
 |  wndButton[0] = (WNDPROC)SetWindowLong(hButton[0],GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 |  wndButton[1] = (WNDPROC)SetWindowLong(hButton[1],GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 |  wndButton[2] = (WNDPROC)SetWindowLong(hButton[2],GWL_WNDPROC,(LONG)SubClassWindowProc); | 
 | /* show them */ | 
 |  State=STATE_UPDATE; | 
 |  UpdateWindow(hButton[0]); | 
 |  LogChildOrder(hMainWnd); | 
 |  Logf("but1 visible=%d",IsWindowVisible(hButton[0])); | 
 |  | 
 | /* now reparent the button to our (invisible) subwindow */ | 
 |  State=STATE_TEST; | 
 |  /* in different order, seeing who gets topmost */ | 
 |  SetParent(hButton[0],hSubWnd); | 
 |  SetParent(hButton[2],hSubWnd); | 
 |  SetParent(hButton[1],hSubWnd); | 
 |  LogChildOrder(hSubWnd); | 
 | /* the button should now be invisible */ | 
 |  Logf("but1 visible=%d",IsWindowVisible(hButton[0])); | 
 | /* see if we can draw on them */ | 
 |  FillPattern(hButton[0],0); | 
 |  | 
 | #ifdef SHOW_SUB | 
 |  State=STATE_SHOW; | 
 |  ShowWindow(hSubWnd,SW_SHOWNORMAL); | 
 |  State=STATE_UPDATE; | 
 |  UpdateWindow(hSubWnd); | 
 |  FillPattern(hSubWnd,0); | 
 | // InvalidateRect(hMainWnd,NULL,TRUE); | 
 |  Logf("but1 visible=%d",IsWindowVisible(hButton[0])); | 
 | #endif | 
 |  | 
 | #ifdef TEST_DIALOG | 
 |  State=STATE_DIALOG; | 
 |  DialogBox(hInst,MAKEINTRESOURCE(1),hMainWnd,(FARPROC)TestDialogProc); | 
 | #endif | 
 | #ifdef TEST_COMMCTL | 
 |  { | 
 |   DWORD arr[16]; | 
 |   CHOOSECOLOR cc={sizeof(cc),0,hInst,0,arr,0}; | 
 |   ChooseColor(&cc); | 
 |  } | 
 | #endif | 
 |  | 
 |  State=STATE_DIRECT; | 
 |  while (GetMessage(&msg,0,0,0)) { | 
 |   TranslateMessage(&msg); | 
 |   State=STATE_DISPATCH; | 
 |   DispatchMessage(&msg); | 
 |   State=STATE_DIRECT; | 
 |  } | 
 |  return 0; | 
 | } | 
 |  | 
 |  |