_PROPVIEW: A FAMILY CLASS BROWSER_ by Mike Klein [LISTING ONE] /***************************************************************************** PROGRAM: PropView (c) 1991 All rights reserved AUTHOR: Mike Klein VERSION: 1.5 FILE: propview.exe REQUIREMENTS: Windows 3.x PURPOSE: Point to any window on screen, view info/properties, and send messages to window too. *****************************************************************************/ #define NOCOMM #include #include #include #include #include #include "propview.h" static HWND hDlgPropView; static HANDLE hInstPropView; static HWND hDlgActive; static HWND hWndTarget; static HWND hDlgChildren; static HWND hDlgProperties; static HWND hDlgSendMsg; static HWND hDlgExtraData; static HWND hDlgStyles; static BYTE Text[100]; static BOOL Capturing = FALSE; static FARPROC lpEnumWindowPropsProc; static FARPROC lpEnumChildrenProc; static BOOL ShowHex = TRUE; static BOOL ShowScreenCoord = TRUE; // Some internally used functions VOID PASCAL ExamineWindow(HWND); VOID PASCAL DrawIcons(VOID); VOID PASCAL OutlineWindow(HWND); VOID PASCAL UpdatePos(VOID); /***************************************************************************** FUNCTION: WinMain PURPOSE : Calls initialization function, processes message loop *****************************************************************************/ int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; MSG msg; int ChildTabs[3]; int PropTab; int hFile; BYTE Msg[81]; BYTE Hex[5]; OFSTRUCT OFstruct; // See if a version of Propview is already running if(!hPrevInstance) { hInstPropView = hInstance; // Fill in window class structure with parameters that describe the // main window. wc.lpszClassName = (LPSTR) "PropView"; wc.lpfnWndProc = MainWndProc; wc.hInstance = hInstPropView; wc.lpszMenuName = (LPSTR) "PropView"; wc.style = CS_DBLCLKS; wc.hIcon = LoadIcon(hInstance, "PropView"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; if(!RegisterClass((LPWNDCLASS) &wc)) { return(FALSE); } // Fill in window class structure with parameters that describe the // single-listbox window. wc.lpszClassName = (LPSTR) "SingleViewer"; wc.lpfnWndProc = GenericViewerWndProc; wc.hInstance = hInstPropView; wc.lpszMenuName = NULL; wc.style = CS_DBLCLKS; wc.hIcon = LoadIcon(hInstance, "PropView"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; if(!RegisterClass((LPWNDCLASS) &wc)) { return(FALSE); } // Fill in window class structure with parameters that describe the // double-listbox window. wc.lpszClassName = (LPSTR) "DoubleViewer"; wc.lpfnWndProc = GenericViewerWndProc; wc.hInstance = hInstPropView; wc.lpszMenuName = NULL; wc.style = CS_DBLCLKS; wc.hIcon = LoadIcon(hInstance, "PropView"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; if(!RegisterClass((LPWNDCLASS) &wc)) { return(FALSE); } // Fill in window class structure with parameters that describe the // message sending window. wc.lpszClassName = (LPSTR) "SendMsg"; wc.lpfnWndProc = SendMsgWndProc; wc.hInstance = hInstPropView; wc.lpszMenuName = NULL; wc.style = CS_DBLCLKS; wc.hIcon = LoadIcon(hInstance, "PropView"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; if(!RegisterClass((LPWNDCLASS) &wc)) { return(FALSE); } // Create the main window PropView CreateDialog ( hInstPropView, "PropView", NULL, NULL ); // Make procedure instances for enum functions if((lpEnumWindowPropsProc = MakeProcInstance(EnumWindowPropsProc, hInstPropView)) == NULL) { return(FALSE); } if((lpEnumChildrenProc = MakeProcInstance(EnumChildrenProc, hInstPropView)) == NULL) { return(FALSE); } // Create the Children window & set caption if((hDlgChildren = CreateDialog ( hInstPropView, "SingleViewer", hDlgPropView, 0L )) == NULL) { return(FALSE); } SetWindowText(hDlgChildren, (LPSTR) "No Children"); SetDlgItemText ( hDlgChildren, IDC_STATIC, (LPSTR) "Class\t\tCtrlID\thWnd\tCaption" ); // Create the Properties window & set caption if((hDlgProperties = CreateDialog ( hInstPropView, "SingleViewer", hDlgPropView, 0L )) == NULL) { return(FALSE); } SetWindowText(hDlgProperties, (LPSTR) "No Properties"); SetDlgItemText(hDlgProperties, IDC_STATIC, (LPSTR) "Property\tValue"); // Set tabs for children and properties list boxes ChildTabs[0] = 53; ChildTabs[1] = 82; ChildTabs[2] = 111; SendDlgItemMessage ( hDlgChildren, IDC_LISTBOX, LB_SETTABSTOPS, 3, (LONG) (LPINT) &ChildTabs ); PropTab = 50; SendDlgItemMessage ( hDlgProperties, IDC_LISTBOX, LB_SETTABSTOPS, 1, (LONG) (LPINT) &PropTab ); // Create the Data window if((hDlgExtraData = CreateDialog ( hInstPropView, "DoubleViewer", hDlgPropView, 0L )) == NULL) { return(FALSE); } SetWindowText(hDlgExtraData, (LPSTR) "Extra Data"); // Create the Styles window if((hDlgStyles = CreateDialog ( hInstPropView, "DoubleViewer", hDlgPropView, 0L )) == NULL) { return(FALSE); } SetWindowText(hDlgStyles, (LPSTR) "Styles"); // Create the SendMsg window if((hDlgSendMsg = CreateDialog ( hInstPropView, "SendMsg", hDlgPropView, 0L )) == NULL) { return(FALSE); } // Fill the msgs combobox in SendMsg dialog hFile = OpenFile("wm.msg", (LPOFSTRUCT) &OFstruct, OF_READ); if(hFile != -1) { FILE *fp = fdopen(hFile, "r"); while(fscanf(fp,"%22s%4s", Msg, Hex) != EOF ) { if(Msg[0] != 'W') { break; } wsprintf((LPSTR) Text, "%-35.35s %s", (LPSTR) &Msg[3], (LPSTR) Hex); SendDlgItemMessage ( hDlgSendMsg, IDC_MESSAGES, CB_ADDSTRING, 0, (LONG) (LPSTR) Text ); } fclose(fp); } // Check some radiobutton defaults CheckRadioButton(hDlgPropView, IDC_HEX, IDC_DEC, IDC_HEX); CheckRadioButton(hDlgPropView, IDC_SCREEN, IDC_DIALOG, IDC_SCREEN); } else { // If there was another instance of PropView running, then switch to // it by finding any window of class = "PropView". Then, if it's an // icon, open the window, otherwise just make it active. if(hDlgPropView = FindWindow("PropView", NULL)) { if(IsIconic(hDlgPropView)) { ShowWindow(hDlgPropView, SW_SHOWNORMAL); } SetActiveWindow(hDlgPropView); } return(FALSE); } // Acquire and dispatch messages until a WM_QUIT message is received. // The window handle hDlgActive points to the currently active window, // and is used to identify and process keystrokes going to any modeless // dialog box. while(GetMessage((LPMSG) &msg, NULL, NULL, NULL)) { if(hDlgActive != NULL) { if(!IsDialogMessage(hDlgActive, (LPMSG) &msg)) { TranslateMessage((LPMSG) &msg); DispatchMessage((LPMSG) &msg); } } else { TranslateMessage((LPMSG) &msg); DispatchMessage((LPMSG) &msg); } } FreeProcInstance(lpEnumWindowPropsProc); FreeProcInstance(lpEnumChildrenProc); } /***************************************************************************** FUNCTION: MainWndProc PURPOSE : Processes messages for PropView dialog box *****************************************************************************/ LONG FAR PASCAL MainWndProc(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam) { HWND hWndTemp; POINT Point; FARPROC lpProc; // Switch stmt for acting on msgs switch(wMsg) { case WM_CREATE : hDlgPropView = hWnd; break; case WM_MOUSEMOVE : // Check to see if we're capturing or not if(!Capturing) { return(DefDlgProc(hWnd, wMsg, wParam, lParam)); } // Find out the window to query. Abort if same as last hWnd GetCursorPos((LPPOINT) &Point); if((hWndTemp = WindowFromPoint(Point)) == NULL) { break; } // Screen out if same window if ( (hWndTemp != hWndTarget) && (hWndTemp != hDlgPropView) && (GetParent(hWndTemp) != hDlgPropView) ) { ExamineWindow(hWndTemp); } UpdatePos(); break; case WM_LBUTTONDOWN : case WM_MBUTTONDOWN : case WM_RBUTTONDOWN : // Any mouse button press cancels capture mode if(Capturing) { Capturing = FALSE; ReleaseCapture(); } break; case WM_COMMAND : switch(wParam) { case IDOK : case IDCANCEL : SendMessage(hWnd, WM_CLOSE, 0, 0L); break; case IDC_HEX : ShowHex = TRUE; ExamineWindow(hWndTarget); UpdatePos(); return(0L); case IDC_DEC : ShowHex = FALSE; ExamineWindow(hWndTarget); UpdatePos(); return(0L); case IDC_SCREEN : ShowScreenCoord = TRUE; ExamineWindow(hWndTarget); UpdatePos(); return(0L); case IDC_DIALOG : ShowScreenCoord = FALSE; ExamineWindow(hWndTarget); UpdatePos(); return(0L); case IDC_SPY : // Run a copy of Spy WinExec("spy", SW_SHOWNORMAL); return(0L); case IDC_CHILDREN : // Show/hide the "children" window if(IsWindowVisible(hDlgChildren)) { ShowWindow(hDlgChildren, SW_HIDE); } else { ShowWindow(hDlgChildren, SW_SHOWNORMAL); } return(0L); case IDC_SENDMSG : // Show/hide the "SendMsg" dialog if(IsWindowVisible(hDlgSendMsg)) { ShowWindow(hDlgSendMsg, SW_HIDE); } else { ShowWindow(hDlgSendMsg, SW_SHOWNORMAL); } return(0L); case IDC_DATA : // Show/hide the window/class data dialog if(IsWindowVisible(hDlgExtraData)) { ShowWindow(hDlgExtraData, SW_HIDE); } else { ShowWindow(hDlgExtraData, SW_SHOWNORMAL); } return(0L); case IDC_STYLES : // Show/hide the window/class data dialog if(IsWindowVisible(hDlgStyles)) { ShowWindow(hDlgStyles, SW_HIDE); } else { ShowWindow(hDlgStyles, SW_SHOWNORMAL); } return(0L); case IDC_PROPERTIES : // Show/hide the window properties dialog if(IsWindowVisible(hDlgProperties)) { ShowWindow(hDlgProperties, SW_HIDE); } else { ShowWindow(hDlgProperties, SW_SHOWNORMAL); } return(0L); case IDM_ABOUT : // Bring up the modal About dialog box lpProc = MakeProcInstance(About, hInstPropView); DialogBox(hInstPropView, "About", hWnd, lpProc); FreeProcInstance(lpProc); return(0L); case IDM_EXIT : SendMessage(hWnd, WM_CLOSE, 0, 0L); return(0L); case IDM_GO : Capturing = TRUE; SetCapture(hWnd); return(0L); default : break; } break; case WM_PAINT : if(hWndTarget != NULL) { DrawIcons(); // Validate areas we just painted so WM_PAINT doesn't ValidateRect(GetDlgItem(hDlgPropView, IDC_HWNDICON), NULL); ValidateRect(GetDlgItem(hDlgPropView, IDC_PARENTICON), NULL); } break; case WM_CLOSE : DestroyWindow(hWnd); return(0L); case WM_ACTIVATE : hDlgActive = (wParam == NULL) ? NULL : hWnd; break; case WM_DESTROY : PostQuitMessage(0); return(0L); default : break; } return(DefDlgProc(hWnd, wMsg, wParam, lParam)); } /***************************************************************************** FUNCTION: GenericViewerWndProc PURPOSE : Processes messages for generic listbox display window *****************************************************************************/ LONG FAR PASCAL GenericViewerWndProc(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam) { BYTE Entry[50]; BYTE *ptr; HWND hWndTemp; int Index; // Switch stmt for acting on msgs switch(wMsg) { case WM_COMMAND : switch(wParam) { case IDC_LISTBOX : if(HIWORD(lParam) == LBN_DBLCLK) { // Get index of entry in listbox clicked on if((Index = (int) SendDlgItemMessage ( hWnd, IDC_LISTBOX, LB_GETCURSEL, 0, 0L )) == LB_ERR) { break; } // Get entry text SendDlgItemMessage ( hWnd, IDC_LISTBOX, LB_GETTEXT, Index, (LONG) (LPSTR) Entry ); if(hDlgChildren == hWnd) { if(Entry[0] == '\"') { // This is when parent entry of ".." was // selected ExamineWindow(GetParent(hWndTarget)); } else { // Pull out the hWnd field of the child // window we want to examine. if(ptr = strrchr(Entry, '\t')) { if(*(ptr + 1) == '\"') { while(--ptr) { if(*ptr == '\t') { break; } } } else { ++ptr; } if(ShowHex) { sscanf(ptr, "%x", &hWndTemp); } else { sscanf(ptr, "%d", &hWndTemp); } ExamineWindow(hWndTemp); } } } } return(0L); default : break; } break; case WM_CLOSE : if(IsWindowVisible(hWnd)) { ShowWindow(hWnd, SW_HIDE); } else { ShowWindow(hWnd, SW_SHOWNORMAL); } return(0L); case WM_SIZE : if(wParam != SIZEICONIC) { if ( hWnd == hDlgChildren || hWnd == hDlgProperties ) { // For SingleViewer dialogs... // Resize the static text ctrl & list box ctrl so // that they fill the size of the resized dialog if(GetDlgItem(hWnd, IDC_STATIC)) { MoveWindow ( GetDlgItem(hWnd, IDC_STATIC), 0, 0, LOWORD(lParam), 12, TRUE ); } if(GetDlgItem(hWnd, IDC_LISTBOX)) { MoveWindow ( GetDlgItem(hWnd, IDC_LISTBOX), 0, 12, LOWORD(lParam), HIWORD(lParam) - 12, TRUE ); } InvalidateRect(GetDlgItem(hWnd, IDC_STATIC), NULL, TRUE); } else { WORD Width = LOWORD(lParam); WORD Height = HIWORD(lParam); // For DoubleViewer dialogs... // Resize both of the static text ctrls & list box // ctrls so that they fill the size of the resized dialog. if(GetDlgItem(hWnd, IDC_WNDTEXT)) { MoveWindow ( GetDlgItem(hWnd, IDC_WNDTEXT), 4, 4, Width / 2 - 8, 12, TRUE ); } if(GetDlgItem(hWnd, IDC_CLSTEXT)) { MoveWindow ( GetDlgItem(hWnd, IDC_CLSTEXT), Width / 2 + 2, 4, Width / 2 - 8, 12, TRUE ); } if(GetDlgItem(hWnd, IDC_WNDLIST)) { MoveWindow ( GetDlgItem(hWnd, IDC_WNDLIST), 4, 19, Width / 2 - 8, Height - (18 + 4), TRUE ); } if(GetDlgItem(hWnd, IDC_CLSLIST)) { MoveWindow ( GetDlgItem(hWnd, IDC_CLSLIST), Width / 2 + 2, 19, Width / 2 - 8, Height - (18 + 4), TRUE ); } InvalidateRect(GetDlgItem(hWnd, IDC_WNDTEXT), NULL, TRUE); InvalidateRect(GetDlgItem(hWnd, IDC_CLSTEXT), NULL, TRUE); } } break; case WM_ACTIVATE : hDlgActive = (wParam == NULL) ? NULL : hWnd; break; default : break; } return(DefDlgProc(hWnd, wMsg, wParam, lParam)); } /***************************************************************************** FUNCTION: SendMsgWndProc PURPOSE : Processes messages for message sending dialog *****************************************************************************/ LONG FAR PASCAL SendMsgWndProc(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam) { BYTE hWndText[7]; BYTE MsgText[50]; BYTE Msg[81]; BYTE wParamText[5]; BYTE lParamText[10]; // Switch stmt for acting on msgs switch(wMsg) { case WM_COMMAND : switch(wParam) { case IDOK : SendMessage(hWnd, WM_CLOSE, 0, 0L); return(0L); case IDC_SEND : // Send message to target window GetDlgItemText ( hWnd, IDC_HWNDTOSEND, (LPSTR) hWndText, sizeof(hWndText) ); GetDlgItemText ( hWnd, IDC_MESSAGES, (LPSTR) MsgText, sizeof(MsgText) ); GetDlgItemText ( hWnd, IDC_WPARAM, (LPSTR) wParamText, sizeof(wParamText) ); GetDlgItemText ( hWnd, IDC_LPARAM, (LPSTR) lParamText, sizeof(lParamText) ); // Check for parms not filled in or null window handle if ( hWndText[0] == '\0' || MsgText[0] == '\0' || wParamText[0] == '\0' || lParamText[0] == '\0' || !IsWindow(hWndTarget) ) { return(0L);; } lstrcpy((LPSTR) Msg, (LPSTR) &MsgText[36]); if(ShowHex) { hWnd = (HWND) strtol(hWndText, NULL, 16); wMsg = (WORD) strtol(Msg, NULL, 16); wParam = (WORD) strtol(wParamText, NULL, 16); lParam = (DWORD) strtol(lParamText, NULL, 16); } else { hWnd = (HWND) strtol(hWndText, NULL, 10); wMsg = (WORD) strtol(Msg, NULL, 10); wParam = (WORD) strtol(wParamText, NULL, 10); lParam = (DWORD) strtol(lParamText, NULL, 10); } if(PostMessage(hWnd, wMsg, wParam, lParam) == FALSE) { MessageBeep(0); MessageBox ( hDlgSendMsg, "PostMessage() failed", "ERROR", MB_ICONEXCLAMATION | MB_OK ); } SetActiveWindow(hDlgSendMsg); return(0L); default : break; } break; case WM_CLOSE : if(IsWindowVisible(hWnd)) { ShowWindow(hWnd, SW_HIDE); } else { ShowWindow(hWnd, SW_SHOWNORMAL); } return(0L); case WM_ACTIVATE : hDlgActive = (wParam == NULL) ? NULL : hWnd; break; default : break; } return(DefDlgProc(hWnd, wMsg, wParam, lParam)); } /***************************************************************************** FUNCTION: UpdatePos PURPOSE : Updates cursor information in dialog *****************************************************************************/ VOID PASCAL UpdatePos(VOID) { POINT Point; POINT Client; if(hWndTarget == NULL) { return; } // Get some cursor information GetCursorPos((LPPOINT) &Point); if(ShowScreenCoord == FALSE) { LONG Units = GetDialogBaseUnits(); WORD Xamt = LOWORD(Units); WORD Yamt = HIWORD(Units); Point.x = (Point.x * 4 ) / Xamt; Point.y = (Point.y * 4 ) / Yamt; } if((hWndTarget != NULL) && (GetParent(hWndTarget) != NULL)) { Client.x = Point.x; Client.y = Point.y; ScreenToClient(hWndTarget, (LPPOINT) &Client); } else { Client.x = 0; Client.y = 0; } if(ShowHex) { wsprintf ( (LPSTR) Text, "Cursor = (0x%04x, 0x%04x), (0x%04x, 0x%04x)", Point.x, Point.y, Client.x, Client.y ); } else { wsprintf ( (LPSTR) Text, "Cursor = (%d, %d), (%d, %d)", Point.x, Point.y, Client.x, Client.y ); } SetDlgItemText(hDlgPropView, IDC_POS, (LPSTR) Text); } /***************************************************************************** FUNCTION: ExamineWindow PURPOSE : Shows info on selected window (ie. children, parent, properties) *****************************************************************************/ VOID PASCAL ExamineWindow(HWND hWnd) { #define NUMCLASSSTYLES 11 #define NUMWNDSTYLES 29 HWND hWndParent; BYTE ModuleFileName[30]; BYTE ClassName[30]; BYTE hWndText[7]; RECT Rect; int i; HANDLE hInst; LONG WndStyle; WORD ClassStyle; WORD WndExtraData; WORD ClsExtraData; static struct { WORD Style; LPSTR Text; } ClassStyles[NUMCLASSSTYLES] = { {CS_BYTEALIGNCLIENT, "CS_BYTEALIGNCLIENT"}, {CS_BYTEALIGNWINDOW, "CS_BYTEALIGNWINDOW"}, {CS_CLASSDC, "CS_CLASSDC"}, {CS_DBLCLKS, "CS_DBLCLKS"}, {CS_GLOBALCLASS, "CS_GLOBALCLASS"}, {CS_HREDRAW, "CS_HREDRAW"}, {CS_NOCLOSE, "CS_NOCLOSE"}, {CS_OWNDC, "CS_OWNDC"}, {CS_PARENTDC, "CS_PARENTDC"}, {CS_SAVEBITS, "CS_SAVEBITS"}, {CS_VREDRAW, "CS_VREDRAW"} }; static struct { LONG Style; LPSTR Text; } WndStyles[NUMWNDSTYLES] = { {WS_POPUP, "WS_POPUP"}, {WS_OVERLAPPED, "WS_OVERLAPPED"}, {WS_CHILD, "WS_CHILD"}, {WS_MINIMIZE, "WS_MINIMIZE"}, {WS_VISIBLE, "WS_VISIBLE"}, {WS_DISABLED, "WS_DISABLED"}, {WS_CLIPSIBLINGS, "WS_CLIPSIBLINGS"}, {WS_CLIPCHILDREN, "WS_CLIPCHILDREN"}, {WS_MAXIMIZE, "WS_MAXIMIZE"}, {WS_CAPTION, "WS_CAPTION"}, {WS_BORDER, "WS_BORDER"}, {WS_DLGFRAME, "WS_DLGFRAME"}, {WS_VSCROLL, "WS_VSCROLL"}, {WS_HSCROLL, "WS_HSCROLL"}, {WS_SYSMENU, "WS_SYSMENU"}, {WS_THICKFRAME, "WS_THICKFRAME"}, {WS_GROUP, "WS_GROUP"}, {WS_TABSTOP, "WS_TABSTOP"}, {WS_MINIMIZEBOX, "WS_MINIMIZEBOX"}, {WS_MAXIMIZEBOX, "WS_MAXIMIZEBOX"}, {WS_EX_DLGMODALFRAME, "WS_EX_DLGMODALFRAME"}, {WS_EX_NOPARENTNOTIFY, "WS_EX_NOPARENTNOTIFY"} }; // Check for NULL hWnd if((hWnd == NULL) || !IsWindow(hWnd)) { return; } // We have a new target window hWndTarget = hWnd; // DRAW ICONS DrawIcons(); // Turn on outline of target window OutlineWindow(hWndTarget); // Update the hWnd in the SendMsg dialog if(ShowHex) { wsprintf(hWndText, "0x%04x", hWndTarget); } else { wsprintf(hWndText, "%d", hWndTarget); } SetDlgItemText(hDlgSendMsg, IDC_HWNDTOSEND, (LPSTR) hWndText); // Display different window stats GetClassName(hWnd, (LPSTR) ClassName, sizeof(ClassName)); if(ShowHex) { wsprintf ( (LPSTR) Text, "= 0x%04x (0x%04x), %s", hWnd, GetDlgCtrlID(hWnd), (LPSTR) ClassName ); } else { wsprintf ( (LPSTR) Text, "= %d (%d), %s", hWnd, GetDlgCtrlID(hWnd), (LPSTR) ClassName ); } SetDlgItemText(hDlgPropView, IDC_HWND, (LPSTR) Text); if(!GetWindowText(hWnd, (LPSTR) Text, sizeof(Text))) { Text[0] = '\0'; } SetDlgItemText(hDlgPropView, IDC_CAPTION, (LPSTR) Text); if((hWndParent = GetParent(hWnd)) != NULL) { GetClassName(hWndParent, (LPSTR) ClassName, sizeof(ClassName)); if(ShowHex) { wsprintf ( (LPSTR) Text, "= 0x%04x (0x%04x), %s", hWndParent, GetDlgCtrlID(hWndParent), (LPSTR) ClassName ); } else { wsprintf ( (LPSTR) Text, "= %d (%d), %s", hWndParent, GetDlgCtrlID(hWndParent), (LPSTR) ClassName ); } SetDlgItemText(hDlgPropView, IDC_HWNDPARENT, (LPSTR) Text); if(!GetWindowText(hWndParent, (LPSTR) Text, sizeof(Text))) { Text[0] = '\0'; } SetDlgItemText(hDlgPropView, IDC_PARENTCAPTION, (LPSTR) Text); } else { SetDlgItemText(hDlgPropView, IDC_HWNDPARENT, (LPSTR) "="); SetDlgItemText(hDlgPropView, IDC_PARENTCAPTION, (LPSTR) ""); } // Get and display INSTANCE information hInst = GetWindowWord(hWnd, GWW_HINSTANCE); GetModuleFileName(hInst, (LPSTR) ModuleFileName, sizeof(ModuleFileName)); if(ShowHex) { wsprintf ( (LPSTR) Text, "hInst = 0x%04x, %s", hInst, (LPSTR) ModuleFileName ); } else { wsprintf ( (LPSTR) Text, "hInst = %d, %s", hInst, (LPSTR) ModuleFileName ); } SetDlgItemText(hDlgPropView, IDC_HINST, (LPSTR) Text); // Get & display RECT of window GetWindowRect(hWnd, (LPRECT) &Rect); if(ShowScreenCoord == FALSE) { LONG Units = GetDialogBaseUnits(); WORD Xamt = LOWORD(Units); WORD Yamt = HIWORD(Units); Rect.left = (Rect.left * Xamt) / 4; Rect.right = (Rect.right * Xamt) / 4; Rect.top = (Rect.top * Yamt) / 4; Rect.bottom = (Rect.bottom * Yamt) / 4; } if(ShowHex) { wsprintf ( (LPSTR) Text, "Rect = (0x%04x, 0x%04x)-(0x%04x, 0x%04x)", Rect.left, Rect.top, Rect.right, Rect.bottom ); } else { wsprintf ( (LPSTR) Text, "Rect = (%d, %d)-(%d, %d)", Rect.left, Rect.top, Rect.right, Rect.bottom ); } SetDlgItemText(hDlgPropView, IDC_RECT, (LPSTR) Text); // Get & display CHILDREN & PROPERTY information SendDlgItemMessage(hDlgChildren, IDC_LISTBOX, WM_SETREDRAW, 0, 0L); SendDlgItemMessage(hDlgProperties, IDC_LISTBOX, WM_SETREDRAW, 0, 0L); SendDlgItemMessage(hDlgProperties, IDC_LISTBOX, LB_RESETCONTENT, 0, 0L); SendDlgItemMessage(hDlgChildren, IDC_LISTBOX, LB_RESETCONTENT, 0, 0L); EnumChildWindows(hWndTarget, lpEnumChildrenProc, NULL); if ( !(i = (int) SendDlgItemMessage ( hDlgChildren, IDC_LISTBOX, LB_GETCOUNT, 0, 0L )) ) { SetWindowText(hDlgChildren, "No children"); } else { if(i == 1) { SetWindowText(hDlgChildren, "One child"); } else { wsprintf(Text, "%d Children", i); SetWindowText(hDlgChildren, Text); } } if(GetParent(hWndTarget)) { SendDlgItemMessage ( hDlgChildren, IDC_LISTBOX, LB_ADDSTRING, 0, (LONG) (LPSTR) "\"..\" (parent)" ); } EnumProps(hWndTarget, lpEnumWindowPropsProc); if ( !(i = (int) SendDlgItemMessage ( hDlgProperties, IDC_LISTBOX, LB_GETCOUNT, 0, 0L )) ) { SetWindowText(hDlgProperties, "No properties"); } else { if(i == 1) { SetWindowText(hDlgProperties, "One property"); } else { wsprintf(Text, "%d Properties", i); SetWindowText(hDlgProperties, Text); } } // Now, turn redrawing for both listbox windows back on, invalidating their // areas, and sending a WM_PAINT. SendDlgItemMessage(hDlgChildren, IDC_LISTBOX, WM_SETREDRAW, 1, 0L); SendDlgItemMessage(hDlgProperties, IDC_LISTBOX, WM_SETREDRAW, 1, 0L); InvalidateRect(GetDlgItem(hDlgChildren, IDC_LISTBOX), NULL, TRUE); InvalidateRect(GetDlgItem(hDlgProperties, IDC_LISTBOX), NULL, TRUE); UpdateWindow(GetDlgItem(hDlgChildren, IDC_LISTBOX)); UpdateWindow(GetDlgItem(hDlgProperties, IDC_LISTBOX)); // Update the Data window SendDlgItemMessage(hDlgExtraData, IDC_WNDLIST, WM_SETREDRAW, 0, 0L); SendDlgItemMessage(hDlgExtraData, IDC_CLSLIST, WM_SETREDRAW, 0, 0L); SendDlgItemMessage(hDlgExtraData, IDC_WNDLIST, LB_RESETCONTENT, 0, 0L); SendDlgItemMessage(hDlgExtraData, IDC_CLSLIST, LB_RESETCONTENT, 0, 0L); WndExtraData = GetClassWord(hWndTarget, GCW_CBWNDEXTRA); ClsExtraData = GetClassWord(hWndTarget, GCW_CBCLSEXTRA); if(ShowHex) { wsprintf ( (LPSTR) Text, "Window = 0x%04x bytes", WndExtraData ); } else { wsprintf ( (LPSTR) Text, "Window = %d bytes", WndExtraData ); } SetDlgItemText(hDlgExtraData, IDC_WNDTEXT, (LPSTR) Text); for(i = 0; i < (int) WndExtraData; i += 2) { BYTE Byte[5]; if(ShowHex) { wsprintf(Byte, "0x%04x", GetWindowWord(hWndTarget, i)); } else { wsprintf(Byte, "%d", GetWindowWord(hWndTarget, i)); } SendDlgItemMessage ( hDlgExtraData, IDC_WNDLIST, LB_ADDSTRING, 0, (LONG) (LPSTR) Byte ); } // Reset, and then fill the class bytes listbox if(ShowHex) { wsprintf ( (LPSTR) Text, "Class = 0x%04x bytes", ClsExtraData ); } else { wsprintf ( (LPSTR) Text, "Class = %d bytes", ClsExtraData ); } SetDlgItemText(hDlgExtraData, IDC_CLSTEXT, (LPSTR) Text); for(i = 0; i < (int) ClsExtraData; i += 2) { BYTE Byte[7]; if(ShowHex) { wsprintf(Byte, "0x%04x", GetClassWord(hWndTarget, i)); } else { wsprintf(Byte, "%d", GetClassWord(hWndTarget, i)); } SendDlgItemMessage ( hDlgExtraData, IDC_CLSLIST, LB_ADDSTRING, 0, (LONG) (LPSTR) Byte ); } SendDlgItemMessage(hDlgExtraData, IDC_CLSLIST, WM_SETREDRAW, 1, 0L); SendDlgItemMessage(hDlgExtraData, IDC_WNDLIST, WM_SETREDRAW, 1, 0L); InvalidateRect(GetDlgItem(hDlgExtraData, IDC_CLSLIST), NULL, TRUE); InvalidateRect(GetDlgItem(hDlgExtraData, IDC_WNDLIST), NULL, TRUE); UpdateWindow(GetDlgItem(hDlgExtraData, IDC_CLSLIST)); UpdateWindow(GetDlgItem(hDlgExtraData, IDC_WNDLIST)); // Update the Styles window SendDlgItemMessage(hDlgStyles, IDC_WNDLIST, WM_SETREDRAW, 0, 0L); SendDlgItemMessage(hDlgStyles, IDC_CLSLIST, WM_SETREDRAW, 0, 0L); SendDlgItemMessage(hDlgStyles, IDC_WNDLIST, LB_RESETCONTENT, 0, 0L); SendDlgItemMessage(hDlgStyles, IDC_CLSLIST, LB_RESETCONTENT, 0, 0L); WndStyle = GetWindowLong(hWndTarget, GWL_STYLE); ClassStyle = GetClassWord(hWndTarget, GCW_STYLE); if(ShowHex) { wsprintf ( (LPSTR) Text, "Wnd Style = 0x%08lx", WndStyle ); } else { wsprintf ( (LPSTR) Text, "Wnd Style = %ld", WndStyle ); } SetDlgItemText(hDlgStyles, IDC_WNDTEXT, (LPSTR) Text); // Check to see if the window is a popup. If so, don't throw in // WS_OVERLAPPED attribute. if(WndStyle & WndStyles[0].Style) { SendDlgItemMessage ( hDlgStyles, IDC_WNDLIST, LB_ADDSTRING, 0, (LONG) (LPSTR) WndStyles[1].Text ); } else { if(WndStyle & WndStyles[1].Style) { SendDlgItemMessage ( hDlgStyles, IDC_WNDLIST, LB_ADDSTRING, 0, (LONG) (LPSTR) WndStyles[0].Text ); } } for(i = 2; i < NUMWNDSTYLES; ++i) { if(WndStyle & WndStyles[i].Style) { SendDlgItemMessage ( hDlgStyles, IDC_WNDLIST, LB_ADDSTRING, 0, (LONG) (LPSTR) WndStyles[i].Text ); } } // Reset, and then fill the class styles combo box if(ShowHex) { wsprintf ( (LPSTR) Text, "Class Style = 0x%04x", ClassStyle ); } else { wsprintf ( (LPSTR) Text, "Class Style = %d", ClassStyle ); } SetDlgItemText(hDlgStyles, IDC_CLSTEXT, (LPSTR) Text); for(i = 0; i < NUMCLASSSTYLES; ++i) { if(ClassStyle & ClassStyles[i].Style) { SendDlgItemMessage ( hDlgStyles, IDC_CLSLIST, LB_ADDSTRING, 0, (LONG) (LPSTR) ClassStyles[i].Text ); } } // Turn off outline of target window OutlineWindow(hWndTarget); // Turn redrawing back on and repaint all listboxes SendDlgItemMessage(hDlgStyles, IDC_WNDLIST, WM_SETREDRAW, 1, 0L); SendDlgItemMessage(hDlgStyles, IDC_CLSLIST, WM_SETREDRAW, 1, 0L); InvalidateRect(GetDlgItem(hDlgStyles, IDC_WNDLIST), NULL, TRUE); InvalidateRect(GetDlgItem(hDlgStyles, IDC_CLSLIST), NULL, TRUE); UpdateWindow(GetDlgItem(hDlgStyles, IDC_WNDLIST)); UpdateWindow(GetDlgItem(hDlgStyles, IDC_CLSLIST)); } /***************************************************************************** FUNCTION: EnumWindowPropsProc PURPOSE : Enumerates properties for window under mouse *****************************************************************************/ int FAR PASCAL EnumWindowPropsProc(HWND hWnd, LPSTR lpString, HANDLE hData) { // Check the passed property name to see if it's a string or an atom if(HIWORD(lpString)) { if(ShowHex) { wsprintf(Text, "%s\t= 0x%04x", (LPSTR) lpString, hData); } else { wsprintf(Text, "%s\t= %d", (LPSTR) lpString, hData); } } else { if(ShowHex) { wsprintf(Text, "0x%04x, 0x%04x", LOWORD((DWORD) lpString), hData); } else { wsprintf(Text, "%d, %d", LOWORD((DWORD) lpString), hData); } } SendDlgItemMessage ( hDlgProperties, IDC_LISTBOX, LB_ADDSTRING, 0, (LONG) (LPSTR) Text ); return(1); } /***************************************************************************** FUNCTION: DrawIcons PURPOSE : Draws the target and parent class icons *****************************************************************************/ VOID PASCAL DrawIcons(VOID) { HWND hWndParent; HDC hDC; HFONT hFont; HICON hIcon; BYTE ClassName[30]; if(hWndTarget == NULL) { return; } // Setup small prop helv font for icon titles hFont = CreateFont ( 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Helv" ); // Get window class name & draw icon if(!GetClassName(hWndTarget, (LPSTR) ClassName, sizeof(ClassName))) { ClassName[0] = '\0'; } if((hIcon = GetClassWord(hWndTarget, GCW_HICON)) == NULL) { if(!lstrcmpi((LPSTR) ClassName, "listbox")) { hIcon = LoadIcon(hInstPropView, "listbox"); } else { if(!lstrcmpi((LPSTR) ClassName, "combobox")) { hIcon = LoadIcon(hInstPropView, "combobox"); } else { if(!lstrcmpi((LPSTR) ClassName, "button")) { hIcon = LoadIcon(hInstPropView, "button"); } else { if(!lstrcmpi((LPSTR) ClassName, "edit") || !lstrcmpi((LPSTR) ClassName, "static")) { hIcon = LoadIcon(hInstPropView, "editcontrol"); } } } } } // Get DC, draw icon, and release DC hDC = GetDC(GetDlgItem(hDlgPropView, IDC_HWNDICON)); if((hIcon == NULL) && IsIconic(hWndTarget) && IsWindowVisible(hWndTarget)) { HDC hDCTarget = GetWindowDC(hWndTarget); BitBlt(hDC, 0, 0, 36, 36, hDCTarget, 0, 0, SRCCOPY); ReleaseDC(hWndTarget, hDCTarget); } else { BitBlt(hDC, 0, 0, 36, 36, hDC, 0, 0, WHITENESS); DrawIcon(hDC, 0, 0, hIcon); } ReleaseDC(GetDlgItem(hDlgPropView, IDC_HWNDICON), hDC); if((hWndParent = GetParent(hWndTarget)) != NULL) { HICON hIcon; // Get DC, draw icon, and release DC hDC = GetDC(GetDlgItem(hDlgPropView, IDC_PARENTICON)); if ( ((hIcon = GetClassWord(hWndParent, GCW_HICON)) == NULL) && IsIconic(hWndParent) && IsWindowVisible(hWndTarget) ) { HDC hDCTarget = GetWindowDC(hWndParent); BitBlt(hDC, 0, 0, 36, 36, hDCTarget, 0, 0, SRCCOPY); ReleaseDC(hWndParent, hDCTarget); } else { BitBlt(hDC, 0, 0, 36, 36, hDC, 0, 0, WHITENESS); DrawIcon(hDC, 0, 0, hIcon); } ReleaseDC(GetDlgItem(hDlgPropView, IDC_PARENTICON), hDC); } else { // Get DC, draw icon, and release DC hDC = GetDC(GetDlgItem(hDlgPropView, IDC_PARENTICON)); BitBlt(hDC, 0, 0, 36, 36, hDC, 0, 0, WHITENESS); ReleaseDC(GetDlgItem(hDlgPropView, IDC_PARENTICON), hDC); } // Do usual cleanup DeleteObject(hFont); } /***************************************************************************** FUNCTION: EnumChildrenProc PURPOSE : Enumerates children of window under mouse *****************************************************************************/ int FAR PASCAL EnumChildrenProc(HWND hWnd, DWORD lParam) { BYTE Text[100]; BYTE Caption[100]; BYTE ClassName[30]; // Get the child window's caption and class name GetWindowText(hWnd, (LPSTR) Caption, sizeof(Caption)); GetClassName(hWnd, (LPSTR) ClassName, sizeof(ClassName)); // Format and add the entry to the child list box if(Caption[0] != '\0') { if(ShowHex) { wsprintf ( (LPSTR) Text, "%s\t0x%04x\t0x%04x\t\"%s\"", (LPSTR) ClassName, GetDlgCtrlID(hWnd), hWnd, (LPSTR) Caption ); } else { wsprintf ( (LPSTR) Text, "%s\t%d\t%d\t\"%s\"", (LPSTR) ClassName, GetDlgCtrlID(hWnd), hWnd, (LPSTR) Caption ); } } else { if(ShowHex) { wsprintf ( (LPSTR) Text, "%s\t0x%04x\t0x%04x", (LPSTR) ClassName, GetDlgCtrlID(hWnd), hWnd ); } else { wsprintf ( (LPSTR) Text, "%s\t%d\t%d", (LPSTR) ClassName, GetDlgCtrlID(hWnd), hWnd ); } } SendDlgItemMessage ( hDlgChildren, IDC_LISTBOX, LB_ADDSTRING, 0, (LONG) (LPSTR) Text ); return(1); } /***************************************************************************** FUNCTION: About PURPOSE : Processes messages for About box *****************************************************************************/ BOOL FAR PASCAL About(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam) { switch(wMsg) { case WM_INITDIALOG : return(TRUE); case WM_COMMAND : if(wParam == IDOK || wParam == IDCANCEL) { EndDialog(hWnd, TRUE); return(TRUE); } break; default : break; } return(FALSE); } /***************************************************************************** FUNCTION: OutlineWindow PURPOSE : Outlines window with a rectangle *****************************************************************************/ VOID PASCAL OutlineWindow(HWND hWnd) { RECT Rect; HDC hDC; HPEN hPen; HPEN hPenOld; HANDLE hBrush; HANDLE hBrushOld; int OldROP2Mode; // Check for valid window handle and pen thickness if(!IsWindow(hWnd)) { return; } // Set up parms to draw rectangle hBrush = GetStockObject(NULL_BRUSH); hPen = CreatePen(PS_SOLID, 6, RGB(0, 0, 0)); // Get DC for window and it's dimensions hDC = GetWindowDC(hWnd); GetWindowRect(hWnd, (LPRECT) &Rect); // Set drawing mode parameters hBrushOld = SelectObject(hDC, hBrush); hPenOld = SelectObject(hDC, hPen); OldROP2Mode = SetROP2(hDC, R2_NOT); // Draw the rectangle and release the DC Rectangle(hDC, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top); // Be a good boy and reset the old context attributes SelectObject(hDC, hBrushOld); SelectObject(hDC, hPenOld); DeleteObject(hPen); SetROP2(hDC, OldROP2Mode); ReleaseDC(hWnd, hDC); }