A typical solution might look like this:
BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)
ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
void CMyTreeCtrl::OnContextMenu(CWnd* pWnd, CPoint point)
{
HTREEITEM hCurSel = GetSelectedItem();
if (point.x < 0 && point.y < 0) {
RECT rect;
if (hCurSel)
{
GetItemRect(hCurSel, &rect, TRUE); ClientToScreen(&rect); point.SetPoint(rect.left, rect.bottom); }
else
{
GetWindowRect(&rect);
point.SetPoint(rect.left, rect.top); }
}
else {
if (GetFocus() != this)
SetFocus();
CPoint pt(point); ScreenToClient(&pt);
hCurSel = HitTest(pt);
if (hCurSel != NULL)
SelectItem(hCurSel);
else { CTreeCtrl::OnContextMenu(pWnd, point);
return;
}
}
CMenu menu;
VERIFY(menu.LoadMenu(IDR_MYTREECTRL_POPUP_MENU));
CMenu *pSub = menu.GetSubMenu(0);
if (NULL == hCurSel)
pSub->EnableMenuItem(IDC_RENAME_ITEM, MF_GRAYED);
int nCommand = pSub->TrackPopupMenuEx(
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_VERPOSANIMATION | TPM_RETURNCMD | TPM_NONOTIFY,
point.x, point.y,
AfxGetMainWnd(), NULL);
switch (nCommand)
{
case IDC_RENAME_ITEM : SetItemText(hCurSel, _T("New item text"));
break;
default : if (nCommand)
SendMessage(WM_COMMAND, nCommand);
}
}