非常基本的问题,但由于新手不明白原因,基本上我想要树控件上的弹出菜单,右键单击树控件时会弹出一个菜单,在此菜单的基本功能上继续。为此,我使用了以下代码,
在 .h 文件中,
#define NEW_RELAY_MENU_START WM_USER + 1
#define NEW_RELAY_MENU_END WM_USER + 256
在.cpp文件中
BEGIN_MESSAGE_MAP(CCtrlModDefDlgTree, CTreeCtrl)
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChangedTreeCtrl)
ON_NOTIFY_REFLECT(NM_RCLICK, &CCtrlModDefDlgTree::OnNMRClick)
ON_COMMAND_RANGE(NEW_RELAY_MENU_START,NEW_RELAY_MENU_END,CCtrlModDefDlgTree::OnNewMenu)
END_MESSAGE_MAP()
CCtrlModDefDlgTree::CCtrlModDefDlgTree()
{
NumberOfRelays.RemoveAll();
NumberOfRelays.Add(L"MENU1");
NumberOfRelays.Add(L"MENU2");
NumberOfRelays.Add(L"MENU3");
NumberOfRelays.Add(L"MENU4");
NumberOfRelays.Add(L"MENU5);
NumberOfRelays.Add(L"MENU6");
}
void CCtrlModDefDlgTree::OnNMRClick(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: Add your control notification handler code here
/* Get the cursor position for this message */
DWORD dwPos = GetMessagePos();
/* Convert the co-ords into a CPoint structure */
CPoint pt( GET_X_LPARAM( dwPos ), GET_Y_LPARAM ( dwPos ) );
CPoint spt;
spt = pt;
/* convert to screen co-ords for the hittesting to work */
ScreenToClient( &spt );
UINT test;
HTREEITEM hti = HitTest( spt, &test );
if ( hti != NULL )
{
/* Is the click atcually *on* the item? */
if ( test & TVHT_ONITEM )
{
/* Do the normal context menu stuff */
ShowPopupMenu( pt );
}
}
*pResult = 0;
}
void CCtrlModDefDlgTree::ShowPopupMenu( CPoint& point )
{
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
//create a menu object for main menu
CMenu *menu = new CMenu();
menu->CreatePopupMenu();
//another menu object for submenu
CMenu *subMenu = new CMenu();
subMenu->CreatePopupMenu();
for(int __index = 0;__index<NumberOfRelays.GetCount();__index++)
{
subMenu->AppendMenu(MF_STRING, NEW_RELAY_MENU_START+__index, NumberOfRelays.ElementAt(__index));
}
//append submenu to menu
menu->AppendMenu(MF_POPUP|MF_STRING, (UINT)subMenu->m_hMenu, _T("New Menu") );
ASSERT(menu != NULL);
CWnd* pWndPopupOwner = this;
while (pWndPopupOwner->GetStyle() & WS_CHILD)
pWndPopupOwner = pWndPopupOwner->GetParent();
menu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
pWndPopupOwner);
}
void CCtrlModDefDlgTree::OnNewMenu(UINT nID)
{
}
但是我的 OnNewMenu() 函数在菜单单击时没有被调用。甚至所有菜单都默认启用。我做错了什么?
您已将命令范围添加到树控件的消息映射中,但未将树控件用作菜单的所有者窗口。
CWnd* pWndPopupOwner = this;
while (pWndPopupOwner->GetStyle() & WS_CHILD)
pWndPopupOwner = pWndPopupOwner->GetParent();
这将找到顶级窗口并将其用作弹出窗口的所有者,这意味着弹出窗口中的WM_COMMAND
消息将转到顶级窗口而不是树。您需要将命令范围添加到该窗口的消息映射中。
或者,您可以将 TPM_RETURNCMD
标志与 TrackPopupMenu
一起使用,这将返回选定的命令 ID,然后自己调用OnNewMenu()
函数:
int iID = menu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
point.x, point.y, pWndPopupOwner);
if (iID) OnNewMenu(iID);