167 lines
4.8 KiB
C++
167 lines
4.8 KiB
C++
/***
|
|
|
|
Source File: Property Page.CPP
|
|
|
|
Implements the CPropertyPage class. See the associated header file for
|
|
details.
|
|
|
|
Copyright (c) 1996 by Microsoft Corporation
|
|
|
|
A Pretty Penny Enterprises Production
|
|
|
|
Change History:
|
|
|
|
11-01-96 a-robkj@microsoft.com- original version
|
|
12-04-96 a-robkj@microsoft.com retrieve handle to sheet, Create a derived
|
|
class for shell extension pages
|
|
|
|
***/
|
|
|
|
#include "ICMUI.H"
|
|
|
|
// CPropertyPage member functions
|
|
|
|
// Class constructor- basic initializations. Any remaining PROPSHEETPAGE
|
|
// initializations are expected to be done by the derived class.
|
|
|
|
CPropertyPage::CPropertyPage() {
|
|
m_psp.dwSize = sizeof m_psp;
|
|
m_psp.pfnDlgProc = (DLGPROC) DialogProc;
|
|
m_psp.lParam = (LPARAM) this;
|
|
m_psp.dwFlags = PSP_DEFAULT; // Can be overriden later
|
|
m_hpsp = NULL;
|
|
m_bChanged = FALSE;
|
|
}
|
|
|
|
// Handle retrieval- I'll admit an addiction to one-liners
|
|
|
|
HPROPSHEETPAGE CPropertyPage::Handle() {
|
|
return m_hpsp = (m_hpsp ? m_hpsp : CreatePropertySheetPage(&m_psp));
|
|
}
|
|
|
|
// Dialog Procedure
|
|
|
|
BOOL CALLBACK CPropertyPage::DialogProc(HWND hwndPage, UINT uMsg, WPARAM wp,
|
|
LPARAM lp) {
|
|
|
|
CPropertyPage *pcppMe =
|
|
(CPropertyPage *) GetWindowLongPtr(hwndPage, DWLP_USER);
|
|
|
|
switch (uMsg) {
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
// In this case, lp points to the PROPSHEETHEADER that created
|
|
// us. We look into its lParam member for our this pointer,
|
|
// and store this in the dialog's private data. This lets us
|
|
// use the pointer to get at all of our overridable functions.
|
|
|
|
pcppMe = (CPropertyPage *) ((LPPROPSHEETPAGE) lp) -> lParam;
|
|
|
|
SetWindowLongPtr(hwndPage, DWLP_USER, (LONG_PTR) pcppMe);
|
|
pcppMe -> m_hwnd = hwndPage;
|
|
|
|
// Now, see if the derived class has any initialization needs
|
|
|
|
return pcppMe -> OnInit();
|
|
|
|
// Overridable processing for standard control notifications
|
|
|
|
case WM_COMMAND:
|
|
|
|
return pcppMe -> OnCommand(HIWORD(wp), LOWORD(wp), (HWND) lp);
|
|
|
|
case WM_DESTROY:
|
|
|
|
return pcppMe -> OnDestroy();
|
|
|
|
case WM_HELP:
|
|
|
|
return pcppMe -> OnHelp((LPHELPINFO) lp);
|
|
|
|
case WM_CONTEXTMENU:
|
|
|
|
return pcppMe -> OnContextMenu((HWND) wp);
|
|
|
|
// Overridable processing for common control notifications
|
|
|
|
case WM_NOTIFY: {
|
|
|
|
// If the message is PSM_SETACTIVE, note the property sheet hwnd
|
|
|
|
LPNMHDR pnmh = (LPNMHDR) lp;
|
|
|
|
if (pnmh -> code == PSN_SETACTIVE)
|
|
pcppMe -> m_hwndSheet = pnmh -> hwndFrom;
|
|
return pcppMe -> OnNotify((int) wp, pnmh);
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE; // We didn't handle the message.
|
|
}
|
|
|
|
// CShellExtensionPage class member methods
|
|
|
|
CShellExtensionPage *CShellExtensionPage::m_pcsepAnchor = NULL;
|
|
|
|
// We enable reference counting, partially because on NT, the Window handle
|
|
// sometimes appears invalid even while the dialog is up. However, we also
|
|
// keep the chaining mechanism, as this is the only sane way we have of
|
|
// freeing up the object instances we've created.
|
|
|
|
CShellExtensionPage::CShellExtensionPage() {
|
|
|
|
if (m_pcsepAnchor) {
|
|
|
|
// If there is a cell other than anchor, update its list.
|
|
if (m_pcsepAnchor -> m_pcsepNext)
|
|
m_pcsepAnchor -> m_pcsepNext -> m_pcsepPrevious = this;
|
|
// Insert this cell right after the anchor.
|
|
m_pcsepPrevious = m_pcsepAnchor;
|
|
m_pcsepNext = m_pcsepAnchor -> m_pcsepNext;
|
|
m_pcsepAnchor -> m_pcsepNext = this;
|
|
}
|
|
else {
|
|
|
|
m_pcsepAnchor = this;
|
|
m_pcsepNext = m_pcsepPrevious = NULL;
|
|
}
|
|
|
|
m_psp.pcRefParent = (UINT *) &CGlobals::ReferenceCounter();
|
|
m_psp.dwFlags |= PSP_USEREFPARENT;
|
|
}
|
|
|
|
CShellExtensionPage::~CShellExtensionPage() {
|
|
|
|
if (this == m_pcsepAnchor) {
|
|
m_pcsepAnchor = m_pcsepNext;
|
|
if (m_pcsepAnchor) {
|
|
// Anchor never has previous.
|
|
m_pcsepAnchor -> m_pcsepPrevious = NULL;
|
|
}
|
|
}
|
|
else {
|
|
m_pcsepPrevious -> m_pcsepNext = m_pcsepNext;
|
|
// If there is other cell following this, update it.
|
|
if (m_pcsepNext)
|
|
m_pcsepNext -> m_pcsepPrevious = m_pcsepPrevious;
|
|
}
|
|
}
|
|
|
|
// This little ditty lets us decide when it's safe to unload the DLL- it also
|
|
// guarantees all class destructors are called as sheets get closed by the
|
|
// various potential callers.
|
|
|
|
BOOL CShellExtensionPage::OKToClose() {
|
|
|
|
while (m_pcsepAnchor) {
|
|
if (IsWindow(m_pcsepAnchor -> m_hwnd))
|
|
return FALSE; // This page is still alive!
|
|
|
|
delete m_pcsepAnchor; // Page isn't alive, delete it...
|
|
}
|
|
|
|
return TRUE; // No more pages allocated
|
|
}
|