How to dynamically generate menus in VC ++

Source: Internet
Author: User

Download source code

I. Preface
In practical use, you often need to add or remove menus and menu items according to the operation. In the VC ++ development environment, there are multiple ways to dynamically generate menus. For example, you can use the resource editor to create menu resources and then Program Dynamically add menus during running. This method of dynamically generating menus is more common and more is used. When you use this method to dynamically Add a menu, you must first add the menu in resource. h: add the menu ID. Because it is a dynamically generated menu option, you cannot map functions in classwizard to implement it. You need to manually add a message function prototype to the header file. In Code Manually add message ing and message response functions in the file. Another way to dynamically generate menus is to not define each menu ID in advance. For example, the content of each record read from the database is dynamically added as a menu item, the number of menu items is not fixed. When a menu item is dynamically added, the IDs of the menu items are sequentially increased. The response code cannot be written in advance for the message response of the menu item, the function must be dynamically responded according to the menu ID.
Ii. Menu-related knowledge
2.1 common menu operation functions
The common menu operations in VC ++ are as follows:
Getmenu ()-Get the menu linked to the frame window.
Insertmenu ()-Insert a new menu item at the specified position, and move other options down.
Getsubmenu ()-obtain the sub-menu pointer.
Getmenuitemcount ()-Get the number of menu items under the menu.
Appendmenu ()-Add a new menu.
Getmenustring ()-Get the tag of the specified menu item.
Deletemenu ()-delete menu.
2.2 menu Message Processing
Windows messages are classified into standard Windows messages, command messages, and control notification messages. Standard messages refer to messages starting with WM _ prefix except wm_command, including keyboard messages and window messages. Command messages, A wm_command message sent from a menu, shortcut key, toolbar button, or other user interface objects. In MFC, different command messages are distinguished by the menu item ID. In SDK, messages are identified by the wparam parameter. A control notification message is a message that is triggered by a control operation. It is a wm_command notification message sent by the Control and subwindow to its parent window.
A menu command is a command message. A menu command can be mapped to a member function of the framework class, View class, or document class, but cannot be mapped to multiple member functions at the same time. Even if a menu command is mapped to multiple different member functions at the same time, the ing of only one member is valid. In the MFC Document/view structure, the effective priorities are mapped to view class, document class, and framework class.
Once a menu message responds in one of the classes, it no longer finds the Response Function in other classes.
Specifically, the menu command message routing process is as follows: When you click a menu item, the cmainframe framework class receives the menu item message first, the cmainframe framework class will hand over the menu item message to its subwindow View class, which is first processed by the View class. If the View class detects that it has not responded to the menu item message, the View class submits the menu item message to the doc class of the document class for processing. If the doc class detects that the doc class does not respond to the menu item message, then, the doc class returns the menu item message to the View class, and the View class returns the message to the cmainframe class for processing. If the cmainframe class shows that the cmainframe class does not respond to the message, it is finally handed over to the app class for processing. In addition, once a message has been responded to in a class, it is no longer transmitted.
Iii. programming example
3.1 menu instance Project
(1) create a project
Create a project dynamicmenu in VC ++: Select "Single Document" in the first step. You do not need to modify the default settings in the next step. In the last step, select "cformview" from the base class drop-down menu. create an MFC Application Based on formview. In section 3.3 of this project, the dynamic control creation is used as an example. The formview in the view can be placed with the control, so select formview.
(2) create menu Resources
Add "dynamic menu example" to the menu under "resource". There are two menu items, respectively "add Example 1" add Example 2 menu 1. The IDS are id_firstmenu and id_secmenu. Click these two menu items and add them dynamically in two ways. Only menus are added, and the menu function is not implemented. That is, no corresponding command processing function corresponds to the menu item. Therefore, the added menu item is gray, is the current unavailable status. After adding a new menu item, you should also specify a message response function for the new menu item.

Figure 1 create two menu items

use MFC classwizard to add a message response function for two menu items under view. The response function of id_firstmenu is void cdynamicmenuview: onfirstmenu :: onsecmenu ().
3.2 add menus dynamically
This example applies to dynamically adding menus defined in advance to the main menu only when necessary, you can delete it if you do not need it. The response function needs to be manually added, and the code needs to be modified again when the menu item is changed.
function example: click "add Example 1" under "dynamic menu example" in the above dynamicmenu project to add a new dynamic menu "dynamic menu 1". click "first1" under the menu item to respond to the menu. A prompt box is displayed. If the menu item "first2" does not define the message response, it is not available, as shown in figure 2.
Figure 2 running interface
main programming steps: Create menu resources and manually add menu IDs, message ing, and message response functions.
implementation steps:
(1) Add the menu ID to be generated in resource. h In the above dynamicmenu Project, for example:

# Define id_first1 32733 // manually added menu id_first1 # define id_first2 32734 // manually added menu id_first2

(2) manually add the command response function prototype in mainfrm. h.

 
Protected: // {afx_msg (cmainframe) afx_msg int oncreate (maid); // note-The classwizard will add and remove member functions here. // do not edit what you see in these blocks of generated code! ///} Afx_msgafx_msg void onfirst1 (); // The macro declare_message_map () of the manually added message Response Function ()

(3) manually add message ing. In mainfrm. cpp, use the on_command macro to associate the message response function.

 
Begin_message_map (cmainframe, cframewnd) // {afx_msg_map (cmainframe) // note-The classwizard will add and remove mapping macros here. // do not edit what you see in these blocks of generated code! On_wm_create () //} afx_msg_mapon_command (id_first1, onfirst1) // manually add idm_hello to the onhello end_message_map () function ()

(4) When a menu item is added, it is often gray and unavailable. Only a trusted response function is defined for this menu item. If the message response function is defined for the id_first1 menu item, the menu item is available. If the message response function is not defined for id_first2, the menu color is gray. In mainfrm. cpp, manually compile the message response function as follows:

 
Void cmainframe: onfirst1 () {MessageBox ("dynamic menu Example 1 !");}

(5) When you click "add Example 1" under the "dynamic menu example", add "dynamic menu 1" at the end of the menu.
Use MFC classwizard to add a message response function for the menu item id_firstmenu under cdynamicmenuview:

 
Void cdynamicmenuview: onfirstmenu () {// todo: add your command handler code here cmenu menu; menu. createpopupmenu (); // create an empty menu getparent ()-> getmenu ()-> appendmenu (mf_popup, (uint) menu. m_hmenu, "dynamic menu 1"); // Add the menu to the end of the existing menu. appendmenu (mf_string | mf_enabled, id_first1, "first1"); menu. appendmenu (mf_string | mf_enabled, id_first2, "first2"); menu. detach (); getparent ()-> drawmenubar (); // re-paint menu}

3.3 dynamically Add the records read from the database as menu items
This column is applicable to scenarios where the number of menu items and the display name of menu items are not fixed in advance. You need to write the menu items to the database and update and maintain the database content. Read records from the database as needed and add them as menu items dynamically.
This column function: click "add Example 2" under "dynamic menu example" in the above dynamicmenu project to add a new dynamic menu "dynamic menu 2" at the end of the menu. the menu items are added by reading the Record Content in the database. Click each menu item to respond to the menu. 3.

Figure 3 running interface

 

Click the newly added menu item, and dynamically create a control based on the name of the menu item and the record content in the current database. For example, if the menu item is "text box" and the type field contype in the current record in the database is "text", a text box is dynamically created on the program running interface when you click this menu item. For example, in the "drop-down box", the Type field contype in the current record in the database is "select". Click this menu item to dynamically create a drop-down box on the program running interface.
Programming steps: Create a database. The records in the database are menu items in menu 2. When menu items are dynamically added, the IDs of menu items increase sequentially. The data volume of menu items is not fixed, the Response Code cannot be written in advance for the message response of each menu item, and a dynamic response function is required. Therefore, the function is classified and responded in the menu item response function based on the menu ID and the database record content.
Steps:
(1) Create an Access database menu with the table name dynamicmenu. Set the two fields in the table to myname and contype, and set the field types to "text". Add two records to the table: text box and text; drop-down box, select, 4. The following controls are dynamically created based on the value of contype, and the value of myname is used as the display content in the control.

Figure 4 table structure and data
(2) connect to the database in the dynamicmenu project.
Add the following connection code to the initinstance () of the dynamicmenu. cpp file:

 
Bool cdynamicmenuapp: initinstance (){... M_pconnection-> open ("provider = Microsoft. Jet. oledb.4.0; Data Source = menu. mdb", "", "", admodeunknown );... }

(3) set the global variable flag in cdynamicmenuview to determine whether "example menu 2" is added, and set the initial value to false in the constructor of cdynamicmenuview. The Code is as follows:

 
Cdynamicmenuview: cdynamicmenuview (): cformview (cdynamicmenuview: IDD) {// {afx_data_init (cdynamicmenuview) // note: the classwizard will add member initialization here //} afx_data_init // todo: Add construction code here flag = false ;}

(4) When you click the menu item "add Example 2 menu", read the records from the database and add them as dynamic menu items. After the menu is added successfully, set the flag to true, this makes it easy to judge the menu response.
Use MFC classwizard to add a message response function for the menu id_secmenu under cdynamicmenuview as follows:

Void cdynamicmenuview: onsecmenu () // read records from the database and add the dynamic menu item {cmenu menu; menu. createpopupmenu (); // create an empty menu getparent ()-> getmenu ()-> appendmenu (mf_popup, (uint) menu. m_hmenu, "dynamic menu 2"); // Add the menu to the end of the existing menu Int J = 8999; _ recordsetptrm_precordset; m_precordset.createinstance (_ uuidof (recordset )); try {m_precordset-> open ("select * From dynamicmenu", // query all fields in the demotable Table m_pconnection.getinterfaceptr (), // obtain the idispatch pointer adop of the database connected to the database Endynamic, adlockoptimistic, adw.text);} catch (_ com_error * E) {afxmessagebox (e-> errormessage ();} If (! M_precordset-> BOF) m_precordset-> movefirst (); else {afxmessagebox ("no record !! "); Return;} // read the record and add it as the menu item m_precordset-> movefirst (); While (! M_precordset-> adoeof) {J = J + 1; // The menu item ID increments by _ variant_tvar; Var = m_precordset-> getcollect ("myname "); // read record value cstring STR = VTOS (VAR); // Add as menu item menu. appendmenu (mf_string | mf_enabled | mf_checked, J, STR); m_precordset-> movenext ();} menu. detach (); getparent ()-> drawmenubar (); flag = true; // After the menu is added, set the menu item to add a flag to facilitate judgment in the menu message response}

(5) Add a menu item message response function.
MFC determines whether a command ID has a handler. The corresponding value is determined by onmongomsg (uint NID, int ncode, void * pextra, afx_cmdhandlerinfo * phandlerinfo) based on the returned value. The return value is true, indicating that a corresponding processing function exists. The return value is false, indicating that no processing function exists. The parameter NID is the ID of the sent message, and the menu is the menu ID. The parameter ncode is 0, indicating the command message. For example, click the message sent from the menu item, if the value is-1, it indicates that the message is update_command_ui. If the phandleinfo parameter is not null, it indicates that the message is being inspected. If it is null, it indicates that the command message is being routed and expected to be processed.
the on1_msg () function of cdynamicmenuview is reloaded because these dynamically added menu items need to be processed in cdynamicmenuview. Use calss Wizard to add the message response function on1_msg for cdynamicmenuview. The Code is as follows:

Bool identifier: on1_msg (uint NID, int ncode, void * pextra, afx_cmdhandlerinfo * phandlerinfo) {// todo: add your specialized code here and/or call the base classif (FLAG) // determine whether to add "example menu 2" {// obtain the total number of menu items in "example menu 2" int n = getparent ()-> getmenu ()-> getsubmenu (6) -> getmenuitemcount ()-1; if (0 = ncode) // determine whether it is a command message {// determine whether the menu ID currently clicked is within the range of the dynamic menu item if (getparent ()-> getmenu ()-> getsubmenu (6) -> getmenuitemid (0) <= NID & nid <= getparent ()-> getmenu ()-> getsubmenu (6)-> getmenuitemid (n )) {If (phandlerinfo = NULL) {cstring strmenuname; // menu item name getparent ()-> getmenu ()-> getmenustring (NID, strmenuname, mf_string ); // obtain the menu item name handler (strmenuname) according to the ID;} return true ;}}return cformview: on1_msg (NID, ncode, pextra, phandlerinfo );}

Handler (strmenuname) is the response code for clicking a custom menu item. The parameter is the name of the currently clicked menu item. The main code is as follows:

Void handler: handler (cstring strmenuname) {_ recordsetptr m_pset2; m_pset2.createinstance (_ uuidof (recordset); cstring strsql2 = "select * From dynamicmenu where myname = '"; strsql2 = strsql2 + strmenuname + "'"; if (m_pset2! = NULL) {If (m_pset2-> state) m_pset2-> close (); m_pset2 = NULL;} m_pset2.createinstance (_ uuidof (recordset )); try {m_pset2-> open (_ bstr_t) strsql2, // query all fields in the demotable Table m_pconnection.getinterfaceptr (), // obtain the idispatch pointer adopendynamic, adlockoptimistic, adshorttext);} catch (_ com_error e) {afxmessagebox ("the object database operation failed !! "); // Return NULL;} If (! M_pset2-> BOF) m_pset2-> movefirst (); else {MessageBox (strmenuname); afxmessagebox ("no matching object record exists !! "); // Return NULL;} cstring ctype = VTOS (m_pset2-> getcollect (" contype "); m_pset2-> close (); if (ctype = "") {CDC * PDC = getdc (); combox = new ccombobox; combox-> Create (ws_child | ws_visible | cbs_dropdown, crect (260 ), (80), (330), (100), this, 1999); combox-> setwindowtext (strmenuname);} else if (ctype = "text ") {CDC * PDC = getdc (); number = new cedit; number-> Create (ws_visible | ws_child | ws_border, crect (260), (40), (330 ), (60), this, 2000); // number-> movewindow (30), (80), (70), (20 )); // number-> showwindow (sw_show); number-> setwindowtext (strmenuname );}}

4. summary
two instances are used to dynamically generate menus in VC ++ 6.0. Section 3.2 is applicable to fixed menu items that need to be added. You need to create a menu item ID in advance, the response function is determined in advance and manually added. The modification involves code. Section 3.3 applies to scenarios where the number of menu items and the display name of menu items are not fixed and change frequently. You only need to write the menu items to the database to update and maintain the database content, this removes the hassle of re-editing application code when menu resources are changed.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.