Adding a Context Menu to a Window

Date: 12 September 1997
Author: Mark Caroli, University of Mannheim, Germany

Overview

This article discusses the use of context menus. Context menus are the menus which appear when the right mouse button is clicked in a window' s client area.

The text is divided into three chapters. The first one focusses on different ways of creating an instance of the TPopupMenu class, which contains the context menu. Chapter two introduces two alternatives for prompting the context menu on the screen. Finally, you can see how to display different context menus for one window. A download sample is available.

Creating An Instance Of The TPopupMenu Class

The first thing that has to be done when you want to use context menus is the creation of an TPopupMenu instance. This chapter introduces several alternatives for accomplishing this task.

Let us assume that you have defined the following menu in the resource workshop

Unfortunenatly a TPopupMenu object cannot be created directly from a resource script. This is only valid for it's base class TMenu. In addition to this there is a TPopupMenu constructor that supports TMenu instances. So all we have to do is:

The corresponding code looks like this:

OWL also supports the use of submenus of the main window's menu as context menu. Therefore we have to retrieve the handle of the main window. It is used to retrieve the main menu itself. The TMenu::GetSubMenu() requires the index of the submenu you wish to extract and returns its handle. From the handle another TMenu instance holding the submenu's items is created. This one is used in the same manner as above to get the TPopupMenu object. These steps are illustrated in the code below:

The previously mentioned alternatives are based on the assumption that the context menu is known at design time. Sometimes this is not the case. The context menu has to be generated at runtime. With the default constructor you can create an empty TPopupMenu object. Menuitems can be added with the AppendMenu(...) function. The meaning of the parameters is explained in the BWCC online help. The following code adds two menuitems to an empty popupmenu:

Invoking A Context Menu

There exist two ways to tell your window to popup a context menu when the right mouse button is pressed.

You can either call the TWindow::AssignContextMenu(...) method in the window' s SetupWindow function. It requires a pointer to a TPopupMenu instance.

Or you can use the WM_RBUTTONDOWN message to display the context menu. In order to achieve that, we, first of all, need to declare the response table entry and a handler for this message.

The the handler's implementation

The next code snippet shows a template implementation:

No matter which alternative you choose a response table entry and a handler for each menuitem must be defined. If you forget these, the menuitems will appear grayed, when the context menu is activated. The article "Responding To Dynamically Created Controls And Menuitems" shows how to respond to menuitems without having defined these things. It also can be seen from the sample application.

Different Context Menus For Different Areas In One Window

Let us say that you have a window where you want to popup different context menus. Which menu is displayed depends on the current position of the mouse cursor. This problem sounds very difficult, but for rectangular regions it is quite easy to solve. For each context menu to be shown, you declare a TRect instance indicating the areas where the context menue is valid. In the EvRButtonDown handler you receive the coordinates of the point where the click took place. Checking in which rectangle the point lies leads to the solution. Below a template function is shown:


This solution does not work properly, if the rectangles intersect.

Further Resources