Date: 12 September
1997
Author: Mark Caroli, University of Mannheim, Germany
This articles issue is the treatment of messages sent by dynamically created controls or menuitems. The first section only focusses on controls . In the second one you get to know how to insert menuitems at runtime . Finally, the response to dynamically created menuitems is explained. In addition to that there is a sample for download purposes.
The standard procedure for responding to a message sent by an arbitary control looks like this:
For the most cases that is suitable, but the controls you want to work with must be known at design time. If the controls are created at runtime this technique does not provide any possibility to respond to messages coming from the new controls. The key to the solution of this problem is the TWindow::EvCommand() function which is called, when something happens in your control. You receive three values:
These are sufficient to identify the sending control and the message. A specific function call can be invoked. The code following code snippet shows how to respond to the BN_CLICKED message of three dynamically created TButton objects. They have the IDs IDBASE, IDBASE+1 and IDBASE+2. As you cann see from the code you have to keep track of the ID's of the new controls.
TResult TDynRespDialog::EvCommand(uint id, THandle hWndCtl, uint notifyCode)
//Responds to the messages sent by the dynamically created controls
{
TResult result;
result = TDialog::EvCommand(id, hWndCtl, notifyCode);
if (notifyCode == BN_CLICKED)
if (id >= IDBASE)
if (id < IDBASE + NUMCTRL)
{
char szString[255];
sprintf (szString,"You've pressed Button %i",id-IDBASE);
MessageBox (szString,"DynControl");
}//if
return result;
}
This section describes in brief how to add new menuitems to an existing menu. First, you need to retrieve the handle of the window holding the menu. Normally this is the FrameWindow. With this handle you can retrieve the menu. The application of the TMenu::GetSubMenu() method delivers the submenu where you want to add the menuitems. Use the TMenu::InsertMenu(...) function to add the items.
void TDynRespWindow::CmDynitem()
{
//get the main menu
HWND HFrame = *GetApplication()->GetMainWindow();
TMenu *pMenu = new TMenu (HFrame);
// get the submenu where the new items will be inserted
TMenu* pSubMenu = new TMenu(pMenu->GetSubMenu(1));
// insert two new item at the end
pSubMenu->InsertMenu(3, MF_BYPOSITION, IDITEMBASE,"Menuitem 1");
pSubMenu->InsertMenu(4, MF_BYPOSITION, IDITEMBASE+1,"Menuitem 2");
delete pMenu;
delete pSubMenu;
}
In the sample above the items are inserted by position. The first parameter specifies the position, the second one is self explainatory, the third one is the ID of the new item and finally we have the item string.
Responding to dynamically created menuitems is nearly the same as responding to controls created in the same manner. You just have to overload a function called EvCommandEnabler(...) in order to avoid that the new items are enabled when you click on the popup menu. The implementation of this function does nothing else then expilicitly enabling the new menuitems.
TResult TDynRespWindow::EvCommand(uint id, THandle hWndCtl, uint notifyCode)
/* Handles command notificatios send by the menuitems with no response table
entry defined */
{
TResult result;
result = TWindow::EvCommand(id, hWndCtl, notifyCode);
if (notifyCode == WM_NULL)
if (id == IDITEMBASE)
MessageBox ("You' ve selected Menuitem 1","Dynamic Menuitems");
else
if (id == IDITEMBASE+1)
MessageBox ("You' ve selected Menuitem 2","Dynamic Menuitems");
return result;
}
void TDynRespWindow::EvCommandEnable(TCommandEnabler& Enabler)
{
if (IDITEMBASE <= Enabler.Id && Enabler.Id <= IDITEMBASE+NUMITEMS)
{
// enable dynamic menu specific item
Enabler.Enable(true);
}//if
else
TWindow::EvCommandEnable(Enabler);
}