📄 treepropsheetbase.cpp
字号:
{
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);
}
// Set font if disabled.
CPropertyPage* pPage = GetPage( nPage );
ASSERT( pPage );
if( NULL != pPage && !IsPageEnabled( pPage ) )
{
::SendMessage( m_pwndPageTree->GetSafeHwnd(), WMU_ENABLETREEITEM, (WPARAM)hItem, (LPARAM)GetSysColor(COLOR_GRAYTEXT) );
}
}
}
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::RefreshPageTree(HTREEITEM hItem /* = TVI_ROOT */, const bool bRedraw /* = true */)
{
// If TVI_ROOT, get the first item.
if (hItem == TVI_ROOT)
{
hItem = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
}
while( hItem )
{
RefreshTreeItem( hItem );
if( m_pwndPageTree->ItemHasChildren( hItem ) )
{
RefreshPageTree( m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD), false );
}
hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
}
if( bRedraw )
{
m_pwndPageTree->Invalidate( TRUE );
}
}
/////////////////////////////////////////////////////////////////////
//
HTREEITEM CTreePropSheetBase::CreatePageTreeItem(LPCTSTR lpszPath, HTREEITEM hParent /* = TVI_ROOT */)
{
CString strPath(lpszPath);
CString strTopMostItem(SplitPageTreePath(strPath));
// Check if an item with the given text does already exist
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 item with that text does not already exist, create a new one
if (!hItem)
{
hItem = m_pwndPageTree->InsertItem(strTopMostItem, hParent);
m_pwndPageTree->SetItemData(hItem, kNoPageAssociated);
if (!strPath.IsEmpty() && m_bTreeImages && m_DefaultImages.GetSafeHandle())
// set folder image
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 CTreePropSheetBase::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 in front of the
// separator, 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 CTreePropSheetBase::KillActiveCurrentPage()
{
HWND hCurrentPage = PropSheet_GetCurrentPageHwnd(m_hWnd);
if (!IsWindow(hCurrentPage))
{
ASSERT(FALSE);
return TRUE;
}
// Check if the current page is really active (if page is invisible
// an virtual empty page is the active one.
if (!::IsWindowVisible(hCurrentPage))
return TRUE;
// Try to deactivate current page
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))
// current page does not allow page change
return FALSE;
// Hide the page
::ShowWindow(hCurrentPage, SW_HIDE);
return TRUE;
}
/////////////////////////////////////////////////////////////////////
//
HTREEITEM CTreePropSheetBase::GetPageTreeItem(int nPage, HTREEITEM hRoot /* = TVI_ROOT */)
{
// Special handling for root case
if (hRoot == TVI_ROOT)
hRoot = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
// Check parameters
if (nPage < 0 || nPage >= GetPageCount())
{
ASSERT(FALSE);
return NULL;
}
if (hRoot == NULL)
{
ASSERT(FALSE);
return NULL;
}
// we are performing a simple linear search here, because we are
// expecting only little data
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)
return hResult;
}
hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
}
// we've found nothing, if we arrive here
return hItem;
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SelectPageTreeItem(int nPage)
{
ASSERT( -1 != nPage );
HTREEITEM hItem = GetPageTreeItem(nPage);
if (!hItem)
return FALSE;
return m_pwndPageTree->SelectItem(hItem);
}
/////////////////////////////////////////////////////////////////////
//
BOOL CTreePropSheetBase::SelectCurrentPageTreeItem()
{
CTabCtrl *pTab = GetTabControl();
if (!IsWindow(pTab->GetSafeHwnd()))
return FALSE;
// TreePropSheetEx: Fix problem when removing last page from control.
int nPage = pTab->GetCurSel();
if( nPage >= 0 && nPage < pTab->GetItemCount() )
return SelectPageTreeItem( nPage );
// TreePropSheetEx: End fix problem when removing last page from control.
return FALSE;
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::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 CTreePropSheetBase::ActivatePreviousPage()
{
if( !IsWindow(m_hWnd) || 0 == GetPageCount() )
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
{
HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
ActivatePreviousPage( hItem );
}
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::ActivatePreviousPage(HTREEITEM hItem)
{
// 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
ASSERT(hItem);
if (!hItem)
return;
HTREEITEM hPrevItem = m_pwndPageTree->GetPrevSiblingItem(hItem);
if( hPrevItem )
{
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)
return;
// If we skip the empty pages and the tree item does not point to
// a property page, call ActivateNextPage again. This is fine since
// we know there is at least one valid property page in the sheet.
if( IsTreeItemDisplayable( hPrevItem ) )
m_pwndPageTree->SelectItem( hPrevItem );
else
ActivatePreviousPage( hPrevItem );
}
/////////////////////////////////////////////////////////////////////
//
void CTreePropSheetBase::ActivateNextPage()
{
// Window must be defined and a least one property page.
if (!IsWindow(m_hWnd) || 0 == GetPageCount() )
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
{
HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
ActivateNextPage( hItem );
}
}
/////////////////////////////////////////////////////////////////////
//
#pragma warning(push)
#pragma warning(disable:4706)
void CTreePropSheetBase::ActivateNextPage(HTREEITEM hItem)
{
// 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
ASSERT(hItem);
if (!hItem)
return;
HTREEITEM hNextItem = m_pwndPageTree->GetChildItem(hItem);
if ( hNextItem )
{
// Have a child, skip rest of search.
}
else if (hNextItem=m_pwndPageTree->GetNextSiblingItem(hItem))
{
// Had not child but has a sibling, skip rest of search.
}
else if (m_pwndPageTree->GetParentItem(hItem))
{
// No child, no sibling, get the next sibling from the parent.
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)
return;
// If we skip the empty pages and the tree item does not point to
// a property page, call ActivateNextPage again. This is fine since
// we know there is at least one valid property page in the sheet.
if( IsTreeItemDisplayable( hNextItem ) )
m_pwndPageTree->SelectItem( hNextItem );
else
ActivateNextPage( hNextItem );
}
#pragma warning(pop)
/////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::IsWizardMode() const
{
return PSH_WIZARD & m_psh.dwFlags?true:false;
}
//////////////////////////////////////////////////////////////////////
//
int CTreePropSheetBase::GetNextValidPageIndex(HTREEITEM hTreeItem) const
{
HTREEITEM hNextItem = GetNextValidPageTreeItem( hTreeItem );
if( NULL == hNextItem )
return 0;
return m_pwndPageTree->GetItemData( hNextItem );
}
//////////////////////////////////////////////////////////////////////
//
HTREEITEM CTreePropSheetBase::GetNextItem(HTREEITEM hItem) const
{
if( m_pwndPageTree->ItemHasChildren(hItem) )
{
return m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD);
}
return m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
}
//////////////////////////////////////////////////////////////////////
//
HTREEITEM CTreePropSheetBase::GetNextValidPageTreeItem(HTREEITEM hTreeItem) const
{
if (hTreeItem == TVI_ROOT)
hTreeItem = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
if (hTreeItem == NULL)
{
return NULL;
}
HTREEITEM hItem = GetNextItem( hTreeItem );
while (hItem)
{
if( IsTreeItemDisplayable( hItem ) )
return hItem;
if (m_pwndPageTree->ItemHasChildren(hItem))
{
HTREEITEM hResult = GetNextValidPageTreeItem( m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD) );
if( hResult )
return hResult;
}
hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::HasValidPropertyPageAssociated(HTREEITEM hItem) const
{
if( NULL == m_pwndPageTree || NULL == hItem )
return false;
return kNoPageAssociated != (int)m_pwndPageTree->GetItemData( hItem );
}
//////////////////////////////////////////////////////////////////////
//
bool CTreePropSheetBase::IsAssociatedPropertyPageEnabled( HTREEITEM hItem ) const
{
DWORD dwItemData = m_pwndPageTree->GetItemData( hItem );
if( kNoPageAssociated == dwItemData )
{
return true;
}
CPropertyPage* pPage = GetPage( dwItemData );
// ASSERT: No page associated with this item data.
ASSERT( pPage );
if( NULL == pPage )
return true;
return IsPageEnabled( pPage );
}
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -