⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 treepropsheet.cpp

📁 MFC窗口程序设计源代码。相信大家看得懂。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				return hResult;
		}

		hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
	}

	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 (!bRealPage)
		m_pFrame->SetMsgText(GenerateEmptyPageMessage(m_strEmptyPageMessage, strCaption));

	//如果没有标题则取消它
	if (!m_pFrame->GetShowCaption())
		return;

	//获取tab控件
	CTabCtrl	*pTabCtrl = GetTabControl();
	if (!IsWindow(pTabCtrl->GetSafeHwnd()))
	{
		ASSERT(FALSE);
		return;
	}

	if (m_bTreeImages)
	{
		//从树上获取图标
		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)
	{
		//从隐藏的tab获取图像
		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()))
	{
		//常规的tab属性表,简单使用页索引
		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();
		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)
		{
			//前一项不存在,则循环至最后项
			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()))
	{
		//常规的tab属性表,简单使用页索引
		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();
		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)
			//前一项不存在,则循环至第一项
			hNextItem = m_pwndPageTree->GetRootItem();

		if (hNextItem)
			m_pwndPageTree->SelectItem(hNextItem);
	}
}


/////////////////////////////////////////////////////////////////////
// Overridings

BOOL CTreePropSheet::OnInitDialog() 
{
	if (m_bTreeViewMode)
	{
		//确保属性表标签没有堆积,否则在树形模式下页标题将会很大
		EnableStackedTabs(FALSE);
		//初始化图像列表
		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, ILC_COLOR32|ILC_MASK, 0, 1);
		}
		else
			m_Images.Create(16, 16, ILC_COLOR32|ILC_MASK, 0, 1);
	}

	//完成缺省的实现
	BOOL bResult = CPropertySheet::OnInitDialog();

	if (!m_bTreeViewMode)
		//如果使用常规的属性表则直接返回即可
		return bResult;

	//获取属性表的标签控件
	CTabCtrl	*pTab = GetTabControl();
	if (!IsWindow(pTab->GetSafeHwnd()))
	{
		ASSERT(FALSE);
		return bResult;
	}

	//隐藏标签控件
	pTab->ShowWindow(SW_HIDE);
	pTab->EnableWindow(FALSE);
	//实际上放置的是一个空的tab控件,目的是在Tab的位置上创建框架
	//相当于将Tab控件当作占位符
	CRect	rectFrame;
	pTab->GetWindowRect(rectFrame);
	ScreenToClient(rectFrame);
	//创建CPropPageFrame 对象
	m_pFrame = CreatePageFrame();
	if (!m_pFrame)
	{
		ASSERT(FALSE);
		AfxThrowMemoryException();
	}
	//创建CPropPageFrame窗口
	m_pFrame->Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0xFFFF);
	m_pFrame->ShowCaption(m_bPageCaption);
	//为树控件提供空间,默认宽度120像素
	const int	nTreeWidth = m_nPageTreeWidth;
	//树形控件和属性表标签控件之间的距离
	const int	nTreeSpace = 5;

	CRect	rectSheet;
	//获取属性表大小
	GetWindowRect(rectSheet);
	//将属性表加宽nTreeWidth,以便为额外的树形控件提供空间
	rectSheet.right+= nTreeWidth;
	//根据新的大小,重新设置属性表
	SetWindowPos(NULL, -1, -1, rectSheet.Width(), rectSheet.Height(), SWP_NOZORDER|SWP_NOMOVE);
	//将属性表调整到父窗口中央
	CenterWindow();
	//将所有的子窗口向右移动nTreeWidth像素
	MoveChildWindows(nTreeWidth, 0);
	//计算树形控件的矩形大小
	CRect	rectTree(rectFrame);
	//树形控件的右边界为:
	rectTree.right = rectTree.left + nTreeWidth - nTreeSpace;
	//计算标题的高度
	//创建Tab控件,只是用来计算标签的高度,因为树形控件的标题栏高度将等于此值
	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 (!m_bPageCaption)
	{
		//使框架小一些
		m_pFrame->GetWnd()->GetWindowRect(rectFrame);
		ScreenToClient(rectFrame);
		rectFrame.top+= rectFrameCaption.Height();
		m_pFrame->GetWnd()->MoveWindow(rectFrame);
		//移动所有的子窗口
		MoveChildWindows(0, -rectFrameCaption.Height());
		//修改树控件的矩形
		rectTree.bottom-= rectFrameCaption.Height();
		//减小窗口的大小
		CRect	rect;
		GetWindowRect(rect);
		rect.top+= rectFrameCaption.Height()/2;
		rect.bottom-= rectFrameCaption.Height()-rectFrameCaption.Height()/2;
		if (GetParent())
			GetParent()->ScreenToClient(rect);
		MoveWindow(rect);
	}

	//最后创建树控件对象
	const DWORD	dwTreeStyle = TVS_SHOWSELALWAYS|TVS_TRACKSELECT|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS;
	m_pwndPageTree = CreatePageTreeObject();
	if (!m_pwndPageTree)
	{
		ASSERT(FALSE);
		AfxThrowMemoryException();
	}
	//并创建树控件窗口
	m_pwndPageTree->CreateEx(
		WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY, 
		_T("SysTreeView32"), _T("属性页树视"), 
		WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle, 
		rectTree, this, s_unPageTreeId);

	if (m_bTreeImages)
	{
		m_pwndPageTree->SetImageList(&m_Images, TVSIL_NORMAL);
		m_pwndPageTree->SetImageList(&m_Images, TVSIL_STATE);
	}

	//设置树控件颜色
	m_pwndPageTree->SetBkColor(RGB(192,192,192));
	//填充树控件
	RefillPageTree();
	// 选择当前页对应的项
	if (pTab->GetCurSel() > -1)
		SelectPageTreeItem(pTab->GetCurSel());

	return bResult;
}


void CTreePropSheet::OnDestroy() 
{
	CPropertySheet::OnDestroy();
	
	if (m_Images.GetSafeHandle())
		m_Images.DeleteImageList();

	delete m_pwndPageTree;
	m_pwndPageTree = NULL;

	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;
}


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)
		//防止选择的变化
		*plResult = TRUE;

	//设置树控件焦点
	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);
}



⌨️ 快捷键说明

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