📄 dlgprop.cpp
字号:
}
/////////////////////////////////////////////////////////////////////////////
// CPropertySheet -- a tabbed "dialog" (really a popup-window)
BEGIN_MESSAGE_MAP(CPropertySheet, CWnd)
//{{AFX_MSG_MAP(CPropertySheet)
ON_WM_CTLCOLOR()
ON_WM_NCCREATE()
ON_MESSAGE(WM_INITDIALOG, HandleInitDialog)
ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
ON_WM_CLOSE()
ON_WM_SYSCOMMAND()
ON_MESSAGE(DM_SETDEFID, OnSetDefID)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
AFX_STATIC_DATA const int _afxPropSheetIDs[4] = { ID_WIZNEXT, ID_WIZFINISH, ID_WIZBACK, IDCANCEL };
AFX_OLDPROPSHEETHEADER* CPropertySheet::GetPropSheetHeader()
{
CPropertySheetEx* pSheetEx = DYNAMIC_DOWNCAST(CPropertySheetEx, this);
if (pSheetEx != NULL)
return (AFX_OLDPROPSHEETHEADER*)&pSheetEx->m_psh;
else
return &m_psh;
}
LRESULT CPropertySheet::OnSetDefID(WPARAM wParam, LPARAM lParam)
{
// WINBUG -- A wrong or invalid ID may be passed in here. If this is the
// case, then look for a valid one.
HWND hWnd;
if (IsWizard() &&
(
((hWnd = ::GetDlgItem(m_hWnd, wParam)) == NULL) ||
!(::GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE) ||
!::IsWindowEnabled(hWnd)
))
{
for (int i = 0; i < 4; i++)
{
// find first button that is visible and enabled
HWND hWnd = ::GetDlgItem(m_hWnd, _afxPropSheetIDs[i]);
if ((GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE) &&
::IsWindowEnabled(hWnd))
{
//WINBUG -- focus could be incorrect as well in this case
// so ... let's set it to the default button
HWND hWndFocus = ::GetFocus();
if (!::IsWindowEnabled(hWndFocus))
::SetFocus(hWnd);
return DefWindowProc(DM_SETDEFID, _afxPropSheetIDs[i], lParam);
}
}
}
return Default();
}
CPropertySheet::CPropertySheet()
{
CommonConstruct(NULL, 0);
}
CPropertySheet::CPropertySheet(UINT nIDCaption, CWnd* pParentWnd,
UINT iSelectPage)
{
ASSERT(nIDCaption != 0);
VERIFY(m_strCaption.LoadString(nIDCaption) != 0);
CommonConstruct(pParentWnd, iSelectPage);
}
CPropertySheet::CPropertySheet(LPCTSTR pszCaption, CWnd* pParentWnd,
UINT iSelectPage)
{
ASSERT(pszCaption != NULL);
m_strCaption = pszCaption;
CommonConstruct(pParentWnd, iSelectPage);
}
void CPropertySheet::Construct(UINT nIDCaption, CWnd* pParentWnd,
UINT iSelectPage)
{
ASSERT(nIDCaption != 0);
VERIFY(m_strCaption.LoadString(nIDCaption) != 0);
CommonConstruct(pParentWnd, iSelectPage);
}
void CPropertySheet::Construct(LPCTSTR pszCaption, CWnd* pParentWnd,
UINT iSelectPage)
{
ASSERT(pszCaption != NULL);
m_strCaption = pszCaption;
CommonConstruct(pParentWnd, iSelectPage);
}
void CPropertySheet::CommonConstruct(CWnd* pParentWnd, UINT iSelectPage)
{
memset(&m_psh, 0, sizeof(m_psh));
m_psh.dwSize = sizeof(m_psh);
m_psh.dwFlags = PSH_PROPSHEETPAGE;
m_psh.pszCaption = m_strCaption;
m_psh.nStartPage = iSelectPage;
m_bStacked = TRUE;
m_bModeless = FALSE;
if (AfxHelpEnabled())
m_psh.dwFlags |= PSH_HASHELP;
m_pParentWnd = pParentWnd; // m_psh.hwndParent set in DoModal/create
}
void CPropertySheet::EnableStackedTabs(BOOL bStacked)
{
m_bStacked = bStacked;
}
void CPropertySheet::SetTitle(LPCTSTR lpszText, UINT nStyle)
{
ASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
ASSERT(lpszText == NULL || AfxIsValidString(lpszText));
if (m_hWnd == NULL)
{
AFX_OLDPROPSHEETHEADER* psh = GetPropSheetHeader();
// set internal state
m_strCaption = lpszText;
psh->pszCaption = m_strCaption;
psh->dwFlags &= ~PSH_PROPTITLE;
psh->dwFlags |= nStyle;
}
else
{
// set external state
SendMessage(PSM_SETTITLE, nStyle, (LPARAM)lpszText);
}
}
CPropertySheet::~CPropertySheet()
{
delete[] (PROPSHEETPAGE*)m_psh.ppsp;
}
BOOL CPropertySheet::PreTranslateMessage(MSG* pMsg)
{
ASSERT_VALID(this);
// allow tooltip messages to be filtered
if (CWnd::PreTranslateMessage(pMsg))
return TRUE;
// allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab,
// Ctrl+PageUp, and Ctrl+PageDown
if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
(pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
{
if (SendMessage(PSM_ISDIALOGMESSAGE, 0, (LPARAM)pMsg))
return TRUE;
}
// handle rest with IsDialogMessage
return PreTranslateInput(pMsg);
}
BOOL CPropertySheet::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
if ((nCode != CN_COMMAND && nCode != CN_UPDATE_COMMAND_UI) ||
!IS_COMMAND_ID(nID) || nID >= 0xf000)
{
// control notification or non-command button or system command
return FALSE; // not routed any further
}
// if we have an owner window, give it second crack
CWnd* pOwner = GetParent();
if (pOwner != NULL)
{
#ifdef _DEBUG
if (afxTraceFlags & traceCmdRouting)
TRACE1("Routing command id 0x%04X to owner window.\n", nID);
#endif
ASSERT(pOwner != this);
if (pOwner->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
}
// last crack goes to the current CWinThread object
CWinThread* pThread = AfxGetThread();
if (pThread != NULL)
{
#ifdef _DEBUG
if (afxTraceFlags & traceCmdRouting)
TRACE1("Routing command id 0x%04X to app.\n", nID);
#endif
if (pThread->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
}
#ifdef _DEBUG
if (afxTraceFlags & traceCmdRouting)
{
TRACE2("IGNORING command id 0x%04X sent to %hs dialog.\n", nID,
GetRuntimeClass()->m_lpszClassName);
}
#endif
return FALSE;
}
CPropertyPage* CPropertySheet::GetActivePage() const
{
ASSERT_VALID(this);
CPropertyPage* pPage;
if (m_hWnd != NULL)
pPage = STATIC_DOWNCAST(CPropertyPage,
CWnd::FromHandle((HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0)));
else
pPage = GetPage(GetActiveIndex());
return pPage;
}
BOOL CPropertySheet::ContinueModal()
{
// allow CWnd::EndModalLoop to be used
if (!CWnd::ContinueModal())
return FALSE;
// when active page is NULL, the modal loop should end
ASSERT(::IsWindow(m_hWnd));
BOOL bResult = SendMessage(PSM_GETCURRENTPAGEHWND);
return bResult;
}
int CPropertySheet::DoModal()
{
ASSERT_VALID(this);
ASSERT(m_hWnd == NULL);
// register common controls
VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
// finish building PROPSHEETHEADER structure
BuildPropPageArray();
// allow OLE servers to disable themselves
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
pApp->EnableModeless(FALSE);
// find parent HWND
HWND hWndTop;
HWND hWndParent = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &hWndTop);
AFX_OLDPROPSHEETHEADER* psh = GetPropSheetHeader();
psh->hwndParent = hWndParent;
BOOL bEnableParent = FALSE;
if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
{
::EnableWindow(hWndParent, FALSE);
bEnableParent = TRUE;
}
HWND hWndCapture = ::GetCapture();
if (hWndCapture != NULL)
::SendMessage(hWndCapture, WM_CANCELMODE, 0, 0);
// setup for modal loop and creation
m_nModalResult = 0;
m_nFlags |= WF_CONTINUEMODAL;
// hook for creation of window
AfxHookWindowCreate(this);
psh->dwFlags |= PSH_MODELESS;
m_nFlags |= WF_CONTINUEMODAL;
HWND hWnd = (HWND)::PropertySheet((PROPSHEETHEADER*)psh);
#ifdef _DEBUG
DWORD dwError = ::GetLastError();
#endif
psh->dwFlags &= ~PSH_MODELESS;
AfxUnhookWindowCreate();
// handle error
if (hWnd == NULL || hWnd == (HWND)-1)
{
TRACE1("PropertySheet() failed: GetLastError returned %d\n", dwError);
m_nFlags &= ~WF_CONTINUEMODAL;
}
int nResult = m_nModalResult;
if (ContinueModal())
{
// enter modal loop
DWORD dwFlags = MLF_SHOWONIDLE;
if (GetStyle() & DS_NOIDLEMSG)
dwFlags |= MLF_NOIDLEMSG;
nResult = RunModalLoop(dwFlags);
}
// hide the window before enabling parent window, etc.
if (m_hWnd != NULL)
{
SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|
SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
}
if (bEnableParent)
::EnableWindow(hWndParent, TRUE);
if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
::SetActiveWindow(hWndParent);
// cleanup
DestroyWindow();
// allow OLE servers to enable themselves
if (pApp != NULL)
pApp->EnableModeless(TRUE);
if (hWndTop != NULL)
::EnableWindow(hWndTop, TRUE);
return nResult;
}
int CALLBACK
AfxPropSheetCallback(HWND, UINT message, LPARAM lParam)
{
switch (message)
{
case PSCB_PRECREATE:
{
_AFX_THREAD_STATE* pState = AfxGetThreadState();
LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
if (lpTemplate->style != pState->m_dwPropStyle ||
lpTemplate->dwExtendedStyle != pState->m_dwPropExStyle)
{
// Mark the dialog template as read-write.
DWORD dwOldProtect;
VirtualProtect(lpTemplate, sizeof(DLGTEMPLATE), PAGE_READWRITE, &dwOldProtect);
// Ensure DS_SETFONT is set correctly.
lpTemplate->style = lpTemplate->style & DS_SETFONT ?
pState->m_dwPropStyle | DS_SETFONT :
pState->m_dwPropStyle & ~DS_SETFONT;
lpTemplate->dwExtendedStyle = pState->m_dwPropExStyle;
return TRUE;
}
return FALSE;
}
}
return 0;
}
BOOL CPropertySheet::Create(CWnd* pParentWnd, DWORD dwStyle, DWORD dwExStyle)
{
_AFX_THREAD_STATE* pState = AfxGetThreadState();
// Calculate the default window style.
if (dwStyle == (DWORD)-1)
{
pState->m_dwPropStyle = DS_MODALFRAME | DS_3DLOOK | DS_CONTEXTHELP |
DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION;
// Wizards don't have WS_SYSMENU.
if (!IsWizard())
pState->m_dwPropStyle |= WS_SYSMENU;
}
else
{
pState->m_dwPropStyle = dwStyle;
}
pState->m_dwPropExStyle = dwExStyle;
ASSERT_VALID(this);
ASSERT(m_hWnd == NULL);
VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
// finish building PROPSHEETHEADER structure
AFX_OLDPROPSHEETHEADER* psh = GetPropSheetHeader();
BuildPropPageArray();
m_bModeless = TRUE;
psh->dwFlags |= (PSH_MODELESS|PSH_USECALLBACK);
psh->pfnCallback = AfxPropSheetCallback;
psh->hwndParent = pParentWnd->GetSafeHwnd();
// hook the window creation process
AfxHookWindowCreate(this);
HWND hWnd = (HWND)PropertySheet((PROPSHEETHEADER*)psh);
#ifdef _DEBUG
DWORD dwError = ::GetLastError();
#endif
// cleanup on failure, otherwise return TRUE
if (!AfxUnhookWindowCreate())
PostNcDestroy(); // cleanup if Create fails
if (hWnd == NULL || hWnd == (HWND)-1)
{
TRACE1("PropertySheet() failed: GetLastError returned %d\n", dwError);
return FALSE;
}
ASSERT(hWnd == m_hWnd);
return TRUE;
}
void CPropertySheet::BuildPropPageArray()
{
// delete existing prop page array
delete[] (PROPSHEETPAGE*)m_psh.ppsp;
m_psh.ppsp = NULL;
// build new prop page array
AFX_OLDPROPSHEETPAGE* ppsp = new AFX_OLDPROPSHEETPAGE[m_pages.GetSize()];
m_psh.ppsp = (LPPROPSHEETPAGE)ppsp;
BOOL bWizard = (m_psh.dwFlags & (PSH_WIZARD | PSH_WIZARD97));
for (int i = 0; i < m_pages.GetSize(); i++)
{
CPropertyPage* pPage = GetPage(i);
memcpy(&ppsp[i], &pPage->m_psp, sizeof(pPage->m_psp));
pPage->PreProcessPageTemplate((PROPSHEETPAGE&)ppsp[i], bWizard);
}
m_psh.nPages = m_pages.GetSize();
}
////////////////////////////////////////////////////////////////////////////
int CPropertySheet::GetPageCount() const
{
ASSERT_VALID(this);
if (m_hWnd == NULL)
return m_pages.GetSize();
CTabCtrl* pTab = GetTabControl();
ASSERT_VALID(pTab);
return pTab->GetItemCount();
}
int CPropertySheet::GetActiveIndex() const
{
if (m_hWnd == NULL)
return ((CPropertySheet*)this)->GetPropSheetHeader()->nStartPage;
CTabCtrl* pTab = GetTabControl();
ASSERT_VALID(pTab);
return pTab->GetCurSel();
}
BOOL CPropertySheet::SetActivePage(int nPage)
{
if (m_hWnd == NULL)
{
GetPropSheetHeader()->nStartPage = nPage;
return TRUE;
}
return (BOOL)SendMessage(PSM_SETCURSEL, nPage);
}
int CPropertySheet::GetPageIndex(CPropertyPage* pPage)
{
for (int i = 0; i < GetPageCount(); i++)
{
if (GetPage(i) == pPage)
return i;
}
return -1; // pPage not found
}
BOOL CPropertySheet::SetActivePage(CPropertyPage* pPage)
{
ASSERT_VALID(this);
ASSERT(pPage != NULL);
ASSERT_KINDOF(CPropertyPage, pPage);
int nPage = GetPageIndex(pPage);
ASSERT(pPage >= 0);
return SetActivePage(nPage);
}
void CPropertySheet::AddPage(CPropertyPage* pPage)
{
ASSERT_VALID(this);
ASSERT(pPage != NULL);
ASSERT_KINDOF(CPropertyPage, pPage);
ASSERT_VALID(pPage);
// add page to internal list
m_pages.Add(pPage);
// add page externally
if (m_hWnd != NULL)
{
// build new prop page array
AFX_OLDPROPSHEETPAGE *ppsp = new AFX_OLDPROPSHEETPAGE[m_pages.GetSize()];
memcpy(ppsp, m_psh.ppsp, sizeof(AFX_OLDPROPSHEETPAGE) * (m_pages.GetSize()-1));
delete[] (PROPSHEETPAGE*)m_psh.ppsp;
m_psh.ppsp = (PROPSHEETPAGE*)ppsp;
ppsp += m_pages.GetSize()-1;
// copy processed PROPSHEETPAGE struct to end
memcpy(ppsp, &pPage->m_psp, sizeof(pPage->m_psp));
pPage->PreProcessPageTemplate((PROPSHEETPAGE&)*ppsp, IsWizard());
HPROPSHEETPAGE hPSP = CreatePropertySheetPage((PROPSHEETPAGE*)ppsp);
if (hPSP == NULL)
AfxThrowMemoryException();
if (!SendMessage(PSM_ADDPAGE, 0, (LPARAM)hPSP))
{
DestroyPropertySheetPage(hPSP);
AfxThrowMemoryException();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -