如何讓右鍵單擊 CTreeCtrl 選項時彈出不同的選單

如何在 Docking Windows 上添加控制項 (控件) 中我們已經成功加入CTreeCtrl

在 如何在 CTreeCtrl 上添加右鍵選單 中我們也成功加入popup menu

但是該如何讓不同層的 CTreeCtrl 顯示不同的快顯功能表呢?

 

首先必須在增加 CTreeCtrl 節點時使用 SetItemData() 設置節點類型

並且對 OnRBClick 作一些修改,利用 GetItemData() 獲得節點類型

再根據節點的類型彈出不同的選單,細節就請參考下面的程式碼和參考資料囉

 

[實作過程]

1. 使用 SetItemData() 設定 root、folder、file 的類型

	HTREEITEM hRoot = m_wndTree.InsertItem(_T(fd.GetFileTitle()));
	m_wndTree.SetItemData(hRoot,1);

	HTREEITEM hSource = m_wndTree.InsertItem(_T("Source Files"), hRoot);
	HTREEITEM hLinker = m_wndTree.InsertItem(_T("Linker Files"), hRoot);
	HTREEITEM hHeader = m_wndTree.InsertItem(_T("Header Files"), hRoot);

	m_wndTree.SetItemData(hSource,2);
	m_wndTree.SetItemData(hLinker,2);
	m_wndTree.SetItemData(hHeader,2);

	hFile = m_wndTree.InsertItem(fileName.c_str(), hFind);
	m_wndTree.SetItemData(hFile, 3);

2. 使用 GetItemData() 得到目前選到的節點類型

然後再根據得到的值去動態調整選單

void CMainFrame::OnRBClick(NMHDR* pNMHDR, LRESULT* pResult)
{
	CPoint point;
	GetCursorPos(&point);
	CPoint pointInTree = point;
	m_wndTree.ScreenToClient(&pointInTree);
	UINT flag = TVHT_ONITEM;
	HTREEITEM item = m_wndTree.HitTest(pointInTree, &flag);

	if(item != NULL)
	{
		m_wndTree.SelectItem(item);

		// Get hLevel, to decide the popup menu
		// 使用 GetItemData() 得到目前選到的節點類型
		int hLevel = m_wndTree.GetItemData(item);

		CMenu menu;
		VERIFY(menu.LoadMenu(IDR_POPMENU));
		CMenu* pPopup = menu.GetSubMenu(0);
		ASSERT(pPopup != NULL);
		CWnd* pWndPopupOwner = GetTopLevelFrame();
		int nItemCount = pPopup->GetMenuItemCount();

		// 根據得到的值動態調整選單
		switch (hLevel)
		{
		case 0:
			// 從第九個開始刪到最後一個,刪掉 ID=10 的 menu 選項
			// MF_BYPOSITION 表示後面自動調整 ID
			for(int i=9;i<nItemCount;i++) 
				pPopup->DeleteMenu(10,MF_BYPOSITION);
			break;
		case 1:
			for(int i=0;i<11;i++) 
				pPopup->DeleteMenu(0, MF_BYPOSITION);
			for(int i=26;i<nItemCount;i++)
				pPopup->DeleteMenu(15, MF_BYPOSITION);
			break;
		case 2:
			for(int i=0;i<27;i++)
				pPopup->DeleteMenu(0, MF_BYPOSITION);
			for(int i=37;i<nItemCount;i++) 
				pPopup->DeleteMenu(10, MF_BYPOSITION);
			break;
		case 3:
			for(int i=0;i<38;i++) 
				pPopup->DeleteMenu(0, MF_BYPOSITION);
			break;
		default:
			MessageBox("Error case.");
			break;
		}
		pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
		pWndPopupOwner);
	}
}

 

[參考資料]

1. 怎么在鼠标右键 单击CTreeCtrl中的项的时候,弹出不同的菜单?

2. CTreeCtrl::GetItemData()的用法,返回值

3. MFC中菜單項的動態添加、刪除與響應

4. CMenu::DeleteMenu