Skip to main content

Application Context Menus

Context menus (or "right-click popup" menus) come in two flavors: application-wide or control-specific. This article focuses on the former.

Implementing the Application Popup Menu

The first step in creating a context menu is simple: use the Visual Studio resource editor to create the menu you wish to display. Make sure that you give it a unique ID; I will use the value IDR_POPUP_MENU for this example. Add to the menu the various menu items that you want to include. Note that your context menu should only have one top-level item (under which all other menu items will be placed). The caption for this top-level item can be whatever you like since the user will never see it. If you are mapping menu items in this context menu to commands that already exist in the program (as is likely), make sure that you give each menu item the appropriate ID. For example, if the ID to my "Open File" command in my main application menu is ID_FILE_OPEN, I would give that same ID to the corresponding item in my context menu. If you aren't mapping commands, simply add any message handlers as normal.
In order to display the context menu to the user when they click the right mouse button, we need to add a handler for the WM_CONTEXTMENU message. This handler should be added to the window class that will handle the menu's message calls. Most often, this class will be your view class, but note that any CWnd based class will do.
Once the message handler has been added, insert the following code into the WM_CONTEXTMENU handler's method:// We might need to adjust the origination point for the

// keyboard context menu
if(point.x == -1 && point.y == -1)
{
CRect rect;
GetClientRect(&rect);
point = rect.TopLeft();
point.Offset(5,5);
ClientToScreen(&point);
}


// Load the top level menu from the resource we created
CMenu myMenu;
myMenu.LoadMenu(IDR_POPUP_MENU);


// Now extract the (one and only) popup menu item from
// this menu resource
CMenu* myPopup = myMenu.GetSubMenu(0);

// Let's display the menu!
myPopup->TrackPopupMenu(TPM_LEFTALIGN TPM_LEFTBUTTON,
point.x, point.y, AfxGetMainWnd(), NULL);


Understanding the Code

The first thing we do is to handle the case where the user invokes our context menu via the keyboard. In this scenario, we adjust the origination point for the menu. Next, we load the menu resource that we created earlier and extract the popup menu item (the one and only top-level item). The popup menu extraction is performed by using the GetSubMenu() method, and passing the (zero-based) index of the item to extract. Since we only had one top-level menu item, a value of zero gets passed in.
Finally, we make a call to the TrackPopupMenu() method to display the menu to the user. The first parameter in this method call is a series of flags used to specify where the menu shows up in relation to the mouse cursor, as well as what buttons can be used to select the menu items. The screen position may only be one of the following:
TPM_CENTERALIGN - Centers the menu horizontally relative to the coordinate specified by x.
TPM_LEFTALIGN - Positions the menu so that its left side is aligned with the coordinate specified by x.
TPM_RIGHTALIGN - Positions the menu so that its right side is aligned with the coordinate specified by x.
The mouse button flag can be any combination of the following two values:
TPM_LEFTBUTTON - Causes the menu to track the left mouse button.
TPM_RIGHTBUTTON - Causes the menu to track the right mouse button.
The next two parameters in the TrackPopupMenu() call specify the horizontal and vertical locations of the menu (the horizontal position depending on the flag used in the first parameter). Next comes a pointer to the window that owns the popup menu. Since we want our messages to be routed to our top-most parent, we use a call to AfxGetMainWnd() to get the top level window. The final parameter defines a CRect in which the user can click without dismissing the popup menu. A value of NULL here will do the right thing: clicking outside of the menu will dismiss it.

Comments

Popular posts from this blog

Simple Windows Registry Access

The Windows registry is an excellent place to store program information. From recent file lists to program settings, the registry provides programmers with a central location to store information for future use. Registry access can be quite simple, provided that you accept a few limitations. First, you must be willing to store your registry values on a per-user basis (rather than for all users). Second, you may only read and write values to your own application's registry branch. Poking around in arbitrary places in the Windows registry is somewhat more complicated than the method provided in this article. Do not assume that the constraints mentioned above render this method of registry access useless. I personally use this registry access method for all of my applications, using the advanced access method only when necessary. The simple method described below will do everything you need it to do for simple storage of application specific information. Enabling Registry Access The ...

Visual C++ FAQs part-2

Q 1.01 Is there any function to minimize the window? A. ThatsAlok quoted :- If you are using MFC: this->ShowWindow(SW_MINIMIZE); If you are using Win32 API based application: ShowWindow(hWnd,SW_MINIMIZE); Q 1.02 How do I stop appearing of the SQL Sever login dialog again and again? A. renjith_sree quoted :- Use CDatabase::noOdbcDialog as the second parameter in OpenEx() method. E.g.: extern CDatabase oDb; extern CString csConnection; oDb.OpenEx(csConnection, CDatabase::noOdbcDialog ); This will suppress the login dialog. Q 1.03 How can I access USB port (COM 5)? A. Antti Keskinen quoted :- The USB is a bus that resides in the computer. The low-level drivers (supplied by Microsoft) allow the bus to enumerate and identify a piece of hardware and then send a request to the registry to find the correct function driver for the device by using the vendor and product IDs returned by the USB descriptors. This is how the bus works in a nutshell. Your computer systems might have a pseudo-devi...

Advanced Windows Registry Access

If you are interested in how to access arbitrary locations in the Windows registry, this is the article for you. However, if you would prefer to learn a simpler method of registry access to store and retrieve program settings, consult my simple registry access article . Opening (Reading) Keys Unlike the simpler, application based method, we don't need to enable registry access via a special function call. Instead, the functions we will be using interface directly with the registry itself. Let's look at the code required to open an arbitrary key value:HKEY hKey; RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE, &hKey); As you can see, we are using the RegOpenKeyEx() function. Let's take a look at its various parameters: Parameter 1: A handle to a currently open key or any of the following predefined reserved handle values: HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS HKEY_PERFORMANCE_DAT...