537 lines
9.8 KiB
C
537 lines
9.8 KiB
C
/*++
|
|
|
|
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);
|
|
}
|
|
}
|
|
|