| /* 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; | |
| } | |