Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

The Microsoft Foundation Class Library: Menus and Dialogs

0.00/5 (No votes)
10 Jul 2009 1  
An Article about the Basics of MFC Resources

Introduction

The purpose of this article is to explain how to use MFC menus and dialogs effectively and as such, assumes a basic knowledge of MFC. Anyone who works with MFC knows that the word “resource” appears often: resource editor, resource compiler, resource file, and resource script file. So then, maybe a good place to start is by defining a resource. Advanced MFC developers might find this content a little too basic and should therefore overlook it. In fact I do not write about MFC often for that very reason. If, however, this article can clarify a few foggy concepts about the world of MFC, then it could benefit those who prefer to develop applications on that particular framework. Typically in MFC, the CForm::View class interacts with the user. While it has limitations when it comes to controls, it still allows controls to be dragged and dropped onto a user interface based on document architecture rather than a dialog box. If you start an MFC project to build an MFC application, you should ensure that you check the “MFC Standard” build style radio button, the “Single Document” check box, and the “Use MFC as a Shared DLL” check box. Continue on with the settings, insert, say, fvd for the application extension, and choose FormView as the base class. Once you build it, you will find a document interface where you can drag and drop controls onto. To add a form to drag the controls onto, go to the resources tab, click the dialog item, and then click the IDD_FORMVIEW_FORM. Drag and drop two static text controls, and in the “caption” properties pane, write String&1 and String&2. Drag and drop two edit control boxes along side of the two previously dragged controls, and insert in their ID property pane: IDC_STRING1 and IDC_STRING2, respectively. Run the application, and note that you have controls on a document-architecture surface. This application has no functionality, but is meant to show how to place controls on a document-oriented surface. Note that this was built with the MFC 2008 Feature pack installed. The items like menus, dialogs, and controls, are called resources.

9.JPG

What is a Resource

A resource is anything other than code that is part of your program. This definition does not include data that your program might process. The two most commonly used resources are menus and dialog boxes. Others include bitmaps and icons that may appear on the face of a static or button control or in a toolbar. A bitmap is not code, but a location, so it should be easy to understand why it is called a resource. But why is menu considered to be a resource. Well, maybe the reason is that the menu seen below is based on a highly structured block of text that looks like this:

IDR_MENU1  MENU DISCARDABLE
BEGIN
  POPUP  “OptionA”
  BEGIN
     MENUITEM “A-1”,  ID_OPTIONA_A1
     MENUITEM “A-2”,  ID_OPTIONA_A2
   END
  POPUP  “OptionB”
  BEGIN
   MENUITEM  “B-1”, ID_OPTIONB_B1     ID_OPTIONB_B1
   MENUITEM  “B-2”, ID_OPTIONB_B2     ID_OPTIONB_B2
   MENUITEM  “B-3”, ID_OPTIONB_B3     ID_OPTIONB_B3
  END
MENUITEM “Clear”,       ID_CLEAR
END

1.JPG

11.JPG

The above blocks of text code were created with Visual Studio 2008 Menu Editor, which will be discussed shortly. Consider the image below:

2.JPG

The dialog box appear upon the event of clicking the ShowDialog menu item. When that second dialog box is closed, then we have this image:

3.JPG

A Dialog Resource

IDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 146, 47
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter information"
FONT 8, "MS Sans Serif"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,89,7,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,89,26,50,14
    RTEXT           "Name",IDC_STATIC,7,7,22,12,SS_CENTERIMAGE
    RTEXT           "Age",IDC_STATIC,7,27,21,13,SS_CENTERIMAGE
    EDITTEXT        IDC_NAME,35,7,39,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_AGE,35,28,23,12,ES_AUTOHSCROLL
END

The above file is a resource script. The two blocks of text shown would be put in separate files. But usually in MFC, all of the resource files are kept in one file called the Resource Script file. If you want to get a better feel for the Resource Script file, then examine the Resource.h header file. The text blocks describe the resource information – the menu and the dialog. If you examine the header file, you will locate some identifiers like IDC_NAME_CLEAR. All identifiers must be associated with an integer. Preprocessor defines, like #defines ID 304, and is maintained in the resource file:

 //{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by MyResScript.rc
//
#define IDR_MENU1                       101
#define ID_OPTIONA_A1                   40001
#define ID_OPTIONA_A2                   40002
#define ID_OPTIONB_B1                   40003
#define ID_OPTIONB_B2                   40004
#define ID_OPTIONB_B3                   40005
#define ID_CLEAR                        40006

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40007
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

To clarify, the first three letters give us an idea of the type of item being identified:

  • IDC_NAME “C” stands for control identifier
  • IDD_xx “D” stands for dialog identifier
  • ID_xx no 3rd letter means menu identifier
  • IDR_xx “R” stands for menu resource

When Visual Studio is used to create menu and dialog resources, it creates and then maintains the resource.h file. You may have to examine the list of identifiers simply because you have to use them in program statements. In the Resource View pane of the container, right-click the resource_script.rc file and select “View Symbols”:

5.JPG

The menu is connected to the window when the window is first created. In the CMainFrame constructor, the 6th parameter of the Create() function -- MAKEINTRESOURCE (IDR_MENU1) – makes the connection:

// MainFrame.CPP Ex08a_Menu
#include "MainFrame.h"

#include "resource.h" // note

 
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  ON_WM_PAINT()
  ON_COMMAND (ID_OPTIONA_A1, DoOptionA1)
  ON_COMMAND (ID_OPTIONA_A2, DoOptionA2)

  ON_COMMAND_RANGE (ID_OPTIONB_B1,
                    ID_OPTIONB_B3,
                            DoOptionB)

  ON_COMMAND (ID_CLEAR,      DoClear)
END_MESSAGE_MAP()

CMainFrame::CMainFrame()
{ 
  Create ( NULL,"Ex08a First Menu",
            WS_OVERLAPPEDWINDOW,
             CRect(0,0,280,200),
             NULL,
               MAKEINTRESOURCE (IDR_MENU1)
         );
}

void CMainFrame::OnPaint()
{
  CPaintDC dc (this);
}

void CMainFrame::DoOptionA1()
{
  CClientDC  dc(this);
  dc.TextOut (10,10,"Option A1");
}

void CMainFrame::DoOptionA2()
{
  CClientDC  dc(this);
  dc.TextOut (10,10,"Option A2");
}

void CMainFrame::DoOptionB(UINT nID)
{
  CClientDC  dc(this);
  switch (nID)
  {
  case ID_OPTIONB_B1:
     dc.TextOut (10,10,"Option B1");
     break;
  case ID_OPTIONB_B2:
     dc.TextOut (10,10,"Option B2");
     break;
  case ID_OPTIONB_B3:
     dc.TextOut (10,10,"Option B3");
     break;
  default:
    break;
  }
}

void CMainFrame::DoClear()
{
  Invalidate();
}

Now the menu item requires mouse clicking in order to call a function designed to handle the “menu item selection” message. The task of converting an event message into a function call – to the appropriate function to handle the message – is taken care of by the message map. A message map is a macro that the preprocessor translates. If we want our program to handle the “Left button down” event, the OS will send our window the WM_LBUTTONDOWN message. Thus we put in the line:

ON_WM_LBUTTON_DOWN

between the BEGIN and END_MESAGE_MAP() lines. Now when our program receives a WM_LBUTTON_DOWN message, MFC will make sure that the:

void  OnLButtonDown   (  UINT  nFlags,  .. ) 

function is called. So what happens when a user presses a character? Well, MFC receives the WM_CHAR message. So we put ON_WM_CHAR() on the message map. Examine the image below. We are in the class view, and notice the box to the right of the lightning mark. You'll see that WM_LBUTTON_DOWN message darkened. Clicking the drop down arrow gives us the function code: this is where we place the handler code. It is similar to double-clicking a control on a Window Forms or ASP.NET 2.0 designer UI.

8.JPG

Having said that again, the clicking of our menu item also calls a function designed to handle the message. So for this to happen, specific entries must be put into the CMainFrame Message map. In the first form, each menu item invokes a specific function. For example, consider the following two entries:

ON_COMMAND (ID_OPTIONA_A1, DoOptionA1)
ON_COMMAND (ID_OPTIONA_A2, DoOptionA2)

When menu item A-1 is selected, which has the identifier ID_OPTIONA_A1, the function DoOptionA1() is invoked. Note that of all of the files shown thus far, “Resource.h” and “MyResScript.rc” were created by Visual Studio. Download the files and extract them into a newly made directory. Double-click the project file and then build the solution. When the solution is built, select “run without debugging”. Below are all of the files involved in this basic dialog box:

// MainFrame.h
#include 


class CMainFrame : public CFrameWnd
{
private:

public:
  CMainFrame();

  CMenu   menu;

  afx_msg void OnPaint ();
  afx_msg void DoOptionA1();
  afx_msg void DoOptionA2();
  afx_msg void DoOptionB(UINT nID);

  afx_msg void DoClear();
  
  DECLARE_MESSAGE_MAP()
};

And:

// MyWinApp.h
#include 


class CMyWinApp : public CWinApp
{
public:
  virtual BOOL InitInstance();
};

Its implementation is as follows:

// MyWinApp.cpp

#include "MyWinApp.h"

#include "MainFrame.h"


BOOL CMyWinApp::InitInstance()
{
  CMainFrame* pFrame = new CMainFrame;
  m_pMainWnd = pFrame;    // a CWinApp member variable 

  pFrame->ShowWindow(SW_SHOW);
  pFrame->UpdateWindow(); // generates WM_PAINT msg

  return TRUE;
}

The Student Information application is meant to show how a dialog box can be invoked in order to obtain user input to then have it displayed on the screen. The structure of the document interface and View is different from that first application, because only the basic principles of MFC were used to build that application. Unzip it to a newly-made folder, double-click the project file, build it, and then use it. Note that these projects are build using MFC "As a Static DLL". When you build an MFC application using the setting "Use MFC as a Static DLL", your application becomes larger than that of using MFC as a Shared DLL because of the fact that you are building the static DLL into the application.

History

  • 11th July, 2009: Initial post 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here