📄 treepropsheet.cpp
字号:
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)
return hResult;
}
hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
}
// we've found nothing, if we arrive here
return hItem;
}
BOOL CTreePropSheet::SelectPageTreeItem(int nPage)
{
HTREEITEM hItem = GetPageTreeItem(nPage);
if (!hItem)
return FALSE;
return m_pwndPageTree->SelectItem(hItem);
}
BOOL CTreePropSheet::SelectCurrentPageTreeItem()
{
CTabCtrl *pTab = GetTabControl();
if (!IsWindow(pTab->GetSafeHwnd()))
return FALSE;
return SelectPageTreeItem(pTab->GetCurSel());
}
void CTreePropSheet::UpdateCaption()
{
HWND hPage = PropSheet_GetCurrentPageHwnd(GetSafeHwnd());
BOOL bRealPage = IsWindow(hPage) && ::IsWindowVisible(hPage);
HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
if (!hItem)
return;
CString strCaption = m_pwndPageTree->GetItemText(hItem);
// if empty page, then update empty page message
if (!bRealPage)
m_pFrame->SetMsgText(GenerateEmptyPageMessage(m_strEmptyPageMessage, strCaption));
// if no captions are displayed, cancel here
if (!m_pFrame->GetShowCaption())
return;
// get tab control, to the the images from
CTabCtrl *pTabCtrl = GetTabControl();
if (!IsWindow(pTabCtrl->GetSafeHwnd()))
{
ASSERT(FALSE);
return;
}
if (m_bTreeImages)
{
// get image from tree
int nImage;
m_pwndPageTree->GetItemImage(hItem, nImage, nImage);
HICON hIcon = m_Images.ExtractIcon(nImage);
m_pFrame->SetCaption(strCaption, hIcon);
if (hIcon)
DestroyIcon(hIcon);
}
else if (bRealPage)
{
// get image from hidden (original) tab provided by the original
// implementation
CImageList *pImages = pTabCtrl->GetImageList();
if (pImages)
{
TCITEM ti;
ZeroMemory(&ti, sizeof(ti));
ti.mask = TCIF_IMAGE;
HICON hIcon = NULL;
if (pTabCtrl->GetItem((int)m_pwndPageTree->GetItemData(hItem), &ti))
hIcon = pImages->ExtractIcon(ti.iImage);
m_pFrame->SetCaption(strCaption, hIcon);
if (hIcon)
DestroyIcon(hIcon);
}
else
m_pFrame->SetCaption(strCaption);
}
else
m_pFrame->SetCaption(strCaption);
}
void CTreePropSheet::ActivatePreviousPage()
{
if (!IsWindow(m_hWnd))
return;
if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
{
// normal tab property sheet. Simply use page index
int nPageIndex = GetActiveIndex();
if (nPageIndex<0 || nPageIndex>=GetPageCount())
return;
int nPrevIndex = (nPageIndex==0)? GetPageCount()-1 : nPageIndex-1;
SetActivePage(nPrevIndex);
}
else
{
// property sheet with page tree.
// we need a more sophisticated handling here, than simply using
// the page index, because we won't skip empty pages.
// so we have to walk the page tree
HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
ASSERT(hItem);
if (!hItem)
return;
HTREEITEM hPrevItem = NULL;
if (hPrevItem=m_pwndPageTree->GetPrevSiblingItem(hItem))
{
while (m_pwndPageTree->ItemHasChildren(hPrevItem))
{
hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
}
}
else
hPrevItem=m_pwndPageTree->GetParentItem(hItem);
if (!hPrevItem)
{
// no prev item, so cycle to the last item
hPrevItem = m_pwndPageTree->GetRootItem();
while (TRUE)
{
while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
if (m_pwndPageTree->ItemHasChildren(hPrevItem))
hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
else
break;
}
}
if (hPrevItem)
m_pwndPageTree->SelectItem(hPrevItem);
}
}
void CTreePropSheet::ActivateNextPage()
{
if (!IsWindow(m_hWnd))
return;
if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
{
// normal tab property sheet. Simply use page index
int nPageIndex = GetActiveIndex();
if (nPageIndex<0 || nPageIndex>=GetPageCount())
return;
int nNextIndex = (nPageIndex==GetPageCount()-1)? 0 : nPageIndex+1;
SetActivePage(nNextIndex);
}
else
{
// property sheet with page tree.
// we need a more sophisticated handling here, than simply using
// the page index, because we won't skip empty pages.
// so we have to walk the page tree
HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
ASSERT(hItem);
if (!hItem)
return;
HTREEITEM hNextItem = NULL;
if (hNextItem=m_pwndPageTree->GetChildItem(hItem))
;
else if (hNextItem=m_pwndPageTree->GetNextSiblingItem(hItem))
;
else if (m_pwndPageTree->GetParentItem(hItem))
{
while (!hNextItem)
{
hItem = m_pwndPageTree->GetParentItem(hItem);
if (!hItem)
break;
hNextItem = m_pwndPageTree->GetNextSiblingItem(hItem);
}
}
if (!hNextItem)
// no next item -- so cycle to the first item
hNextItem = m_pwndPageTree->GetRootItem();
if (hNextItem)
m_pwndPageTree->SelectItem(hNextItem);
}
}
/////////////////////////////////////////////////////////////////////
// Overridings
BOOL CTreePropSheet::OnInitDialog()
{
if (m_bTreeViewMode)
{
// be sure, there are no stacked tabs, because otherwise the
// page caption will be to large in tree view mode
EnableStackedTabs(FALSE);
// Initialize image list.
if (m_DefaultImages.GetSafeHandle())
{
IMAGEINFO ii;
m_DefaultImages.GetImageInfo(0, &ii);
if (ii.hbmImage) DeleteObject(ii.hbmImage);
if (ii.hbmMask) DeleteObject(ii.hbmMask);
m_Images.Create(ii.rcImage.right-ii.rcImage.left, ii.rcImage.bottom-ii.rcImage.top, theApp.m_iDfltImageListColorFlags|ILC_MASK, 0, 1);
}
else
m_Images.Create(16, 16, theApp.m_iDfltImageListColorFlags|ILC_MASK, 0, 1);
}
// perform default implementation
BOOL bResult = CPropertySheet::OnInitDialog();
if (!m_bTreeViewMode)
// stop here, if we would like to use tabs
return bResult;
// Get tab control...
CTabCtrl *pTab = GetTabControl();
if (!IsWindow(pTab->GetSafeHwnd()))
{
ASSERT(FALSE);
return bResult;
}
HighColorTab::UpdateImageList(*this);
// ... and hide it
pTab->ShowWindow(SW_HIDE);
pTab->EnableWindow(FALSE);
// Place another (empty) tab ctrl, to get a frame instead
CRect rectFrame;
pTab->GetWindowRect(rectFrame);
ScreenToClient(rectFrame);
m_pFrame = CreatePageFrame();
if (!m_pFrame)
{
ASSERT(FALSE);
AfxThrowMemoryException();
}
m_pFrame->Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0xFFFF);
m_pFrame->ShowCaption(m_bPageCaption);
// Lets make place for the tree ctrl
const int nTreeWidth = m_nPageTreeWidth;
const int nTreeSpace = 5;
CRect rectSheet;
GetWindowRect(rectSheet);
rectSheet.right+= nTreeWidth;
SetWindowPos(NULL, -1, -1, rectSheet.Width(), rectSheet.Height(), SWP_NOZORDER|SWP_NOMOVE);
CenterWindow();
MoveChildWindows(nTreeWidth, 0);
// Lets calculate the rectangle for the tree ctrl
CRect rectTree(rectFrame);
rectTree.right = rectTree.left + nTreeWidth - nTreeSpace;
// calculate caption height
CTabCtrl wndTabCtrl;
wndTabCtrl.Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0x1234);
wndTabCtrl.InsertItem(0, _T(""));
CRect rectFrameCaption;
wndTabCtrl.GetItemRect(0, rectFrameCaption);
wndTabCtrl.DestroyWindow();
m_pFrame->SetCaptionHeight(rectFrameCaption.Height());
// if no caption should be displayed, make the window smaller in
// height
if (!m_bPageCaption)
{
// make frame smaller
m_pFrame->GetWnd()->GetWindowRect(rectFrame);
ScreenToClient(rectFrame);
rectFrame.top+= rectFrameCaption.Height();
m_pFrame->GetWnd()->MoveWindow(rectFrame);
// move all child windows up
MoveChildWindows(0, -rectFrameCaption.Height());
// modify rectangle for the tree ctrl
rectTree.bottom-= rectFrameCaption.Height();
// make us smaller
CRect rect;
GetWindowRect(rect);
rect.top+= rectFrameCaption.Height()/2;
rect.bottom-= rectFrameCaption.Height()-rectFrameCaption.Height()/2;
if (GetParent())
GetParent()->ScreenToClient(rect);
MoveWindow(rect);
}
// finally create tht tree control
const DWORD dwTreeStyle = TVS_SHOWSELALWAYS/*|TVS_TRACKSELECT*/|TVS_HASLINES/*|TVS_LINESATROOT*/|TVS_HASBUTTONS;
m_pwndPageTree = CreatePageTreeObject();
if (!m_pwndPageTree)
{
ASSERT(FALSE);
AfxThrowMemoryException();
}
// MFC7-support here (Thanks to Rainer Wollgarten)
#if _MFC_VER >= 0x0700
{
// Using 'CTreeCtrl::CreateEx' (and it's indeed a good idea to call this one), results in
// flawed window styles (border is missing) when running under WinXP themed.. ???
//m_pwndPageTree->CreateEx(
// WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY,
// WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle,
// rectTree, this, s_unPageTreeId);
// Feel free to explain to me why we need to call CWnd::CreateEx to get the proper window style
// for the tree view control when running under WinXP. Look at CTreeCtrl::CreateEx and CWnd::CreateEx to
// see the (minor) difference. However, this could create problems in future MFC versions..
m_pwndPageTree->CWnd::CreateEx(
WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY,
WC_TREEVIEW, _T("PageTree"),
WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle,
rectTree, this, s_unPageTreeId);
}
#else
{
m_pwndPageTree->CreateEx(
WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY,
_T("SysTreeView32"), _T("PageTree"),
WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle,
rectTree, this, s_unPageTreeId);
}
#endif
m_pwndPageTree->SetItemHeight(m_pwndPageTree->GetItemHeight() + 6);
if (m_bTreeImages)
{
m_pwndPageTree->SetImageList(&m_Images, TVSIL_NORMAL);
m_pwndPageTree->SetImageList(&m_Images, TVSIL_STATE);
}
// Fill the tree ctrl
RefillPageTree();
// Select item for the current page
if (pTab->GetCurSel() > -1)
SelectPageTreeItem(pTab->GetCurSel());
return bResult;
}
void CTreePropSheet::OnDestroy()
{
CPropertySheet::OnDestroy();
if (m_Images.GetSafeHandle())
m_Images.DeleteImageList();
if (m_pwndPageTree)
{
VERIFY( m_pwndPageTree->DestroyWindow() );
delete m_pwndPageTree;
m_pwndPageTree = NULL;
}
if (m_pFrame)
{
VERIFY( m_pFrame->GetWnd()->DestroyWindow() );
delete m_pFrame;
m_pFrame = NULL;
}
}
LRESULT CTreePropSheet::OnAddPage(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(PSM_ADDPAGE, wParam, lParam);
if (!m_bTreeViewMode)
return lResult;
RefillPageTree();
SelectCurrentPageTreeItem();
return lResult;
}
LRESULT CTreePropSheet::OnRemovePage(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(PSM_REMOVEPAGE, wParam, lParam);
if (!m_bTreeViewMode)
return lResult;
RefillPageTree();
SelectCurrentPageTreeItem();
return lResult;
}
LRESULT CTreePropSheet::OnSetCurSel(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
if (!m_bTreeViewMode)
return lResult;
SelectCurrentPageTreeItem();
UpdateCaption();
return lResult;
}
LRESULT CTreePropSheet::OnSetCurSelId(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
if (!m_bTreeViewMode)
return lResult;
SelectCurrentPageTreeItem();
UpdateCaption();
return lResult;
}
void CTreePropSheet::OnPageTreeSelChanging(NMHDR *pNotifyStruct, LRESULT *plResult)
{
*plResult = 0;
if (m_bPageTreeSelChangedActive)
return;
else
m_bPageTreeSelChangedActive = TRUE;
NMTREEVIEW *pTvn = reinterpret_cast<NMTREEVIEW*>(pNotifyStruct);
int nPage = m_pwndPageTree->GetItemData(pTvn->itemNew.hItem);
BOOL bResult;
if (nPage<0 || (unsigned)nPage>=m_pwndPageTree->GetCount())
bResult = KillActiveCurrentPage();
else
bResult = SetActivePage(nPage);
if (!bResult)
// prevent selection to change
*plResult = TRUE;
// Set focus to tree ctrl (I guess that's what the user expects)
m_pwndPageTree->SetFocus();
m_bPageTreeSelChangedActive = FALSE;
return;
}
void CTreePropSheet::OnPageTreeSelChanged(NMHDR *pNotifyStruct, LRESULT *plResult)
{
*plResult = 0;
UpdateCaption();
return;
}
LRESULT CTreePropSheet::OnIsDialogMessage(WPARAM wParam, LPARAM lParam)
{
MSG *pMsg = reinterpret_cast<MSG*>(lParam);
if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_TAB && GetKeyState(VK_CONTROL)&0x8000)
{
if (GetKeyState(VK_SHIFT)&0x8000)
ActivatePreviousPage();
else
ActivateNextPage();
return TRUE;
}
return CPropertySheet::DefWindowProc(PSM_ISDIALOGMESSAGE, wParam, lParam);
}
//} //namespace TreePropSheet
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -