📄 treepropsheetbase.cpp
字号:
// TreePropSheetBase.cpp
//
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 by Yves Tkaczyk
// (http://www.tkaczyk.net - yves@tkaczyk.net)
//
// The contents of this file are subject to the Artistic License (the "License").
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
// http://www.opensource.org/licenses/artistic-license.html
//
// This code is an update of CTreePropSheet written by Sven Wiegand and published
// on code project at http://www.codetools.com/property/treepropsheet.asp.
//
// /********************************************************************
// *
// * Copyright (c) 2002 Sven Wiegand <forum@sven-wiegand.de>
// *
// * You can use this and modify this in any way you want,
// * BUT LEAVE THIS HEADER INTACT.
// *
// * Redistribution is appreciated.
// *
// * $Workfile:$
// * $Revision: 1.4 $
// * $Modtime:$
// * $Author: ytkaczyk $
// *
// * Revision History:
// * $History:$
// *
// *********************************************************************/
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TreePropSheetBase.h"
#include "PropPageFrameEx.h"
#include "TreePropSheetTreeCtrl.h"
#include "HighColorTab.hpp"
#include "TreePropSheetUtil.hpp"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
namespace TreePropSheet
{
const DWORD kNoPageAssociated = 0xFFFFFFFF; //! Value for tree item data when no page is associated in the tree.
//-------------------------------------------------------------------
// class CTreePropSheetBase
//-------------------------------------------------------------------
BEGIN_MESSAGE_MAP(CTreePropSheetBase, CPropertySheet)
//{{AFX_MSG_MAP(CTreePropSheetBase)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(PSM_ADDPAGE, OnAddPage)
ON_MESSAGE(PSM_REMOVEPAGE, OnRemovePage)
ON_MESSAGE(PSM_SETCURSEL, OnSetCurSel)
ON_MESSAGE(PSM_SETCURSELID, OnSetCurSelId)
ON_MESSAGE(PSM_ISDIALOGMESSAGE, OnIsDialogMessage)
ON_NOTIFY(TVN_SELCHANGINGA, s_unPageTreeId, OnPageTreeSelChanging)
ON_NOTIFY(TVN_SELCHANGINGW, s_unPageTreeId, OnPageTreeSelChanging)
ON_NOTIFY(TVN_SELCHANGEDA, s_unPageTreeId, OnPageTreeSelChanged)
ON_NOTIFY(TVN_SELCHANGEDW, s_unPageTreeId, OnPageTreeSelChanged)
ON_REGISTERED_MESSAGE(WMU_ENABLEPAGE, OnEnablePage)
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CTreePropSheetBase, CPropertySheet)
const UINT CTreePropSheetBase::s_unPageTreeId = 0x7EEE;
CTreePropSheetBase::CTreePropSheetBase()
: CPropertySheet()
{
Init();
}
CTreePropSheetBase::CTreePropSheetBase(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
: CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
Init();
}
CTreePropSheetBase::CTreePropSheetBase(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
: CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
Init();
}
CTreePropSheetBase::~CTreePropSheetBase()
{
if( m_Images.GetSafeHandle() )
m_Images.DeleteImageList();
//Fix for TN017
if( m_pwndPageTree )
delete m_pwndPageTree;
m_pwndPageTree = NULL;
if( m_pFrame )
delete m_pFrame;
m_pFrame = NULL;
}
/////////////////////////////////////////////////////////////////////
// Operations
/////////////////////////////////////////////////////////////////////
BOOL CTreePropSheetBase::SetTreeViewMode(BOOL bTreeViewMode /* = TRUE */, BOOL bPageCaption /* = FALSE */, BOOL bTreeImages /* = FALSE */)
{
if (IsWindow(m_hWnd))
{
// needs to be called, before the window has been created
ASSERT(FALSE);
return FALSE;
}
m_bTreeViewMode = bTreeViewMode;
if (m_bTreeViewMode)
{
m_bPageCaption = bPageCaption;
m_bTreeImages = bTreeImages;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SetTreeWidth(int nWidth)
{
if (IsWindow(m_hWnd))
{
// needs to be called, before the window is created.
ASSERT(FALSE);
return FALSE;
}
m_nPageTreeWidth = nWidth;
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::SetEmptyPageText(LPCTSTR lpszEmptyPageText)
{
m_strEmptyPageMessage = lpszEmptyPageText;
}
/////////////////////////////////////////////////////////////////////
//
DWORD CTreePropSheetBase::SetEmptyPageTextFormat(DWORD dwFormat)
{
DWORD dwPrevFormat = m_pFrame->GetMsgFormat();
m_pFrame->SetMsgFormat(dwFormat);
return dwPrevFormat;
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SetTreeDefaultImages(CImageList *pImages)
{
if (pImages->GetImageCount() != 2)
{
ASSERT(FALSE);
return FALSE;
}
if (m_DefaultImages.GetSafeHandle())
m_DefaultImages.DeleteImageList();
m_DefaultImages.Create(pImages);
// update, if necessary
if (IsWindow(m_hWnd))
RefillPageTree();
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SetTreeDefaultImages(UINT unBitmapID, int cx, COLORREF crMask)
{
if (m_DefaultImages.GetSafeHandle())
m_DefaultImages.DeleteImageList();
if (!m_DefaultImages.Create(unBitmapID, cx, 0, crMask))
return FALSE;
if (m_DefaultImages.GetImageCount() != 2)
{
m_DefaultImages.DeleteImageList();
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
CTreeCtrl* CTreePropSheetBase::GetPageTreeControl()
{
return m_pwndPageTree;
}
/////////////////////////////////////////////////////////////////////
//
CPropPageFrame* CTreePropSheetBase::GetFrameControl()
{
return m_bTreeViewMode?m_pFrame:NULL;
}
/////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::IsTreeViewMode() const
{
return m_bTreeViewMode?true:false;
}
/////////////////////////////////////////////////////////////////////
//
int CTreePropSheetBase::GetTreeWidth() const
{
if( m_pwndPageTree->GetSafeHwnd() )
{
CRect rectTree;
m_pwndPageTree->GetWindowRect( &rectTree );
return rectTree.Width();
}
else
{
return m_nPageTreeWidth;
}
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::SetAutoExpandTree(const bool bAutoExpandTree)
{
m_bAutoExpandTree = bAutoExpandTree;
}
/////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::IsAutoExpandTree() const
{
return m_bAutoExpandTree;
}
/////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::EnablePage(const CPropertyPage* const pPage,const bool bEnable)
{
/* - Based on flag value:
- If disabling, if the current page is the page that is being disabled,
activate the next page. If the new page is the initial
page, the call fails as there is no available new page. If the current
is not the page being disabled, just disable it. Act accordingly
and set flag, return previous status.
- If enabling, just switch the flag.
- Refresh tree. */
CPageInformation& pageInformation = m_mapPageInformation[pPage];
bool bPreviousStatus = pageInformation.IsEnabled();
if( bEnable )
{
pageInformation.SetIsEnabled( true );
}
else
{
// Active next page if disabling the current page.
if( GetActivePage() == pPage )
{
ActivateNextPage();
// This is the only active page left, it cannot be disabled.
if( GetActivePage() == pPage )
{
return bPreviousStatus;
}
}
// We are now sure that the active page is not the page being disabled,
// we can proceed.
pageInformation.SetIsEnabled( false );
}
// Enable/disable the page if it exists.
if( pPage->GetSafeHwnd() )
{
::EnableWindow( pPage->GetSafeHwnd(), bEnable?TRUE:FALSE );
}
// Refresh the tree control.
RefreshPageTree();
return bPreviousStatus;
}
/////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::IsPageEnabled(const CPropertyPage* const pPage) const
{
/* If the page is in the information map, return the status from the map
otherwise returns true (the page has never been disabled. Implementation
is such that querying the page status will not any unnecessary add entry
into the map.*/
tMapPageInformation::const_iterator citPage = m_mapPageInformation.find( pPage );
if( m_mapPageInformation.end() == citPage )
return true;
return citPage->second.IsEnabled();
}
/////////////////////////////////////////////////////////////////////
// public helpers
/////////////////////////////////////////////////////////////////////
BOOL CTreePropSheetBase::SetPageIcon(CPropertyPage *pPage, HICON hIcon)
{
pPage->m_psp.dwFlags|= PSP_USEHICON;
pPage->m_psp.hIcon = hIcon;
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SetPageIcon(CPropertyPage *pPage, UINT unIconId)
{
HICON hIcon = AfxGetApp()->LoadIcon(unIconId);
if (!hIcon)
return FALSE;
return SetPageIcon(pPage, hIcon);
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SetPageIcon(CPropertyPage *pPage, CImageList &Images, int nImage)
{
HICON hIcon = Images.ExtractIcon(nImage);
if (!hIcon)
return FALSE;
return SetPageIcon(pPage, hIcon);
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::DestroyPageIcon(CPropertyPage *pPage)
{
if (!pPage || !(pPage->m_psp.dwFlags&PSP_USEHICON) || !pPage->m_psp.hIcon)
return FALSE;
DestroyIcon(pPage->m_psp.hIcon);
pPage->m_psp.dwFlags&= ~PSP_USEHICON;
pPage->m_psp.hIcon = NULL;
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// Overridable implementation helpers
/////////////////////////////////////////////////////////////////////
CString CTreePropSheetBase::GenerateEmptyPageMessage(LPCTSTR lpszEmptyPageMessage, LPCTSTR lpszCaption)
{
CString strMsg;
strMsg.Format(lpszEmptyPageMessage, lpszCaption);
return strMsg;
}
/////////////////////////////////////////////////////////////////////
//
CTreeCtrl* CTreePropSheetBase::CreatePageTreeObject()
{
// Create the tree control.
return new CTreePropSheetTreeCtrl;
}
/////////////////////////////////////////////////////////////////////
//
CPropPageFrame* CTreePropSheetBase::CreatePageFrame()
{
return new CPropPageFrameEx;
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::RefreshTreeItem(HTREEITEM hItem)
{
ASSERT(hItem);
if (hItem)
{
DWORD dwItemData = m_pwndPageTree->GetItemData( hItem );
if( kNoPageAssociated != dwItemData )
{
// Set font if disabled.
CPropertyPage* pPage = GetPage( dwItemData );
ASSERT( pPage );
if( NULL != pPage )
{
// Set text color
::SendMessage( m_pwndPageTree->GetSafeHwnd(), WMU_ENABLETREEITEM, (WPARAM)hItem, (LPARAM)( IsPageEnabled( pPage ) ? m_pwndPageTree->GetTextColor():GetSysColor( COLOR_GRAYTEXT ) ) );
}
}
}
}
/////////////////////////////////////////////////////////////////////
// Implementation helpers
/////////////////////////////////////////////////////////////////////
void CTreePropSheetBase::MoveChildWindows(int nDx, int nDy)
{
CWnd *pWnd = GetWindow(GW_CHILD);
while (pWnd)
{
CRect rect;
pWnd->GetWindowRect(rect);
rect.OffsetRect(nDx, nDy);
ScreenToClient(rect);
pWnd->MoveWindow(rect);
pWnd = pWnd->GetNextWindow();
}
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::RefillPageTree()
{
if (!IsWindow(m_hWnd))
return;
// TreePropSheetEx: OnPageTreeSelChanging does not process message.
TreePropSheet::CIncrementScope RefillingPageTreeContentGuard( m_nRefillingPageTreeContent );
// TreePropSheetEx: End OnPageTreeSelChanging does not process message.
m_pwndPageTree->DeleteAllItems();
CTabCtrl *pTabCtrl = GetTabControl();
if (!IsWindow(pTabCtrl->GetSafeHwnd()))
{
ASSERT(FALSE);
return;
}
const int nPageCount = pTabCtrl->GetItemCount();
// rebuild image list
if (m_bTreeImages)
{
for (int i = m_Images.GetImageCount()-1; i >= 0; --i)
m_Images.Remove(i);
// add page images
CImageList *pPageImages = pTabCtrl->GetImageList();
if (pPageImages)
{
for (int nImage = 0; nImage < pPageImages->GetImageCount(); ++nImage)
{
HICON hIcon = pPageImages->ExtractIcon(nImage);
m_Images.Add(hIcon);
DestroyIcon(hIcon);
}
}
// add default images
if (m_DefaultImages.GetSafeHandle())
{
HICON hIcon;
// add default images
hIcon = m_DefaultImages.ExtractIcon(0);
if (hIcon)
{
m_Images.Add(hIcon);
DestroyIcon(hIcon);
}
hIcon = m_DefaultImages.ExtractIcon(1);
{
m_Images.Add(hIcon);
DestroyIcon(hIcon);
}
}
}
// insert tree items
for (int nPage = 0; nPage < nPageCount; ++nPage)
{
// Get title and image of the page
CString strPagePath;
TCITEM ti;
ZeroMemory(&ti, sizeof(ti));
ti.mask = TCIF_TEXT|TCIF_IMAGE;
ti.cchTextMax = MAX_PATH;
ti.pszText = strPagePath.GetBuffer(ti.cchTextMax);
ASSERT(ti.pszText);
if (!ti.pszText)
return;
pTabCtrl->GetItem(nPage, &ti);
strPagePath.ReleaseBuffer();
// Create an item in the tree for the page
HTREEITEM hItem = CreatePageTreeItem(ti.pszText);
ASSERT(hItem);
if (hItem)
{
m_pwndPageTree->SetItemData(hItem, nPage);
// set image
if (m_bTreeImages)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -