📄 treepropsheet.cpp
字号:
// TreePropSheet.cpp : implementation file
//
#include "stdafx.h"
#include "TreePropSheet.h"
#include "PropPageFrame.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// class CTreePropSheet
BEGIN_MESSAGE_MAP(CTreePropSheet, CPropertySheet)
//{{AFX_MSG_MAP(CTreePropSheet)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
ON_MESSAGE(PSM_ADDPAGE, OnAddPage)
ON_MESSAGE(PSM_REMOVEPAGE, OnRemovePage)
ON_MESSAGE(PSM_SETCURSEL, OnSetCurSel)
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)
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CTreePropSheet, CPropertySheet)
const UINT CTreePropSheet::s_unPageTreeId = 0x7EEE;
CTreePropSheet::CTreePropSheet()
: CPropertySheet(),
m_bPageTreeSelChangedActive(FALSE),
m_bTreeViewMode(TRUE),
m_bPageCaption(FALSE),
m_bTreeImages(FALSE),
m_nPageTreeWidth(120),
m_pwndPageTree(NULL),
m_pFrame(NULL)
{}
CTreePropSheet::CTreePropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
: CPropertySheet(nIDCaption, pParentWnd, iSelectPage),
m_bPageTreeSelChangedActive(FALSE),
m_bTreeViewMode(TRUE),
m_bPageCaption(FALSE),
m_bTreeImages(FALSE),
m_nPageTreeWidth(120),
m_pwndPageTree(NULL),
m_pFrame(NULL)
{
}
CTreePropSheet::CTreePropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
: CPropertySheet(pszCaption, pParentWnd, iSelectPage),
m_bPageTreeSelChangedActive(FALSE),
m_bTreeViewMode(TRUE),
m_bPageCaption(FALSE),
m_bTreeImages(FALSE),
m_nPageTreeWidth(120),
m_pwndPageTree(NULL),
m_pFrame(NULL)
{
}
CTreePropSheet::~CTreePropSheet()
{
}
/////////////////////////////////////////////////////////////////////
// Operationen
BOOL CTreePropSheet::SetTreeViewMode(BOOL bTreeViewMode /* = TRUE */, BOOL bPageCaption /* = FALSE */, BOOL bTreeImages /* = FALSE */)
{
if (IsWindow(m_hWnd))
{
//需要在窗口创建之前调用
ASSERT(FALSE);
return FALSE;
}
m_bTreeViewMode = bTreeViewMode;
if (m_bTreeViewMode)
{
m_bPageCaption = bPageCaption;
m_bTreeImages = bTreeImages;
}
return TRUE;
}
BOOL CTreePropSheet::SetTreeWidth(int nWidth)
{
if (IsWindow(m_hWnd))
{
//需要在窗口创建之前调用
ASSERT(FALSE);
return FALSE;
}
m_nPageTreeWidth = nWidth;
return TRUE;
}
void CTreePropSheet::SetEmptyPageText(LPCTSTR lpszEmptyPageText)
{
m_strEmptyPageMessage = lpszEmptyPageText;
}
DWORD CTreePropSheet::SetEmptyPageTextFormat(DWORD dwFormat)
{
DWORD dwPrevFormat = m_pFrame->GetMsgFormat();
m_pFrame->SetMsgFormat(dwFormat);
return dwPrevFormat;
}
BOOL CTreePropSheet::SetTreeDefaultImages(CImageList *pImages)
{
if (pImages->GetImageCount() != 8)
{
ASSERT(FALSE);
return FALSE;
}
if (m_DefaultImages.GetSafeHandle())
m_DefaultImages.DeleteImageList();
m_DefaultImages.Create(pImages);
//如果需要的话则更新
if (IsWindow(m_hWnd))
RefillPageTree();
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// public helpers
BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, HICON hIcon)
{
pPage->m_psp.dwFlags|= PSP_USEHICON;
pPage->m_psp.hIcon = hIcon;
return TRUE;
}
BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, CImageList &Images, int nImage)
{
HICON hIcon = Images.ExtractIcon(nImage);
if (!hIcon)
return FALSE;
return SetPageIcon(pPage, hIcon);
}
BOOL CTreePropSheet::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 CTreePropSheet::GenerateEmptyPageMessage(LPCTSTR lpszEmptyPageMessage, LPCTSTR lpszCaption)
{
CString strMsg;
strMsg.Format(lpszEmptyPageMessage, lpszCaption);
return strMsg;
}
CTreeCtrl* CTreePropSheet::CreatePageTreeObject()
{
return new CTreeCtrl;
}
CPropPageFrame* CTreePropSheet::CreatePageFrame()
{
return new CPropPageFrame;
}
/////////////////////////////////////////////////////////////////////
// Implementation helpers
void CTreePropSheet::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 CTreePropSheet::RefillPageTree()
{
if (!IsWindow(m_hWnd))
return;
m_pwndPageTree->DeleteAllItems();
CTabCtrl *pTabCtrl = GetTabControl();
if (!IsWindow(pTabCtrl->GetSafeHwnd()))
{
ASSERT(FALSE);
return;
}
const int nPageCount = pTabCtrl->GetItemCount();
//重建图像列表
if (m_bTreeImages)
{
for (int i = m_Images.GetImageCount()-1; i >= 0; --i)
m_Images.Remove(i);
//添加页图像
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);
}
}
// 添加缺省的图像
if (m_DefaultImages.GetSafeHandle())
{
HICON hIcon;
// 添加缺省的图像
hIcon = m_DefaultImages.ExtractIcon(0);
if (hIcon)
{
m_Images.Add(hIcon);
DestroyIcon(hIcon);
}
hIcon = m_DefaultImages.ExtractIcon(1);
{
m_Images.Add(hIcon);
DestroyIcon(hIcon);
}
}
}
//插入树项
for (int nPage = 0; nPage < nPageCount; ++nPage)
{
//获取页的标题和图像
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();
//为页中的树插入项
HTREEITEM hItem = CreatePageTreeItem(ti.pszText);
ASSERT(hItem);
if (hItem)
{
m_pwndPageTree->SetItemData(hItem, nPage);
//设置图像
if (m_bTreeImages)
{
int nImage = ti.iImage;
if (nImage < 0 || nImage >= m_Images.GetImageCount())
nImage = m_DefaultImages.GetSafeHandle()? m_Images.GetImageCount()-1 : -1;
m_pwndPageTree->SetItemImage(hItem, nImage, nImage);
}
}
}
}
HTREEITEM CTreePropSheet::CreatePageTreeItem(LPCTSTR lpszPath, HTREEITEM hParent /* = TVI_ROOT */)
{
CString strPath(lpszPath);
CString strTopMostItem(SplitPageTreePath(strPath));
//检查给定文本的项是否已经存在
HTREEITEM hItem = NULL;
HTREEITEM hChild = m_pwndPageTree->GetChildItem(hParent);
while (hChild)
{
if (m_pwndPageTree->GetItemText(hChild) == strTopMostItem)
{
hItem = hChild;
break;
}
hChild = m_pwndPageTree->GetNextItem(hChild, TVGN_NEXT);
}
//如果不存在则创建一个
if (!hItem)
{
hItem = m_pwndPageTree->InsertItem(strTopMostItem, hParent);
m_pwndPageTree->SetItemData(hItem, -1);
if (!strPath.IsEmpty() && m_bTreeImages && m_DefaultImages.GetSafeHandle())
//设置图像
m_pwndPageTree->SetItemImage(hItem, m_Images.GetImageCount()-2, m_Images.GetImageCount()-2);
}
if (!hItem)
{
ASSERT(FALSE);
return NULL;
}
if (strPath.IsEmpty())
return hItem;
else
return CreatePageTreeItem(strPath, hItem);
}
CString CTreePropSheet::SplitPageTreePath(CString &strRest)
{
int nSeperatorPos = 0;
while (TRUE)
{
nSeperatorPos = strRest.Find(_T("::"), nSeperatorPos);
if (nSeperatorPos == -1)
{
CString strItem(strRest);
strRest.Empty();
return strItem;
}
else if (nSeperatorPos>0)
{
// if there is an odd number of backslashes infront of the
// seperator, than do not interpret it as separator
//如果在分隔符前有奇数数目的反斜杠,则不将它解释为分隔符
int nBackslashCount = 0;
for (int nPos = nSeperatorPos-1; nPos >= 0 && strRest[nPos]==_T('\\'); --nPos, ++nBackslashCount);
if (nBackslashCount%2 == 0)
break;
else
++nSeperatorPos;
}
}
CString strItem(strRest.Left(nSeperatorPos));
strItem.Replace(_T("\\::"), _T("::"));
strItem.Replace(_T("\\\\"), _T("\\"));
strRest = strRest.Mid(nSeperatorPos+2);
return strItem;
}
BOOL CTreePropSheet::KillActiveCurrentPage()
{
HWND hCurrentPage = PropSheet_GetCurrentPageHwnd(m_hWnd);
if (!IsWindow(hCurrentPage))
{
ASSERT(FALSE);
return TRUE;
}
//检测当前页是否为活动页
if (!::IsWindowVisible(hCurrentPage))
return TRUE;
//试图杀死当前页
PSHNOTIFY pshn;
pshn.hdr.code = PSN_KILLACTIVE;
pshn.hdr.hwndFrom = m_hWnd;
pshn.hdr.idFrom = GetDlgCtrlID();
pshn.lParam = 0;
if (::SendMessage(hCurrentPage, WM_NOTIFY, pshn.hdr.idFrom, (LPARAM)&pshn))
//当前页不允许改变
return FALSE;
//隐藏该页
::ShowWindow(hCurrentPage,SW_HIDE);
return TRUE;
}
HTREEITEM CTreePropSheet::GetPageTreeItem(int nPage, HTREEITEM hRoot /* = TVI_ROOT */)
{
//对于根项则进行特殊的处理
if (hRoot == TVI_ROOT)
hRoot = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
//检查参数的有效性
if (nPage < 0 || nPage >= GetPageCount())
{
ASSERT(FALSE);
return NULL;
}
if (hRoot == NULL)
{
ASSERT(FALSE);
return NULL;
}
//完成简单的线性搜索
HTREEITEM hItem = hRoot;
while (hItem)
{
if ((signed)m_pwndPageTree->GetItemData(hItem) == nPage)
return hItem;
if (m_pwndPageTree->ItemHasChildren(hItem))
{
HTREEITEM hResult = GetPageTreeItem(nPage, m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD));
if (hResult)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -