这可能是非常基本的问题,但由于新手不明白原因,基本上我想要树控制上的弹出菜单,在右键单击树控件时会弹出一个菜单,在此菜单的基础上其他功能继续。为此,我使用了以下代码,
<。>在.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()函数没有在菜单上调用。即使所有菜单都默认启用。我做错了什么?
答案 0 :(得分:1)
您已将命令范围添加到树控件的消息映射中,但您没有使用树控件作为菜单的所有者窗口。
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);