Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TrackPopupMenu not working (context menu for a menu item)

1,166 views
Skip to first unread message

Dark

unread,
Jul 25, 2003, 12:54:36 PM7/25/03
to
Hi,

If anyone could help me with this problem, I'd appreciate it.

I am trying to write a C++ program with some logic so that when
the user has a menu open and right-clicks on a menu item, a
context menu will be shown, with options specific to that menu
item. I'm creating the main menu dynamically, and also plan to
have certain items on the context menu created dynamically.

I've put my code in CMainFrame::OnRButtonDown(). This way, it is
executed whenever I right-click on an open menu.

But when I call TrackPopupMenu() (either the CMenu version, or the
win32 version, or TrackPopupMenuEx()), it returns zero (which means
the function was nonsuccessful) without even showing the popup menu.
GetLastError() also usually returns zero. Very sporadically,
GetLastError() returns 87 - ERROR_INVALID_PARAMETER.

I've tried using CMainFrame::OnContextMenu() instead, but that
doesn't seem to get called when I right-click on an open menu
item. When I right-click somewhere else, such as in the application
window, the popup menu does get shown. This makes me think that my
code for TrackPopupMenu() is written correctly, and that there is
just some issue with calling it when another menu is already open.

The popup menu also works fine when called from the OnRButtonDown()
handler in my View class. But there again, that handler is only called
when I've right-clicked in the application window, and not on an open
menu.

I've tried using a static/previously created menu with LoadMenu() and
GetSubMenu(), as well as creating the popup dynamically instead with
CreatePopupMenu() and AppendMenu(), but doing it either way gets the
same results.


There's got to be a way of doing what I want, since Windows has this
functionality - when you open the Start menu and right-click on an
item, you get a context menu. But I haven't found any examples of
code for doing this in the web. The examples all seem to be for
displaying context menus when clicking on things other than a menu.


Here is one example of my code:

void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu *pmnuMain;
CMenu *pmnuPopup;
CString strMsg;

pmnuMain = new CMenu;
if (!pmnuMain->LoadMenu(IDR_BKMK_POPUP_MENU))
{
MessageBox("Error loading mainpopup menu!");
return;
}

pmnuPopup = pmnuMain->GetSubMenu(0);
if (!pmnuPopup)
{
MessageBox("Error getting submenu");
return;
}

if (!pmnuPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,
point.x, point.y,
this,
NULL))
{
DWORD dwErr = GetLastError();
MessageBox("Error doing trackpopup!");
strMsg.Format("getlasterror: 0x%08x", dwErr);
MessageBox(strMsg);
}

CFrameWnd::OnRButtonDown(nFlags, point);
}

Here is another version I've tried:

void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CMenu *pmnuPopup;
CString strMsg;
HMENU hMnu;
HWND hWnd;

pmnuPopup = new CMenu;

pmnuPopup->CreatePopupMenu();
pmnuPopup->AppendMenu(MF_STRING,
IDR_MENU_ID_MIN + 1,
"popup 1");
pmnuPopup->AppendMenu(MF_STRING,
IDR_MENU_ID_MIN + 2,
"popup 2");
pmnuPopup->AppendMenu(MF_STRING,
IDR_MENU_ID_MIN + 3,
"popup 3");

hMnu = pmnuPopup->GetSafeHmenu();
hWnd = this->GetSafeHwnd();
ClientToScreen(&point);
::SetForegroundWindow(hWnd);

if (!TrackPopupMenu(hMnu,
TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD,
point.x, point.y, 0,
hWnd,
NULL))
{
DWORD dwErr = GetLastError();
MessageBox("Error doing trackpopup!");
strMsg.Format("getlasterror: 0x%08x", dwErr);
MessageBox(strMsg);
}

CFrameWnd::OnRButtonDown(nFlags, point);
}


I'm running MSVC++ 4.0 on Windows ME.

Thanks for any help,

Dark

Tim

unread,
Jul 25, 2003, 9:17:35 PM7/25/03
to
Dark,

Hi, I believe that you can only have 1 active menu at a time. The usual
approach is to modify the menu prior to display.

Take a look at WM_INITMENU and the topic on menus in MSDN.

Also, take a look at OnxxxUI for enable, disable, tick, untick.

- Tim


"Dark" <ocean...@netscape.net> wrote in message
news:242f7055.03072...@posting.google.com...

Elias Fotinis

unread,
Jul 26, 2003, 6:23:45 PM7/26/03
to
Dark wrote:
> I am trying to write a C++ program with some logic so that when
> the user has a menu open and right-clicks on a menu item, a
> context menu will be shown, with options specific to that menu
> item. I'm creating the main menu dynamically, and also plan to
> have certain items on the context menu created dynamically.

Like Tim said, I don't think you can have two separate menus active at
the same time.

Every menu in Windows that has a right-click submenu is actually a
special window of class "BaseBar" (or "MenuSite"; I don't remember
exactly). So, I believe we have to implement our own special "menus" to
do this.

Dark

unread,
Jul 26, 2003, 10:02:02 PM7/26/03
to
I don't really want both menus to be active at the same time - only
the context-menu will be active, although the underlying one will
still be displayed.

However, I searched the MSDN site as Tim suggested, and did eventually
find out what I needed. There is a TPM_RECURSE flag that needs to be
set in order for the context menu to work on an open menu item.
My version of VC++ didn't include documentation on this flag, and
didn't even have it defined, but when I use it, it works:

#define TPM_RECURSE 1
...
if (!pmnuPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RECURSE,
point.x, point.y,
this,
NULL))
...

There is also a message specific to when you right-click on a menu
item: WM_MENURBUTTONUP, which isn't in my documentation either.
I tried using it, but it only seems to be sent for right-clicks on
regular menu items, not for clicks on submenu-type menu items. So
I'm still using WM_RBUTTONDOWN instead.

Thanks,
Dark

"Elias Fotinis" <efoti...@SPAMyahoo.com> wrote in message news:<1059259444.67698@athprx02>...

Tim

unread,
Jul 26, 2003, 11:10:59 PM7/26/03
to
Normally, if you use menus as they are designed and intended to be used, you
do not have to do any of this EG processing WM_MENURBUTTONUP as the menu
system itself handles this message.
It seems to me that you may be complicating things expecting them to be
complex.

If you have a context menu, then assemble the entire context menu before
calling Track... you won't then need to know anything about what goes on
while the menu is active. Similarly for resouce based menus EG the main menu
bar, modify the menu during the WM_INITMENU message and add / remove any
menu items you need to customise it before it is show.

In general it is regarded as not nice to have such context sensitive menus -
eg as per the Project Properties in VS.Net - the user will find it difficult
to learn when and why the various menu items appear and disappear. It is not
intuitive. Be careful to detail the whens and whys in online help. Consider
using the Enable / Disable methods and have all the options in the context
menu all the time - it is then an easy read for the user to see 'when I
right click on an object in state x this happens'.

- Tim


"Dark" <ocean...@netscape.net> wrote in message

news:242f7055.0307...@posting.google.com...

0 new messages