windows-nt/Source/XPSP1/NT/shell/ext/hnw/wizard/myprsht.cpp
2020-09-26 16:20:57 +08:00

877 lines
25 KiB
C++

//
// MyPrSht.cpp
//
// Implementation of the extensions made to the PropertySheet API
// in IE5, but which we need on all platforms.
//
// History:
//
// 10/11/1999 KenSh Created
//
#include "stdafx.h"
#include "TheApp.h"
#include "MyPrSht.h"
#include "CWnd.h"
#include "unicwrap.h"
// Thunk up to propsheetpage v6 for XP
typedef struct _PROPSHEETPAGEV6W
{
DWORD dwSize;
DWORD dwFlags;
HINSTANCE hInstance;
union
{
LPCWSTR pszTemplate;
#ifdef _WIN32
LPCDLGTEMPLATE pResource;
#else
const VOID *pResource;
#endif
} DUMMYUNIONNAME;
union
{
HICON hIcon;
LPCWSTR pszIcon;
} DUMMYUNIONNAME2;
LPCWSTR pszTitle;
DLGPROC pfnDlgProc;
LPARAM lParam;
LPFNPSPCALLBACKW pfnCallback;
UINT *pcRefParent;
#if (_WIN32_IE >= 0x0400)
LPCWSTR pszHeaderTitle; // this is displayed in the header
LPCWSTR pszHeaderSubTitle; ///
#endif
HANDLE hActCtx;
} PROPSHEETPAGEV6W, *LPPROPSHEETPAGEV6W;
// Local data
//
static CMyPropSheet* g_pMyPropSheet;
static const TCHAR c_szProp_ClassPointer[] = _T("CP");
#define DEFAULTHEADERHEIGHT 58 // in pixels
#define DEFAULTTEXTDIVIDERGAP 5
#define DEFAULTCTRLWIDTH 501 // page list window in new wizard style
#define DEFAULTCTRLHEIGHT 253 // page list window in new wizard style
#define TITLEX 22
#define TITLEY 10
#define SUBTITLEX 44
#define SUBTITLEY 25
// fixed sizes for the bitmap painted in the header section
#define HEADERBITMAP_Y 5
#define HEADERBITMAP_WIDTH 49
#define HEADERBITMAP_CXBACK (5 + HEADERBITMAP_WIDTH)
#define HEADERBITMAP_HEIGHT 49
#define HEADERSUBTITLE_WRAPOFFSET 10
// Fixed sizes for the watermark bitmap (Wizard97IE5 style)
#define BITMAP_WIDTH 164
#define BITMAP_HEIGHT 312
#define DRAWTEXT_WIZARD97FLAGS (DT_LEFT | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL)
#define IDD_PAGELIST 0x3020
#define IDD_DIVIDER 0x3026
#define IDD_TOPDIVIDER 0x3027
#ifndef IS_INTRESOURCE
#define IS_INTRESOURCE(psz) (HIWORD((DWORD_PTR)(psz)) == 0)
#endif
/////////////////////////////////////////////////////////////////////////////
// MyPropertySheet
INT_PTR MyPropertySheet(LPCPROPSHEETHEADER pHeader)
{
// If IE5 is present, use the built-in property sheet code
// REVIEW: should we bother checking for IE5 on older OS's?
if (theApp.IsWin98SEOrLater() && (! theApp.IsBiDiLocalized()) )
{
// BUGBUG THUNK THIS (but which way???)
return PropertySheet(pHeader);
}
// BUGBUG: nobody destroys g_pMyPropSheet, nobody does g_pMyPropSheet->Release()
ASSERT(g_pMyPropSheet == NULL);
g_pMyPropSheet = new CMyPropSheet();
if (g_pMyPropSheet)
return g_pMyPropSheet->DoPropSheet(pHeader);
else
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// MyCreatePropertySheetPage
HPROPSHEETPAGE MyCreatePropertySheetPage(LPPROPSHEETPAGE ppsp)
{
// If IE5 is present, use the built-in property sheet code
// REVIEW: should we bother checking for IE5 on older OS's?
if (theApp.IsWin98SEOrLater() && (! theApp.IsBiDiLocalized()) )
{
if (g_fRunningOnNT)
{
PROPSHEETPAGEV6W spv6;
ASSERT(sizeof (spv6) >= sizeof (PROPSHEETPAGE));
memcpy(&spv6, ppsp, sizeof (PROPSHEETPAGE));
spv6.dwSize = sizeof (spv6);
spv6.hActCtx = NULL;
return CreatePropertySheetPage((PROPSHEETPAGE*) &spv6);
}
else
{
return CreatePropertySheetPage(ppsp);
}
}
PROPSHEETPAGE psp;
CopyMemory(&psp, ppsp, ppsp->dwSize);
// REVIEW: this memory is never freed
LPPROPSHEETPAGE ppspOriginal = (LPPROPSHEETPAGE)malloc(sizeof(PROPSHEETPAGE));
if (ppspOriginal)
{
CopyMemory(ppspOriginal, ppsp, ppsp->dwSize);
psp.dwSize = PROPSHEETPAGE_V1_SIZE;
psp.dwFlags &= ~(PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE | PSP_HIDEHEADER);
psp.lParam = (LPARAM)ppspOriginal;
return ::CreatePropertySheetPage(&psp);
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// IsIMEWindow
BOOL IsIMEWindow(HWND hwnd, LPCREATESTRUCT lpcs)
{
// check for cheap CS_IME style first...
if (GetClassLong(hwnd, GCL_STYLE) & CS_IME)
return TRUE;
// get class name of the window that is being created
LPCTSTR pszClassName;
TCHAR szClassName[_countof("ime")+1];
if (HIWORD(lpcs->lpszClass))
{
pszClassName = lpcs->lpszClass;
}
else
{
szClassName[0] = _T('\0');
GlobalGetAtomName((ATOM)lpcs->lpszClass, szClassName, _countof(szClassName));
pszClassName = szClassName;
}
// a little more expensive to test this way, but necessary...
if (StrCmpI(pszClassName, _T("ime")) == 0)
return TRUE;
return FALSE; // not an IME window
}
void CMyPropSheet::SetHeaderFonts()
{
if (m_hFontBold == NULL)
{
LOGFONT LogFont;
GetObject(GetWindowFont(m_hWnd), sizeof(LogFont), &LogFont);
LogFont.lfWeight = FW_BOLD;
m_hFontBold = CreateFontIndirect(&LogFont);
}
}
// Kensh: Copied and modified from _ComputeHeaderHeight in prsht.c (comctl32.dll)
//
// In Wizard97 only:
// The subtitles user passed in could be larger than the two line spaces we give
// them, especially in localization cases. So here we go through all subtitles and
// compute the max space they need and set the header height so that no text is clipped
int CMyPropSheet::ComputeHeaderHeight(int dxMax)
{
SetHeaderFonts();
int dyHeaderHeight;
int dyTextDividerGap;
HDC hdc;
dyHeaderHeight = DEFAULTHEADERHEIGHT;
hdc = ::GetDC(m_hWnd);
// First, let's get the correct text height and spacing, this can be used
// as the title height and the between-lastline-and-divider spacing.
{
HFONT hFont, hFontOld;
TEXTMETRIC tm;
if (m_hFontBold)
hFont = m_hFontBold;
else
hFont = GetWindowFont(m_hWnd);
hFontOld = (HFONT)SelectObject(hdc, hFont);
if (GetTextMetrics(hdc, &tm))
{
dyTextDividerGap = tm.tmExternalLeading;
m_ySubTitle = max ((tm.tmHeight + tm.tmExternalLeading + TITLEY), SUBTITLEY);
}
else
{
dyTextDividerGap = DEFAULTTEXTDIVIDERGAP;
m_ySubTitle = SUBTITLEY;
}
if (hFontOld)
SelectObject(hdc, hFontOld);
}
// Second, get the subtitle text block height
// should make into a function if shared
{
RECT rcWrap;
// UINT uPages;
//
// WIZARD97IE5 subtracts out the space used by the header bitmap.
// WIZARD97IE4 uses the full width since the header bitmap
// in IE4 is a watermark and occupies no space.
//
// if (ppd->psh.dwFlags & PSH_WIZARD97IE4)
// rcWrap.right = dxMax;
// else
rcWrap.right = dxMax - HEADERBITMAP_CXBACK - HEADERSUBTITLE_WRAPOFFSET;
// Note (kensh): the "real" wizard code computes the max height across
// all pages. Our cheap version only computes the current page's height
LPPROPSHEETPAGE ppsp = GetCurrentPropSheetPage();
if (ppsp != NULL)
{
if (!(ppsp->dwFlags & PSP_HIDEHEADER) &&
(ppsp->dwFlags & PSP_USEHEADERSUBTITLE))
{
int iSubHeaderHeight = WriteHeaderTitle(hdc, &rcWrap, ppsp->pszHeaderSubTitle,
FALSE, DT_CALCRECT | DRAWTEXT_WIZARD97FLAGS);
if ((iSubHeaderHeight + m_ySubTitle) > dyHeaderHeight)
dyHeaderHeight = iSubHeaderHeight + m_ySubTitle;
}
}
}
// If the header height has been recomputed, set the correct gap between
// the text and the divider.
if (dyHeaderHeight != DEFAULTHEADERHEIGHT)
{
ASSERT(dyHeaderHeight > DEFAULTHEADERHEIGHT);
dyHeaderHeight += dyTextDividerGap;
}
::ReleaseDC(m_hWnd, hdc);
return dyHeaderHeight;
}
// Kensh: Copied and modified from _WriteHeaderTitle in prsht.c (comctl32.dll)
//
int CMyPropSheet::WriteHeaderTitle(HDC hdc, LPRECT prc, LPCTSTR pszTitle, BOOL bTitle, DWORD dwDrawFlags)
{
SetHeaderFonts();
LPCTSTR pszOut;
int cch;
int cx, cy;
UINT ETO_Flags=0;
SIZE Size;
TCHAR szTitle[MAX_PATH*4];
HFONT hFontOld = NULL;
HFONT hFont;
int yDrawHeight = 0;
if (IS_INTRESOURCE(pszTitle))
{
LPPROPSHEETPAGE ppsp = GetCurrentPropSheetPage();
if (NULL != ppsp)
{
LoadString(ppsp->hInstance, (UINT)LOWORD(pszTitle), szTitle, _countof(szTitle));
}
else
{
*szTitle = 0;
}
pszOut = szTitle;
}
else
pszOut = pszTitle;
cch = lstrlen(pszOut);
if (bTitle && m_hFontBold)
hFont = m_hFontBold;
else
hFont = GetWindowFont(m_hWnd);
hFontOld = (HFONT)SelectObject(hdc, hFont);
if (bTitle)
{
cx = TITLEX;
cy = TITLEY;
if (theApp.IsBiDiLocalized())
{
ETO_Flags |= ETO_RTLREADING;
if (GetTextExtentPoint32(hdc, pszOut, lstrlen (pszOut), &Size))
cx = prc->right - Size.cx;
}
ExtTextOut(hdc, cx, cy, ETO_Flags, prc, pszOut, cch, NULL);
}
else
{
RECT rcWrap;
CopyRect(&rcWrap, prc);
rcWrap.left = SUBTITLEX;
rcWrap.top = m_ySubTitle;
if (theApp.IsBiDiLocalized())
{
dwDrawFlags |= DT_RTLREADING | DT_RIGHT;
}
yDrawHeight = DrawText(hdc, pszOut, cch, &rcWrap, dwDrawFlags);
}
if (hFontOld)
SelectObject(hdc, hFontOld);
return yDrawHeight;
}
/////////////////////////////////////////////////////////////////////////////
// CMyPropSheet
CMyPropSheet::CMyPropSheet()
{
m_pRealHeader = NULL;
m_hHook = NULL;
m_hbrWindow = NULL;
m_hbrDialog = NULL;
m_hwndActive = NULL;
m_hbmWatermark = NULL;
m_hbmHeader = NULL;
m_hpalWatermark = NULL;
m_hFontBold = NULL;
}
CMyPropSheet::~CMyPropSheet()
{
free(m_pRealHeader);
ASSERT(m_hHook == NULL);
if (m_hbrWindow != NULL)
DeleteObject(m_hbrWindow);
if (m_hbrDialog != NULL)
DeleteObject(m_hbrDialog);
}
void CMyPropSheet::InitColorSettings()
{
if (m_hbrWindow != NULL)
DeleteObject(m_hbrWindow);
m_hbrWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
if (m_hbrDialog != NULL)
DeleteObject(m_hbrDialog);
m_hbrDialog = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
}
void CMyPropSheet::LoadBitmaps()
{
LPPROPSHEETHEADER ppsh = m_pRealHeader;
if (ppsh)
{
if (ppsh->dwFlags & PSH_USEHBMHEADER)
m_hbmHeader = ppsh->hbmHeader;
else
m_hbmHeader = LoadBitmap(ppsh->hInstance, ppsh->pszbmHeader);
if (ppsh->dwFlags & PSH_USEHBMWATERMARK)
m_hbmWatermark = ppsh->hbmWatermark;
else
m_hbmWatermark = LoadBitmap(ppsh->hInstance, ppsh->pszbmWatermark);
// Note: might need a palette later, but so far it hasn't been necessary
}
}
INT_PTR CMyPropSheet::DoPropSheet(LPCPROPSHEETHEADER ppsh)
{
INT_PTR nResult = 0;
ASSERT(m_pRealHeader == NULL);
m_pRealHeader = (LPPROPSHEETHEADER)malloc(ppsh->dwSize);
if (m_pRealHeader)
{
CopyMemory(m_pRealHeader, ppsh, ppsh->dwSize);
InitColorSettings();
// Create header and watermark bitmaps
LoadBitmaps();
PROPSHEETHEADER psh;
ASSERT(sizeof(psh) >= ppsh->dwSize);
CopyMemory(&psh, ppsh, ppsh->dwSize);
psh.dwSize = PROPSHEETHEADER_V1_SIZE;
psh.dwFlags &= 0x00000fff; // W95 gold comctl32 prop sheet mask.
psh.dwFlags |= PSH_WIZARD;
ASSERT(m_hHook == NULL);
m_hHook = SetWindowsHookEx(WH_CBT, HookProc, NULL, GetCurrentThreadId());
nResult = ::PropertySheet(&psh);
if (m_hHook != NULL)
{
UnhookWindowsHookEx(m_hHook);
m_hHook = NULL;
}
}
return nResult;
}
LRESULT CALLBACK CMyPropSheet::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
ASSERT(g_pMyPropSheet != NULL);
LRESULT lResult = CallNextHookEx(g_pMyPropSheet->m_hHook, nCode, wParam, lParam);
if (nCode == HCBT_CREATEWND)
{
HWND hwnd = (HWND)wParam;
LPCBT_CREATEWND pCbt = (LPCBT_CREATEWND)lParam;
// Make sure this isn't an IME window
if (IsIMEWindow(hwnd, pCbt->lpcs))
goto done;
if (g_pMyPropSheet->m_hWnd == NULL) // The main wizard window
{
// Add the WS_EX_DLGMODALFRAME extended style to the window
// Remove WS_EX_CONTEXTHELP extended style from the window
SHSetWindowBits(hwnd, GWL_EXSTYLE, WS_EX_DLGMODALFRAME|WS_EX_CONTEXTHELP, WS_EX_DLGMODALFRAME);
// Add the WS_SYSMENU style to the window
SHSetWindowBits(hwnd, GWL_STYLE, WS_SYSMENU, WS_SYSMENU);
// Subclass the window
g_pMyPropSheet->Attach(hwnd);
}
else if (pCbt->lpcs->hwndParent == g_pMyPropSheet->m_hWnd &&
pCbt->lpcs->hMenu == NULL &&
(pCbt->lpcs->style & WS_CHILD) == WS_CHILD)
{
// It's a wizard page sub-dialog -- subclass it so we can
// draw its background
CMyPropPage* pPropPage = new CMyPropPage;
if (pPropPage)
{
pPropPage->Attach(hwnd);
pPropPage->Release();
}
}
}
else if (nCode == HCBT_DESTROYWND)
{
HWND hwnd = (HWND)wParam;
if (hwnd == g_pMyPropSheet->m_hWnd)
{
// Main window being destroyed -- stop hooking window creation
UnhookWindowsHookEx(g_pMyPropSheet->m_hHook);
g_pMyPropSheet->m_hHook = NULL;
}
}
done:
return lResult;
}
LPPROPSHEETPAGE CMyPropSheet::GetCurrentPropSheetPage()
{
CMyPropPage* pPage = CMyPropPage::FromHandle(GetActivePage());
if (pPage)
{
return pPage->GetPropSheetPage();
}
return NULL;
}
LRESULT CMyPropSheet::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SETTINGCHANGE:
{
InitColorSettings();
return Default(message, wParam, lParam);
}
case PSM_SETCURSEL:
{
InvalidateRect(m_hWnd, NULL, TRUE);
return Default(message, wParam, lParam);
}
break;
/*
case WM_ERASEBKGND:
{
TRACE("Main window - WM_ERASEBKGND - active page = %X\r\n", GetActivePage());
LPPROPSHEETPAGE ppsp = GetCurrentPropSheetPage();
HDC hdc = (HDC)wParam;
RECT rcClient;
GetClientRect(&rcClient);
if (ppsp->dwFlags & PSP_HIDEHEADER)
{
RECT rcDivider;
GetDlgItemRect(hwnd, IDD_DIVIDER, &rcDivider);
rcClient.top = rcDivider.bottom;
FillRect(hdc, &rcClient, m_hbrDialog);
rcClient.bottom = rcClient.top;
rcClient.top = 0;
FillRect(hdc, &rcClient, m_hbrWindow);
return TRUE;
}
else
{
RECT rcHeader;
CopyRect(&rcHeader, &rcClient);
rcHeader.bottom = DEFAULTHEADERHEIGHT;
FillRect(hdc, &rcHeader, m_hbrWindow);
rcClient.top = rcHeader.bottom;
FillRect(hdc, &rcClient, m_hbrDialog);
}
}
return FALSE;
*/
case WM_PAINT:
{
PAINTSTRUCT ps;
LPPROPSHEETPAGE ppsp = GetCurrentPropSheetPage();
HDC hdc = ::BeginPaint(m_hWnd, &ps);
if (ppsp != NULL)
{
if (ppsp->dwFlags & PSP_HIDEHEADER)
{
// Draw the watermark
PaintWatermark(hdc, ppsp);
}
else
{
// Draw the header
PaintHeader(hdc, ppsp);
}
}
::EndPaint(m_hWnd, &ps);
}
break;
case WM_CTLCOLOREDIT:
case WM_CTLCOLORDLG:
case WM_CTLCOLOR:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORBTN:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
{
return (LRESULT)OnCtlColor(message, (HDC)wParam, (HWND)lParam);
}
default:
{
return Default(message, wParam, lParam);
}
}
return 0;
}
HBRUSH CMyPropSheet::OnCtlColor(UINT message, HDC hdc, HWND hwndControl)
{
HBRUSH hbr = (HBRUSH)Default(message, (WPARAM)hdc, (LPARAM)hwndControl);
if (message == WM_CTLCOLOREDIT || message == WM_CTLCOLORDLG)
return hbr;
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
return m_hbrWindow;
}
//
// lprc is the target rectangle.
// Use as much of the bitmap as will fit into the target rectangle.
// If the bitmap is smaller than the target rectangle, then fill the rest with
// the pixel in the upper left corner of the hbmpPaint.
//
void PaintWithPaletteBitmap(HDC hdc, LPRECT lprc, HPALETTE hplPaint, HBITMAP hbmpPaint)
{
HDC hdcBmp = CreateCompatibleDC(hdc);
if (hdcBmp)
{
BITMAP bm;
int cxRect, cyRect, cxBmp, cyBmp;
GetObject(hbmpPaint, sizeof(BITMAP), &bm);
SelectObject(hdcBmp, hbmpPaint);
if (hplPaint)
{
SelectPalette(hdc, hplPaint, FALSE);
RealizePalette(hdc);
}
cxRect = RECTWIDTH(*lprc);
cyRect = RECTHEIGHT(*lprc);
// Never use more pixels from the bmp as we have room in the rect.
cxBmp = min(bm.bmWidth, cxRect);
cyBmp = min(bm.bmHeight, cyRect);
BitBlt(hdc, lprc->left, lprc->top, cxBmp, cyBmp, hdcBmp, 0, 0, SRCCOPY);
// If bitmap is too narrow, then StretchBlt to fill the width.
if (cxBmp < cxRect)
StretchBlt(hdc, lprc->left + cxBmp, lprc->top,
cxRect - cxBmp, cyBmp,
hdcBmp, 0, 0, 1, 1, SRCCOPY);
// If bitmap is to short, then StretchBlt to fill the height.
if (cyBmp < cyRect)
StretchBlt(hdc, lprc->left, cyBmp,
cxRect, cyRect - cyBmp,
hdcBmp, 0, 0, 1, 1, SRCCOPY);
DeleteDC(hdcBmp);
}
}
void CMyPropSheet::PaintWatermark(HDC hdc, LPPROPSHEETPAGE ppsp)
{
RECT rcClient;
RECT rcClient_Dlg;
GetClientRect(m_hWnd, &rcClient);
GetClientRect(m_hWnd, &rcClient_Dlg);
RECT rcDivider;
GetDlgItemRect(m_hWnd, IDD_DIVIDER, &rcDivider);
if (m_hbmWatermark)
{
// Bottom gets gray
rcClient.top = rcDivider.bottom;
FillRect(hdc, &rcClient, m_hbrDialog);
rcClient.bottom = rcClient.top;
rcClient.top = 0;
// Right-hand side gets m_hbrWindow.
if (theApp.IsBiDiLocalized())
rcClient.right = rcClient_Dlg.right - BITMAP_WIDTH;
else
rcClient.left = BITMAP_WIDTH;
FillRect(hdc, &rcClient, m_hbrWindow);
// Left-hand side gets watermark in top portion with autofill...
if (theApp.IsBiDiLocalized())
{
rcClient.right = rcClient_Dlg.right;
rcClient.left = rcClient_Dlg.right - BITMAP_WIDTH;
}
else
{
rcClient.right = rcClient.left;
rcClient.left = 0;
}
PaintWithPaletteBitmap(hdc, &rcClient, m_hpalWatermark, m_hbmWatermark);
}
}
void CMyPropSheet::PaintHeader(HDC hdc, LPPROPSHEETPAGE ppsp)
{
RECT rcClient, rcHeaderBitmap;
GetClientRect(m_hWnd, &rcClient);
int cyHeader = ComputeHeaderHeight(rcClient.right);
// Bottom gets gray
rcClient.top = cyHeader;
FillRect(hdc, &rcClient, m_hbrDialog);
// Top gets white
rcClient.bottom = rcClient.top;
rcClient.top = 0;
FillRect(hdc, &rcClient, m_hbrWindow);
// Draw the fixed-size header bitmap
int bx= RECTWIDTH(rcClient) - HEADERBITMAP_CXBACK;
ASSERT(bx > 0);
SetRect(&rcHeaderBitmap, bx, HEADERBITMAP_Y, bx + HEADERBITMAP_WIDTH, HEADERBITMAP_Y + HEADERBITMAP_HEIGHT);
PaintWithPaletteBitmap(hdc, &rcHeaderBitmap, m_hpalWatermark, m_hbmHeader);
// Draw header title & subtitle
rcClient.right = bx - HEADERSUBTITLE_WRAPOFFSET;
WriteHeaderTitle(hdc, &rcClient, ppsp->pszHeaderTitle, TRUE, DRAWTEXT_WIZARD97FLAGS);
WriteHeaderTitle(hdc, &rcClient, ppsp->pszHeaderSubTitle, FALSE, DRAWTEXT_WIZARD97FLAGS);
}
/////////////////////////////////////////////////////////////////////////////
// CMyPropPage
CMyPropPage* CMyPropPage::FromHandle(HWND hwnd)
{
return (CMyPropPage*)(CWnd::FromHandle(hwnd));
}
LPPROPSHEETPAGE CMyPropPage::GetPropSheetPage()
{
return m_ppspOriginal;
}
LRESULT CMyPropPage::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
LPPROPSHEETPAGE ppspBogus = (LPPROPSHEETPAGE)lParam;
LPPROPSHEETPAGE ppspOriginal = (LPPROPSHEETPAGE) ppspBogus->lParam;
m_ppspOriginal = ppspOriginal;
lParam = (LPARAM)ppspOriginal;
}
break;
case WM_ERASEBKGND:
{
if ((m_ppspOriginal->dwFlags & PSP_HIDEHEADER) != 0)
{
// Let the parent window bleed through
return FALSE;
}
}
break;
case WM_CTLCOLORSTATIC:
{
if ((m_ppspOriginal->dwFlags & PSP_HIDEHEADER) != 0)
{
return (LRESULT)g_pMyPropSheet->OnCtlColor(message, (HDC)wParam, (HWND)lParam);
}
}
break;
case WM_NOTIFY:
{
NMHDR* pHdr = (NMHDR*)lParam;
switch (pHdr->code)
{
case PSN_KILLACTIVE:
{
// TRACE("PSN_KILLACTIVE - hwnd = %X\r\n", hwnd);
}
break;
case PSN_SETACTIVE:
{
// TRACE("PSN_SETACTIVE - hwnd = %X\r\n", hwnd);
HWND hwndParent = GetParent(m_hWnd);
RECT rcParent;
::GetClientRect(hwndParent, &rcParent);
RECT rcTopDivider;
HWND hwndTopDivider = GetDlgItemRect(hwndParent, IDD_TOPDIVIDER, &rcTopDivider);
// Hide the tab control (not sure why it's showing up, but it shouldn't)
ShowWindow(::GetDlgItem(hwndParent, IDD_PAGELIST), SW_HIDE);
RECT rcDivider;
HWND hwndDivider = GetDlgItemRect(hwndParent, IDD_DIVIDER, &rcDivider);
// Set the proper size and position for the dialog
if ((m_ppspOriginal->dwFlags & PSP_HIDEHEADER) != 0)
{
// Reposition the divider
SetWindowPos(hwndDivider, NULL, 0, rcDivider.top, rcParent.right, RECTHEIGHT(rcDivider),
SWP_NOZORDER | SWP_NOACTIVATE);
// Hide the top divider
if (hwndTopDivider != NULL)
ShowWindow(hwndTopDivider, SW_HIDE);
// Reposition the dialog
SetWindowPos(m_hWnd, NULL, rcParent.left, rcParent.top, RECTWIDTH(rcParent), rcDivider.top - rcParent.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
else
{
int cyHeader = g_pMyPropSheet->ComputeHeaderHeight(rcParent.right);
// Reposition and show the top divider
if (hwndTopDivider != NULL)
{
SetWindowPos(hwndTopDivider, NULL, 0, cyHeader, rcParent.right, RECTHEIGHT(rcTopDivider),
SWP_NOZORDER | SWP_NOACTIVATE);
ShowWindow(hwndTopDivider, SW_SHOW);
}
// Reposition the dialog
SetWindowPos(m_hWnd, NULL, rcParent.left + 7, cyHeader + 7, RECTWIDTH(rcParent) - 14, rcDivider.top - cyHeader - 14,
SWP_NOZORDER | SWP_NOACTIVATE);
}
g_pMyPropSheet->OnSetActivePage(m_hWnd);
}
break;
}
}
break;
default:
break;
}
return CWnd::Default(message, wParam, lParam);
}