/*++ Copyright (c) 2000 Microsoft Corporation Module Name: wnd.c Abstract: Utilities for window management Author: Jim Schmidt (jimschm) 01-Feb-2000 Revision History: --*/ // // Includes // #include "pch.h" #define DBG_WND "Wnd" // // Strings // // None // // Constants // // None // // Macros // // None // // Types // typedef struct { PCSTR WindowTitle; DWORD ProcessId; HWND Match; } FINDWINDOW_STRUCTA, *PFINDWINDOW_STRUCTA; typedef struct { PCWSTR WindowTitle; DWORD ProcessId; HWND Match; } FINDWINDOW_STRUCTW, *PFINDWINDOW_STRUCTW; // // Globals // static INT g_CursorRefCount = 0; static HCURSOR g_OldCursor = NULL; // // Macro expansion list // // None // // Private function prototypes // // None // // Macro expansion definition // // None // // Code // BOOL CALLBACK pEnumWndProcA ( HWND hwnd, LPARAM lParam ) /*++ Routine Description: A callback that is called for every top level window on the system. It is used with pFindParentWindow to locate a specific window. Arguments: hwnd - Specifies the handle of the current enumerated window lParam - Specifies a pointer to a FINDWINDOW_STRUCTA variable that holds WindowTitle and ProcessId, and receives the handle if a match is found. Return Value: The handle to the matching window, or NULL if no window has the specified title and process ID. --*/ { CHAR title[MAX_MBCHAR_PATH]; DWORD processId; PFINDWINDOW_STRUCTA p; BOOL match = FALSE; p = (PFINDWINDOW_STRUCTA) lParam; if (!GetWindowThreadProcessId (hwnd, &processId)) { DEBUGMSG ((DBG_WND, "Enumerated hwnd no longer valid")); return TRUE; } if (processId == p->ProcessId) { match = TRUE; } if (p->WindowTitle) { GetWindowTextA (hwnd, title, ARRAYSIZE(title)); DEBUGMSGA (( DBG_NAUSEA, "Testing window: %s, ID=%08Xh against %s, %08Xh", title, processId, p->WindowTitle, p->ProcessId )); match = match && StringMatchA (title, p->WindowTitle); } ELSE_DEBUGMSGA (( DBG_NAUSEA, "Testing window: Process ID=%08Xh against %08Xh", processId, p->ProcessId )); if (match) { p->Match = hwnd; #ifdef DEBUG // // Get the window title for the following debug message // GetWindowTextA (hwnd, title, ARRAYSIZE(title)); DEBUGMSGA (( DBG_NAUSEA, "Window found: %s, ID=%u", title, processId )); #endif return FALSE; // stop enum } return TRUE; // continue enum } BOOL CALLBACK pEnumWndProcW ( HWND hwnd, LPARAM lParam ) { WCHAR title[MAX_MBCHAR_PATH]; DWORD processId; PFINDWINDOW_STRUCTW p; BOOL match = FALSE; p = (PFINDWINDOW_STRUCTW) lParam; if (!GetWindowThreadProcessId (hwnd, &processId)) { DEBUGMSG ((DBG_WND, "Enumerated hwnd no longer valid")); return TRUE; } if (processId == p->ProcessId) { match = TRUE; } if (p->WindowTitle) { GetWindowTextW (hwnd, title, ARRAYSIZE(title)); DEBUGMSGW (( DBG_NAUSEA, "Testing window: %s, ID=%08Xh against %s, %08Xh", title, processId, p->WindowTitle, p->ProcessId )); match = match && StringMatchW (title, p->WindowTitle); } ELSE_DEBUGMSGW (( DBG_NAUSEA, "Testing window: Process ID=%08Xh against %08Xh", processId, p->ProcessId )); if (match) { p->Match = hwnd; #ifdef DEBUG // // Get the window title for the following debug message // GetWindowTextW (hwnd, title, ARRAYSIZE(title)); DEBUGMSGA (( DBG_NAUSEA, "Window found: %s, ID=%u", title, processId )); #endif return FALSE; // stop enum } return TRUE; // continue enum } HWND WndFindWindowInProcessA ( IN DWORD ProcessId, IN PCSTR WindowTitle OPTIONAL ) /*++ Routine Description: Finds a window by enumerating all top-level windows, and checking the process id. The first one to match the optionally supplied title is used. Arguments: ProcessId - Specifies the ID of the process who owns the window. If zero is specified, NULL is returned. WindowTitle - Specifies the name of the window to find. Return Value: The handle to the matching window, or NULL if no window has the specified title and process ID. --*/ { FINDWINDOW_STRUCTA findWndStruct; // // If no process ID, we cannot have a match // if (!ProcessId) { DEBUGMSG ((DBG_WND, "ProcessId == 0")); return NULL; } ZeroMemory (&findWndStruct, sizeof (findWndStruct)); findWndStruct.WindowTitle = WindowTitle; findWndStruct.ProcessId = ProcessId; EnumWindows (pEnumWndProcA, (LPARAM) &findWndStruct); return findWndStruct.Match; } HWND WndFindWindowInProcessW ( IN DWORD ProcessId, IN PCWSTR WindowTitle OPTIONAL ) { FINDWINDOW_STRUCTW findWndStruct; // // If no process ID, we cannot have a match // if (!ProcessId) { DEBUGMSG ((DBG_WND, "ProcessId == 0")); return NULL; } ZeroMemory (&findWndStruct, sizeof (findWndStruct)); findWndStruct.WindowTitle = WindowTitle; findWndStruct.ProcessId = ProcessId; EnumWindows (pEnumWndProcW, (LPARAM) &findWndStruct); return findWndStruct.Match; } #define WIDTH(rect) (rect.right - rect.left) #define HEIGHT(rect) (rect.bottom - rect.top) VOID WndCenterWindow ( IN HWND hwnd, IN HWND Parent OPTIONAL ) { RECT WndRect, ParentRect; int x, y; if (!Parent) { ParentRect.left = 0; ParentRect.top = 0; ParentRect.right = GetSystemMetrics (SM_CXFULLSCREEN); ParentRect.bottom = GetSystemMetrics (SM_CYFULLSCREEN); } else { GetWindowRect (Parent, &ParentRect); } MYASSERT (IsWindow (hwnd)); GetWindowRect (hwnd, &WndRect); x = ParentRect.left + (WIDTH(ParentRect) - WIDTH(WndRect)) / 2; y = ParentRect.top + (HEIGHT(ParentRect) - HEIGHT(WndRect)) / 2; SetWindowPos (hwnd, NULL, x, y, 0, 0, SWP_NOZORDER|SWP_NOSIZE); } VOID WndTurnOnWaitCursor ( VOID ) /*++ Routine Description: WndTurnOnWaitCursor sets the cursor to IDC_WAIT. It maintains a use counter, so code requring the wait cursor can be nested. Arguments: none Return Value: none --*/ { if (g_CursorRefCount == 0) { g_OldCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); } g_CursorRefCount++; } VOID WndTurnOffWaitCursor ( VOID ) /*++ Routine Description: WndTurnOffWaitCursor decrements the wait cursor counter, and if it reaches zero the cursor is restored. Arguments: none Return Value: none --*/ { if (!g_CursorRefCount) { DEBUGMSG ((DBG_WHOOPS, "TurnOffWaitCursor called too many times")); } else { g_CursorRefCount--; if (!g_CursorRefCount) { SetCursor (g_OldCursor); } } } VOID WndSetWizardButtonsA ( IN HWND PageHandle, IN DWORD EnableButtons, IN DWORD DisableButtons, IN PCSTR AlternateFinishText OPTIONAL ) { DWORD flags = 0; HWND wizardHandle; wizardHandle = GetParent (PageHandle); if (EnableButtons & FINISH_BUTTON) { MYASSERT (!(EnableButtons & CANCEL_BUTTON)); MYASSERT (!(EnableButtons & NEXT_BUTTON)); MYASSERT (!(DisableButtons & CANCEL_BUTTON)); MYASSERT (!(DisableButtons & NEXT_BUTTON)); MYASSERT (!(DisableButtons & FINISH_BUTTON)); EnableButtons &= ~(CANCEL_BUTTON|NEXT_BUTTON); DisableButtons &= ~(CANCEL_BUTTON|NEXT_BUTTON); flags |= PSWIZB_FINISH; } if (DisableButtons & FINISH_BUTTON) { MYASSERT (!(EnableButtons & CANCEL_BUTTON)); MYASSERT (!(EnableButtons & NEXT_BUTTON)); MYASSERT (!(DisableButtons & CANCEL_BUTTON)); MYASSERT (!(DisableButtons & NEXT_BUTTON)); EnableButtons &= ~(CANCEL_BUTTON|NEXT_BUTTON); DisableButtons &= ~(CANCEL_BUTTON|NEXT_BUTTON); flags |= PSWIZB_DISABLEDFINISH; } if (EnableButtons & NEXT_BUTTON) { MYASSERT (!(DisableButtons & NEXT_BUTTON)); flags |= PSWIZB_NEXT; } if (EnableButtons & BACK_BUTTON) { MYASSERT (!(DisableButtons & BACK_BUTTON)); flags |= PSWIZB_BACK; } if (DisableButtons & NEXT_BUTTON) { flags &= ~PSWIZB_NEXT; } if (DisableButtons & BACK_BUTTON) { flags &= ~PSWIZB_BACK; } PropSheet_SetWizButtons (wizardHandle, flags); if (EnableButtons & CANCEL_BUTTON) { EnableWindow (GetDlgItem (wizardHandle, IDCANCEL), TRUE); } if (DisableButtons & CANCEL_BUTTON) { EnableWindow (GetDlgItem (wizardHandle, IDCANCEL), FALSE); } if (AlternateFinishText) { if (flags & PSWIZB_FINISH) { SendMessage ( wizardHandle, PSM_SETFINISHTEXT, 0, (LPARAM) AlternateFinishText ); } } } VOID WndSetWizardButtonsW ( IN HWND PageHandle, IN DWORD EnableButtons, IN DWORD DisableButtons, IN PCWSTR AlternateFinishText OPTIONAL ) { PCSTR ansiText; if (AlternateFinishText) { ansiText = ConvertWtoA (AlternateFinishText); WndSetWizardButtonsA (PageHandle, EnableButtons, DisableButtons, ansiText); FreeConvertedStr (ansiText); } else { WndSetWizardButtonsA (PageHandle, EnableButtons, DisableButtons, NULL); } }