windows-nt/Source/XPSP1/NT/sdktools/proccon/snapin/ppage.h
2020-09-26 16:20:57 +08:00

482 lines
11 KiB
C++

/*======================================================================================//
| Process Control //
| //
|Copyright (c) 1998 Sequent Computer Systems, Incorporated. All rights reserved. //
| //
|File Name: //
| //
|Description: //
| //
|Created: Paul Skoglund 07-1998 //
| //
|Rev History: //
| Based on code from ATL snapin wizard update for VC++ 6.0 - atlsnap.h
| In this module class CSnapInPropertyPageImpl renamed to
| CMySnapInPropertyPageImpl to avoid name clash
| Modified to provide better support for Wizard style property pages...
|
| 1999 03 22 Paul Skoglund
| Created CMySnapInPropertyWizardImpl template to use like CSnapInPropertyPageImpl
| but specific for Wizard style pages. The template forces declaration of
| Header Title resource ID and a SubHeader Title resource ID as used in the
| PSH_WIZARD97 style.
| Change to use Title as resource ID rather than string.
|
|=======================================================================================*/
#ifndef __PPAGE_H__
#define __PPAGE_H__
#ifndef ATLASSERT
#define ATLASSERT ASSERT
#endif
#include <mmc.h>
#include <commctrl.h>
#pragma comment(lib, "mmc.lib")
#pragma comment(lib, "comctl32.lib")
template <class T, bool bAutoDelete = true>
class ATL_NO_VTABLE CMySnapInPropertyPageImpl : public CDialogImplBase
{
public:
PROPSHEETPAGE m_psp;
operator PROPSHEETPAGE*() { return &m_psp; }
// Construction
CMySnapInPropertyPageImpl(int nTitle)
{
// initialize PROPSHEETPAGE struct
memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
m_psp.dwSize = sizeof(PROPSHEETPAGE);
m_psp.dwFlags = PSP_USECALLBACK;
m_psp.hInstance = _Module.GetResourceInstance();
m_psp.pszTemplate = MAKEINTRESOURCE(T::IDD);
m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
m_psp.pfnCallback = T::PropPageCallback;
m_psp.lParam = (LPARAM)this;
if(nTitle != NULL)
{
m_psp.pszTitle = MAKEINTRESOURCE(nTitle);
m_psp.dwFlags |= PSP_USETITLE;
}
}
static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
ATLASSERT(hWnd == NULL);
if(uMsg == PSPCB_CREATE)
{
CDialogImplBase* pPage = (CDialogImplBase*)ppsp->lParam;
_Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
}
if (bAutoDelete && uMsg == PSPCB_RELEASE)
{
T* pPage = (T*)ppsp->lParam;
delete pPage;
}
return 1;
}
HPROPSHEETPAGE Create()
{
return ::CreatePropertySheetPage(&m_psp);
}
BOOL EndDialog(int)
{
// do nothing here, calling ::EndDialog will close the whole sheet
ATLASSERT(FALSE);
return FALSE;
}
// Operations
void CancelToClose()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
::SendMessage(GetParent(), PSM_CANCELTOCLOSE, 0, 0L);
}
void SetModified(BOOL bChanged = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
if(bChanged)
::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0L);
else
::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
}
LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
}
typedef CMySnapInPropertyPageImpl< T, bAutoDelete > thisClass;
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
END_MSG_MAP()
// Message handler
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT(::IsWindow(m_hWnd));
NMHDR* pNMHDR = (NMHDR*)lParam;
// don't handle messages not from the page/sheet itself
if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
{
bHandled = FALSE;
return 1;
}
T* pT = (T*)this;
LRESULT lResult = 0;
// handle default
switch(pNMHDR->code)
{
case PSN_SETACTIVE:
lResult = pT->OnSetActive() ? 0 : -1;
break;
case PSN_KILLACTIVE:
lResult = !pT->OnKillActive();
break;
case PSN_APPLY:
lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
break;
case PSN_RESET:
pT->OnReset();
break;
case PSN_QUERYCANCEL:
lResult = !pT->OnQueryCancel();
break;
case PSN_WIZNEXT:
lResult = !pT->OnWizardNext();
break;
case PSN_WIZBACK:
lResult = !pT->OnWizardBack();
break;
case PSN_WIZFINISH:
lResult = !pT->OnWizardFinish();
break;
case PSN_HELP:
lResult = pT->OnHelp();
break;
default:
bHandled = FALSE; // not handled
}
return lResult;
}
// Overridables
BOOL OnSetActive()
{
return TRUE;
}
BOOL OnKillActive()
{
return TRUE;
}
BOOL OnApply()
{
return TRUE;
}
void OnReset()
{
}
BOOL OnQueryCancel()
{
return TRUE; // ok to cancel
}
BOOL OnWizardBack()
{
return TRUE;
}
BOOL OnWizardNext()
{
return TRUE;
}
BOOL OnWizardFinish()
{
return TRUE;
}
BOOL OnHelp()
{
return TRUE;
}
void DisableControl(UINT id)
{
T* pT = dynamic_cast<T*>(this);
if (!pT)
return;
HWND hWndCtl = pT->GetDlgItem(id);
ASSERT(hWndCtl);
if (hWndCtl)
::EnableWindow(hWndCtl, FALSE);
}
};
//
// For Wizard Pages...
//
template <class T, bool bAutoDelete = true>
class ATL_NO_VTABLE CMySnapInPropertyWizardImpl : public CDialogImplBase
{
protected:
BOOL OnBaseSetActive()
{
if (m_PagePosition != NOT_A_WIZARD)
{
DWORD dwFlags = 0;
if ( m_PagePosition == FIRST_PAGE )
dwFlags = PSWIZB_NEXT;
else if ( m_PagePosition == MIDDLE_PAGE )
dwFlags = PSWIZB_BACK | PSWIZB_NEXT;
else if ( m_PagePosition == LAST_PAGE )
dwFlags = PSWIZB_BACK | PSWIZB_FINISH;
else if ( m_PagePosition == LASTANDONLY_PAGE )
dwFlags = PSWIZB_FINISH;
::PostMessage(GetParent(), PSM_SETWIZBUTTONS, 0, (LPARAM) dwFlags);
}
T* pT = (T*)this;
return pT->OnSetActive();
}
public:
PROPSHEETPAGE m_psp;
typedef enum _WIZ_POSITION
{
NOT_A_WIZARD,
FIRST_PAGE,
MIDDLE_PAGE,
LAST_PAGE,
LASTANDONLY_PAGE,
} WIZ_POSITION;
WIZ_POSITION m_PagePosition;
operator PROPSHEETPAGE*() { return &m_psp; }
// Construction
CMySnapInPropertyWizardImpl(WIZ_POSITION pageposition, int nTitle)
{
//
m_PagePosition = pageposition;
// initialize PROPSHEETPAGE struct
memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
m_psp.dwSize = sizeof(PROPSHEETPAGE);
m_psp.dwFlags = PSP_USECALLBACK;
m_psp.hInstance = _Module.GetResourceInstance();
m_psp.pszTemplate = MAKEINTRESOURCE(T::IDD);
m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
m_psp.pfnCallback = T::PropPageCallback;
m_psp.lParam = (LPARAM)this;
if(nTitle)
{
m_psp.pszTitle = MAKEINTRESOURCE(nTitle);
m_psp.dwFlags |= PSP_USETITLE;
}
if (T::ID_HeaderTitle)
{
m_psp.dwFlags |= PSP_USEHEADERTITLE;
m_psp.pszHeaderTitle = MAKEINTRESOURCE(T::ID_HeaderTitle);
}
if (T::ID_HeaderSubTitle)
{
m_psp.dwFlags |= PSP_USEHEADERSUBTITLE;
m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(T::ID_HeaderSubTitle);
}
}
static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
ATLASSERT(hWnd == NULL);
if(uMsg == PSPCB_CREATE)
{
CDialogImplBase* pPage = (CDialogImplBase*)ppsp->lParam;
_Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
}
if (bAutoDelete && uMsg == PSPCB_RELEASE)
{
T* pPage = (T*)ppsp->lParam;
delete pPage;
}
return 1;
}
HPROPSHEETPAGE Create()
{
return ::CreatePropertySheetPage(&m_psp);
}
BOOL EndDialog(int)
{
// do nothing here, calling ::EndDialog will close the whole sheet
ATLASSERT(FALSE);
return FALSE;
}
// Operations
void CancelToClose()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
::SendMessage(GetParent(), PSM_CANCELTOCLOSE, 0, 0L);
}
void SetModified(BOOL bChanged = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
if(bChanged)
::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0L);
else
::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
}
LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
}
typedef CMySnapInPropertyWizardImpl< T, bAutoDelete > thisClass;
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
END_MSG_MAP()
// Message handler
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT(::IsWindow(m_hWnd));
NMHDR* pNMHDR = (NMHDR*)lParam;
// don't handle messages not from the page/sheet itself
if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
{
bHandled = FALSE;
return 1;
}
T* pT = (T*)this;
LRESULT lResult = 0;
// handle default
switch(pNMHDR->code)
{
case PSN_SETACTIVE:
lResult = pT->OnBaseSetActive() ? 0 : -1;
break;
case PSN_KILLACTIVE:
lResult = !pT->OnKillActive();
break;
case PSN_APPLY:
lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
break;
case PSN_RESET:
pT->OnReset();
break;
case PSN_QUERYCANCEL:
lResult = !pT->OnQueryCancel();
break;
case PSN_WIZNEXT:
lResult = !pT->OnWizardNext();
break;
case PSN_WIZBACK:
lResult = !pT->OnWizardBack();
break;
case PSN_WIZFINISH:
lResult = !pT->OnWizardFinish();
break;
case PSN_HELP:
lResult = pT->OnHelp();
break;
default:
bHandled = FALSE; // not handled
}
return lResult;
}
// Overridables
BOOL OnSetActive()
{
return TRUE;
}
BOOL OnKillActive()
{
return TRUE;
}
BOOL OnApply()
{
return TRUE;
}
void OnReset()
{
}
BOOL OnQueryCancel()
{
return TRUE; // ok to cancel
}
BOOL OnWizardBack()
{
return TRUE;
}
BOOL OnWizardNext()
{
return TRUE;
}
BOOL OnWizardFinish()
{
if ( m_PagePosition == LAST_PAGE )
{
T* pT = (T*)this;
if ( !pT->OnWizardNext() )
return FALSE;
}
return TRUE;
}
BOOL OnHelp()
{
return TRUE;
}
void DisableControl(UINT id)
{
T* pT = dynamic_cast<T*>(this);
if (!pT)
return;
HWND hWndCtl = pT->GetDlgItem(id);
ASSERT(hWndCtl);
if (hWndCtl)
::EnableWindow(hWndCtl, FALSE);
}
};
#endif // __PPAGE_H__