propertypagehost.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 403 行

CPP
403
字号
// PropertyPageHost.cpp : implementation file
//

#include "stdafx.h"
#include "PropertyPageHost.h"
#include "dialoghelper.h"

#if _MSC_VER > 1200
#	include <afxocc.h>
#else
#	include <..\src\occimpl.h>
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPropertyPageHost

CPropertyPageHost::CPropertyPageHost() : m_nSelIndex(-1)
{
}

CPropertyPageHost::~CPropertyPageHost()
{
}


BEGIN_MESSAGE_MAP(CPropertyPageHost, CWnd)
	//{{AFX_MSG_MAP(CPropertyPageHost)
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
	ON_MESSAGE(PSM_GETCURRENTPAGEHWND, OnGetCurrentPageHwnd)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CPropertyPageHost message handlers

BOOL CPropertyPageHost::Create(UINT nRefCtrlID, CWnd* pParent, UINT uCtrlID)
{
	ASSERT_VALID(pParent);

	if (!pParent || !::IsWindow(*pParent))
		return FALSE;

	CWnd* pRefCtrl = pParent->GetDlgItem(nRefCtrlID);

	ASSERT_VALID(pRefCtrl);

	if (!pRefCtrl || !::IsWindow(*pRefCtrl))
		return FALSE;

	CRect rHost;
	pRefCtrl->GetWindowRect(rHost);
	pParent->ScreenToClient(rHost);

	if (Create(rHost, pParent, uCtrlID))
	{
		// move us after nRefCtrlID in the z-order
		SetWindowPos(pRefCtrl, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
		return TRUE;
	}

	return FALSE;
}

BOOL CPropertyPageHost::Create(LPRECT lpRect, CWnd* pParent, UINT uCtrlID)
{
	ASSERT_VALID(pParent);

	if (!pParent || !::IsWindow(*pParent))
		return FALSE;

	if (!m_aPages.GetSize())
		return FALSE;

	if (!CWnd::Create(NULL, NULL, WS_CHILD | WS_VISIBLE, *lpRect, pParent, uCtrlID))
		return FALSE;

	// create the first page
	return SetActivePage(0);
}

int CPropertyPageHost::GetActiveIndex() const
{
	return m_nSelIndex;
}

CPropertyPage* CPropertyPageHost::GetActivePage()
{
	if (m_nSelIndex < 0)
		return NULL;

	CPropertyPage* pPage = m_aPages[m_nSelIndex].pPage;

	if (!pPage || !pPage->GetSafeHwnd())
		return NULL;

	return pPage;
}

BOOL CPropertyPageHost::IsPageCreated(int nIndex) const
{
	const CPropertyPage* pPage = GetPage(nIndex);

	return (pPage && pPage->GetSafeHwnd());
}

LRESULT CPropertyPageHost::OnGetCurrentPageHwnd(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
	CWnd* pActive = GetActivePage();

	return pActive ? (LRESULT)pActive->GetSafeHwnd() : NULL;
}

BOOL CPropertyPageHost::SetActivePage(int nIndex, BOOL bAndFocus)
{
	if (nIndex < 0 || nIndex >= m_aPages.GetSize())
		return FALSE;

	CPropertyPage* pPage = m_aPages[nIndex].pPage;

	if (!pPage)
		return FALSE;

	CWnd* pFocus = GetFocus();
	BOOL bNeedCreate = (pPage->GetSafeHwnd() == NULL);

	if (bNeedCreate) // first time only
	{
		if (!pPage->Create(pPage->m_psp.pszTemplate, this))
			return FALSE;

		// make sure we can into/out of the page
		pPage->ModifyStyleEx(0, WS_EX_CONTROLPARENT | DS_CONTROL);

		// make sure the page is a child and modify it if necessary
		pPage->ModifyStyle(WS_POPUPWINDOW | WS_OVERLAPPEDWINDOW, 0);

		if (!(pPage->GetStyle() & WS_CHILD))
		{
			pPage->ModifyStyle(0, WS_CHILD);
			pPage->SetParent(this);
			ASSERT (pPage->GetParent() == this);
		}

		// set font to our parent's font
		CWnd* pOurParent = GetParent();
		ASSERT (pOurParent);

		CFont* pFont = pOurParent->GetFont();

		if (pFont)
			CDialogHelper::SetFont(pPage, (HFONT)pFont->GetSafeHandle(), FALSE);

		CRect rClient;
		GetClientRect(rClient);

		pPage->SetParent(this);
		pPage->MoveWindow(rClient);
	}

	// hide the current page provided it's not just about to be reshown
	BOOL bSamePage = (m_nSelIndex == nIndex);

	if (!bSamePage)
	{
		if (m_nSelIndex != -1)
		{
			CPropertyPage* pCurPage = GetActivePage();
			ASSERT (pCurPage);

			if (pCurPage)
			{
				pCurPage->ShowWindow(SW_HIDE);
				pCurPage->OnKillActive();
			}
		}

		pPage->OnSetActive();
		pPage->ShowWindow(SW_SHOW);

		// move the focus to the first dlg ctrl
		if (bAndFocus)
		{
			CWnd* pCtrl = pPage->GetNextDlgTabItem(NULL);

			if (pCtrl)
				pCtrl->SetFocus();
		}
		else
			pFocus->SetFocus();

		m_nSelIndex = nIndex;
	}

	return TRUE;
}

BOOL CPropertyPageHost::SetActivePage(CPropertyPage* pPage, BOOL /*bAndFocus*/)
{
	return SetActivePage(FindPage(pPage));
}

BOOL CPropertyPageHost::AddPage(CPropertyPage* pPage, LPCTSTR szTitle, DWORD dwItemData)
{
	if (!pPage || !pPage->IsKindOf(RUNTIME_CLASS(CPropertyPage)))
		return FALSE;

	if (FindPage(pPage) == -1)
	{
		PAGEITEM pi(pPage, szTitle, dwItemData);
		int nPage = m_aPages.Add(pi);

		if (szTitle)
		{
			pPage->m_psp.pszTitle = m_aPages[nPage].sTitle; // the final string address
			pPage->m_psp.dwFlags |= PSP_USETITLE;
		}
	}

	return TRUE;
}

int CPropertyPageHost::FindPage(CPropertyPage* pPage)
{
	int nPage = m_aPages.GetSize();

	while (nPage--)
	{
		if (m_aPages[nPage].pPage == pPage)
			break;
	}

	return nPage;
}

BOOL CPropertyPageHost::PreTranslateMessage(MSG* pMsg) 
{
	CWnd* pActive = GetActivePage();

	if (pActive)
	{
		if (pActive->PreTranslateMessage(pMsg))
			return TRUE;
		
		else if (pActive->IsDialogMessage(pMsg)) 
			return TRUE;
	}
	
	return FALSE;
}

// unfortunately there is a bug in MFC that can cause an infinite loop
// when the property page is hosting an OLE control so we fix
// it by providing a replacement to the buggy code
BOOL COccManager::IsDialogMessage(CWnd* pWndDlg, LPMSG lpMsg)
{
	CWnd* pWndFocus = CWnd::GetFocus();
//	HWND hWndFocus = pWndFocus->GetSafeHwnd();
//	HWND hWndDlg = pWndDlg->GetSafeHwnd();
	UINT uMsg = lpMsg->message;

	if (((uMsg >= WM_KEYFIRST) && (uMsg <= WM_KEYLAST)) ||
		((uMsg >= WM_MOUSEFIRST) && (uMsg <= WM_MOUSELAST)))
	{
		CWnd* pWndCtrl = pWndFocus;

		// Walk up the parent chain, until we find an OLE control.
		while ((pWndCtrl != NULL) && (pWndCtrl->m_pCtrlSite == NULL) &&
			(pWndCtrl->GetParent() != pWndDlg))
		{
			pWndCtrl = pWndCtrl->GetParent();
		}

		// let the control attempt to translate the message
		if (pWndCtrl != NULL && pWndCtrl->m_pCtrlSite != NULL &&
			pWndCtrl->m_pCtrlSite->m_pActiveObject != NULL &&
			pWndCtrl->m_pCtrlSite->m_pActiveObject->TranslateAccelerator(lpMsg) == S_OK)
		{
			return TRUE;
		}

		// handle CTRLINFO_EATS_RETURN and CTRLINFO_EATS_ESCAPE flags
		if ((uMsg == WM_KEYUP || uMsg == WM_KEYDOWN || uMsg == WM_CHAR) &&
			pWndCtrl != NULL && pWndCtrl->m_pCtrlSite != NULL &&
			((LOWORD(lpMsg->wParam) == VK_RETURN &&
			 (pWndCtrl->m_pCtrlSite->m_ctlInfo.dwFlags & CTRLINFO_EATS_RETURN)) ||
			(LOWORD(lpMsg->wParam) == VK_ESCAPE &&
			 (pWndCtrl->m_pCtrlSite->m_ctlInfo.dwFlags & CTRLINFO_EATS_ESCAPE))))
		{
			return FALSE;
		}
	}

	// else simple default
	// because this is where the MFC bug existed
	return ::IsDialogMessage(pWndDlg->GetSafeHwnd(), lpMsg);
}

void CPropertyPageHost::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);
	
	// resize active page
	if (m_nSelIndex != -1)
	{
		CPropertyPage* pPage = GetActivePage();
		ASSERT (pPage);

		if (pPage)
			pPage->MoveWindow(0, 0, cx, cy, TRUE);
	}
}

BOOL CPropertyPageHost::OnEraseBkgnd(CDC* /*pDC*/) 
{
	return TRUE;
}

void CPropertyPageHost::OnOK()
{
	int nPage = m_aPages.GetSize();

	while (nPage--)
	{
		CPropertyPage* pPage = m_aPages[nPage].pPage;

		if (pPage && pPage->GetSafeHwnd())
		{
			pPage->UpdateData();
			pPage->OnOK();
		}
	}
}

int CPropertyPageHost::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// *************************************************************************
	// EXTREMELY IMPORTANT
	// set these styles because otherwise propsheet
	// goes into infinite loop when focus changes
	ModifyStyle(0, DS_CONTROL, 0);
	ModifyStyleEx(0, WS_EX_CONTROLPARENT);
	// *************************************************************************
	
	return 0;
}

CString CPropertyPageHost::GetPageTitle(int nIndex) const
{
	if (nIndex < 0 || nIndex > m_aPages.GetSize())
		return "";

	return m_aPages[nIndex].sTitle;
}

DWORD CPropertyPageHost::GetPageItemData(int nIndex) const
{
	if (nIndex < 0 || nIndex > m_aPages.GetSize())
		return 0;

	return m_aPages[nIndex].dwItemData;
}

CPropertyPage* CPropertyPageHost::GetPage(int nIndex)
{
	if (nIndex < 0 || nIndex > m_aPages.GetSize())
		return NULL;

	return m_aPages[nIndex].pPage;
}

const CPropertyPage* CPropertyPageHost::GetPage(int nIndex) const
{
	if (nIndex < 0 || nIndex > m_aPages.GetSize())
		return NULL;

	return m_aPages[nIndex].pPage;
}

CPropertyPage* CPropertyPageHost::FindPage(DWORD dwItemData)
{
	int nPage = m_aPages.GetSize();

	while (nPage--)
	{
		if (dwItemData && dwItemData == m_aPages[nPage].dwItemData)
			return m_aPages[nPage].pPage;
	}

	return NULL;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?