Top Banner
MFC Tutorial Part 1 - Creating a Window MFC provides really nice classes for doing windows programming. It has taken away all the pains of SDK, where a programmer is expected to handle everything in the world except writing for application logic. It used to be such a big pain, that people hated SDK so much and lots of them shifted to VB development. This series of MFC Tutorial articles, will try to cover some of the basics for a good start in MFC Programming. The first task to be done in any application is to create a window for an application. MFC provides two important classes viz. CWinApp & CFrameWnd, which can be used for creating a window & the application. Both these classes have their own message handling mechanisms, screen-drawing functions etc., To be precise, CWinApp provides the application level functionalities and CFrameWnd provides the functionalities related to GUI. All these classes are derived from CCmdTarget which in turn is derived from CObject. CCmdTarget is created with the capability to handle windows messages, which is referred as Message Maps. If you wonder what this Message map means, "Message maps are macros which take care of the event handling". This topic will be dealt in the next part of ourMFC Tutorial (Part 2). The CWinApp class has an important over-ridable function InitInstance which handles the Window creations. The next important one is a data member, m_pMainWnd (of CWinApp) which holds the pointer to the window. Let's write an example and try to understand it. Follow these steps to create an application with minimal usage wizard. The wizard will be used just to create a simple workspace for this MFC Tutorial. Step1: Create a new project of type Win32 application. In the second screen of the wizard, select the first option. Do not allow the wizard to add any files. Step 2: After the project is created, click on Menu -->Project --> Add to Project -->New and select a .cpp file and give a name to it. Step 3: Copy and paste the code below. //MFC1.CPP - MFC Tutorial Part 1 from codersource.net #include <afxwin.h> class MFC_Tutorial_Window :public CFrameWnd
64

MFC Tutorial

Nov 03, 2014

Download

Documents

MFC Tutorial
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: MFC Tutorial

MFC Tutorial Part 1 - Creating a Window   

  MFC provides really nice classes for doing windows programming. It has taken away all the pains of SDK, where a programmer is expected to handle everything in the world except writing for application logic. It used to be such a big pain, that people hated SDK so much and lots of them shifted to VB development.   This series of MFC Tutorial articles, will try to cover some of the basics for a good start in MFC Programming.

    The first task to be done in any application is to create a window for an application. MFC provides two important classes viz. CWinApp & CFrameWnd, which can be used for creating a window & the application. Both these classes have their own message handling mechanisms, screen-drawing functions etc., To be precise, CWinApp provides the application level functionalities and CFrameWnd provides the functionalities related to GUI.

    All these classes are derived from CCmdTarget which in turn is derived from CObject. CCmdTarget is created with the capability to handle windows messages, which is referred as Message Maps. If you wonder what this Message map means, "Message maps are macros which take care of the event handling". This topic will be dealt in the next part of ourMFC Tutorial (Part 2).

     The CWinApp class has an important over-ridable function InitInstance which handles the Window creations. The next important one is a data member, m_pMainWnd (of CWinApp) which holds the pointer to the window.

    Let's write an example and try to understand it.    Follow these steps to create an application with minimal usage wizard. The wizard will be used just to create a simple workspace for this MFC Tutorial.

Step1:    Create a new project of type Win32 application. In the second screen of the wizard, select the first option. Do not allow the wizard to add any files. Step 2:     After the project is created, click on Menu -->Project --> Add to Project -->New and select a .cpp file and give a name to it.Step 3:    Copy and paste the code below. 

//MFC1.CPP - MFC Tutorial Part 1 from codersource.net

#include <afxwin.h>

class MFC_Tutorial_Window :public CFrameWnd{public:    MFC_Tutorial_Window()    {         Create(NULL,"MFC Tutorial Part 1 CoderSource Window");    }};

class MyApp :public CWinApp{   MFC_Tutorial_Window *wnd; public:

Page 2: MFC Tutorial

   BOOL InitInstance()   {        wnd = new MFC_Tutorial_Window();        m_pMainWnd = wnd;        m_pMainWnd->ShowWindow(1);        return 1;     }};

MyApp theApp;

//End of program MFC Tutorial Part 1

Step 4:   Now compile the application. It will generate linker errors. The reason is because the MFC libraries are not yet linked.    Do the last step of this MFC Tutorial.Step 5:Select Menu -->Project --> Settings and General tab. On the first combo box "Microsoft Foundation classes" and select "Use MFC in shared dll".   Now compile and run the program.

   This MFC Tutorial example creates a simple Window with a title called "MFC Tutorial Part 1 CoderSource Window". The window has no contents, menu or any other controls.    The next part of this MFC Tutorial series will handle the left out topics one by one.

MFC Tutorial Part 2 - Message Maps   

    This article is the next step after MFC Tutorial Part 1 which dealt with a simple task of creating a window. This part tries to cover the details about Message Map.   Message Maps are the way by which MFC handles the Application messages. Any class which is derived from CCmdTarget is a candidate for handling messages. Previously in win32 SDK, a programmer is supposed to handle all messages posted to the message loop. The application he wrote should have a function to handle the messages and do the actions according to the commands passed to it. To the relief of all MFC has relieved the programmers from all these pains and allows programmers just to restrict themselves with the functionality implementations.

  Let's look at some sample code to understand the basics of this message maps.

Step1:    Create a new project of type Win32 application. In the second screen of the wizard, select the first option. Do not allow the wizard to add any files. 

Step 2:     After the project is created, click on Menu -->Project --> Add to Project -->New and select a .cpp file and give a name to it.

Step 3:    Copy and paste the code below. 

//MFC2.CPP - MFC Tutorial Part 2 from CoderSource.net

#include <afxwin.h>

Page 3: MFC Tutorial

class MFC_Tutorial_Window :public CFrameWnd{public:    MFC_Tutorial_Window()    {        Create(NULL,"MFC Tutorial Part 2 CoderSource Window");    }    void OnLButtonDown(UINT nFlags, CPoint point);    DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)      ON_WM_LBUTTONDOWN() //Macro to map the left button click to the handlerEND_MESSAGE_MAP()

void MFC_Tutorial_Window::OnLButtonDown(UINT nFlags, CPoint point) {    // TODO: Add your message handler code here and/or call default   CFrameWnd::OnLButtonDown(nFlags, point);   MessageBox("Left Button clicked");}

class MyApp :public CWinApp{     MFC_Tutorial_Window *wnd;?public:     BOOL InitInstance()     {         wnd = new MFC_Tutorial_Window();         m_pMainWnd = wnd;         m_pMainWnd->ShowWindow(1);         return 1;     }};

MyApp theApp;

//End of program 

    The changes/additions to the previous code are highlighted in bold colors. There are only 4 additional macros which are used here.

DECLARE_MESSAGE_MAP:    This tells the application that the class in which this is called is going to have a message map and handle messages. A class can have only one message map. Also a class will be eligible to execute a message map if it is derived from CCmdTarget or a class which is derived from CCmdTarget. 

BEGIN_MESSAGE_MAP & END_MESSAGE_MAP:    This macro takes two parameters. The class name which implements the message map and the base class for it. It then is succeeded by the macros which represent messages viz., ON_WM_LBUTTONDOWN, ON_WM_SIZE etc., It is then closed by END_MESSAGE_MAP(3rd Macro).

Page 4: MFC Tutorial

ON_WM_LBUTTONDOWN:    This is the macro which declares that the MFC_Tutorial_Window is going to handle Left button clicks and the function which will handle this is OnLButtonDown(UINT nFlags, CPoint point). When there is any click related to this class, the mentioned function will be called automatically with the specific parameters. This is how all the messages are handled.

   Compile and execute this program. Do not forget to include MFC Library Project --> Settings --> General tab --> Microsoft Foundation classes combo and select "Use MFC in shared dll".

After running this MFC_Tutorial_Window, if you click using the left mouse button, a message box will be displayed.

 

MFC Paint Brush   

    This MFC Tutorial part 3 deals with the task of creating a simple paint brush application. This program will draw a line when the left mouse button is clicked and dragged. This will stop drawing the line when the left mouse button is released.    This MFC Tutorial application creates a window by using the class CFrameWnd, and also uses Message map. When the left mouse button is clicked, the application stores the window co-ordinates in the variable called m_StartPoint of typeCPoint. When the mouse button is released it keeps the mouse up co-ordinates in the variable m_EndPoint of the sameCPoint type. 

 

    The CPoint in this MFC Tutorial is a class which has a data member of type struct POINT and some other member functions. This struct POINT has two members which store the x and y co-ordinates of the particular point. This MFC Tutorial Application moves to the m_StartPoint and then draws a line till m_EndPoint. The function CClientDC::MoveTo is used for moving to a particular co-ordinate and CClientDC::LineTo is used for drawing the line.    This leaves us with the discussion about CClientDC. There is a concept in windows programming, called Device Contextin windows. This is used in conjunction with the outputs. This device context (DC) can direct the outputs to the screen or to the printer. The root class for device contexts is CDC. The classes like CClientDC, CPaintDC, CMetaDC are all derived from this CDC class. The applications have to write their formatted outputs to the device context and the DC will take care of writing it to the screen or to the printer.Steps for creating the MFC Tutorial 3 (MFC paint brush application):

Step1:Create a new project of type Win32 application. In the second screen of the wizard, select the first option. Do not allow the wizard to add any files.?

Step 2:?After the project is created, click on Menu -->Project --> Add to Project -->New and select a Source File(.cpp) option and give a name?to the file.

Step 3:  Copy and paste the code below into the newly created source file.? 

//MFC_Tutorial_3.CPP - MFC Tutorial Part 3 from CoderSource.net

#include <afxwin.h>

class MFC_Tutorial_Window :public CFrameWnd

Page 5: MFC Tutorial

{     CPoint m_StartPoint, m_EndPoint;     public:     MFC_Tutorial_Window()     {          Create(NULL,"MFC Tutorial Part 2 CoderSource Window");     }     void OnLButtonDown(UINT nFlags, CPoint point);     void OnLButtonUp(UINT nFlags, CPoint point);     DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)     ON_WM_LBUTTONDOWN() //Macro to map the left button click to the handler     ON_WM_LBUTTONUP() //Macro to map the left button click to the handlerEND_MESSAGE_MAP()

void MFC_Tutorial_Window::OnLButtonDown(UINT nFlags, CPoint point) {     // TODO: Add your message handler code here and/or call default

     CFrameWnd::OnLButtonDown(nFlags, point);     m_StartPoint = point;}

void MFC_Tutorial_Window::OnLButtonUp(UINT nFlags, CPoint point) {     // TODO: Add your message handler code here and/or call default

     CFrameWnd::OnLButtonDown(nFlags, point);     m_EndPoint = point;     CClientDC dc(this);     dc.MoveTo(m_StartPoint);     dc.LineTo(m_EndPoint);}

class MyApp :public CWinApp{     MFC_Tutorial_Window *wnd;     public:     BOOL InitInstance()     {           wnd = new MFC_Tutorial_Window();           m_pMainWnd = wnd;           m_pMainWnd->ShowWindow(1);           return 1;      }};

MyApp theApp;

//End of MFC_Tutorial_3.CPP

There are some disadvantages in this application.1. If the application window is resized, maximized, minimized all the lines drawn are gone.

Page 6: MFC Tutorial

2. Also if we drag the mouse like drawing a curve, it will still draw a straight line.  These problems will be solved by using a device context class called CMetaFileDC.

MFC Menus   

    Menu programming is the next step to be learnt in MFC after learning message maps. MFC provides two ways of programming menus. One is by using the resource option and the second is by using the dynamic menu option. This part of MFC Tutorial discusses about the Resource option.     The following steps will explain how to add a menu to this MFC Tutorial application.

    Step 1:        Create the project with out adding any files by selecting "Empty project" option.    Step 2:        After the project gets created, click on Project --> Add To Project --> New and select SourceFile (.cpp File) option. Give any name to the file and click OK.

    Step 3:        Copy the previous MFC Tutorial 2 code. Do not forget to choose the MFC Library by clicking Menu --> Project --> Settings --> General --> Microsoft Foundation Classes as "Use MFC as Shared Library".    Step 4:         Choose Menu --> Insert --> Resource. Select Menu from the list of resources. Click "New" and create one popup item as "File" and one menu item under this "File" as "New". Press enter on this "New" menu item and open the properties. Enter IDM_FILE_NEW as the menu resource ID in the resource id box. Press the Enter key again.    Step 5:         A new resource file will be created. Save this resource file.     Step 6:        Click Project --> Add To Project --> Files and select the two new filesScript1.rc and resource.h.    Step 7:         Now add the highlighted code into the project at the appropriate places. This code shows you how to 

load the menu resource into a CMenu class set the menu to the window writing handlers for the menu items.

//MFC_Tutorial_5.cpp

#include <afxwin.h>#include "resource.h"

class MFC_Tutorial_Window :public CFrameWnd{    CMenu menu1;public:    MFC_Tutorial_Window()    {

Page 7: MFC Tutorial

        Create(NULL,"MFC Tutorial Part 1 CoderSource Window");        menu1.LoadMenu(IDR_MENU1);        SetMenu(&menu1);    }    void OnFileNew();

    DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)    ON_COMMAND(IDM_FILE_NEW,OnFileNew)END_MESSAGE_MAP()

void MFC_Tutorial_Window::OnFileNew(){    MessageBox("Clicked File->New");}class MyApp :public CWinApp{    MFC_Tutorial_Window *wnd;public:    BOOL InitInstance()    {        wnd = new MFC_Tutorial_Window();        m_pMainWnd = wnd;        m_pMainWnd->ShowWindow(1);        return 1;    }};

MyApp theApp; 

Please find the sample code for this mfc tutorial here

MFC Tutorial Part 5 - Dialog Boxes   

    Application programs in any language need some interactive screens to give inputs and obtain outputs. All windows based GUIs will definitely use dialogs for such user interactions. This part of our MFC Tutorial deals with the Dialog boxes in MFC.

    Dialog Box handling is done using CDialog class in MFC. CDialog is a CWnd derived class with some extra facilities for dialog handling. The initialization of the dialog is done using an over-ridable function OnInitDialog. The dialogs are closed by calling the function EndDialog. The dialogs can accommodate a lot of controls like an Edit controls, static controls, list boxes, combo boxes, progress bars, list views, tree views and many more. 

 

Page 8: MFC Tutorial

    All the above mentioned controls have their own classes for handling themselves. All of them including dialog box, also have their own message handling mechanisms involving message maps. They all are treated as window/s, except with some special characteristics.

    Let us see a step by step procedure for adding a dialog box to our application in this MFC Tutorial. This tutorial needs the knowledge of Creating a window MFC Tutorial part I and Menu creation as in MFC

Tutorial Part IV.

Two types of dialogs can be created in MFC. They are.      1. Modal Dialogs      2. Modeless dialogs

This MFC Tutorial example demonstrates the creation of Modal dialogs.

Step1:    Create a new project of type Win32 application. In the second screen of the wizard, select the first option "Create an empty project". Do not allow the wizard to add any files.?

Step 2:?    After the project is created, click on Menu -->Project --> Add to Project -->New and select a .cpp file and give a name?to it.

Step 3:    Copy and paste the code below.?

//MFC5.CPP - MFC Tutorial Part 5 from CoderSource.net

#include <afxwin.h>

class MFC_Tutorial_Window :public CFrameWnd{    public:    MFC_Tutorial_Window()    {        Create(NULL,"MFC Tutorial Part 5 CoderSource Dialog");    }    DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)

END_MESSAGE_MAP()

class MyApp :public CWinApp{    MFC_Tutorial_Window *wnd;?public:

Page 9: MFC Tutorial

    BOOL InitInstance()    {        wnd = new MFC_Tutorial_Window();        m_pMainWnd = wnd;        m_pMainWnd->ShowWindow(1);        return 1;    }};

MyApp theApp;

//This code snippet has the capacity to create a window

    Now we have to add the dialog resource and then add the necessary code for it

Step 4:     Click on the Menu --> Insert --> Resource --> "Dialog" and click New  command button. A default dialog will be created with two command buttons. 

Step 5:    On the left hand side, on the Resouces view if the Dialog tree is expanded, the resource id of the newly created dialog will be displayed. Just press Enter key on the dialog box and change the dialog id to IDR_MYDIALOG.

Step 6:    Save the resource. It will give a file name as script1.rc. Just take care that you save it to the path of your project. 

Step 7:    Now click on Menu --> View --> Class Wizard or press Ctrl + W. You will be presented with a dialog asking you, if you want to create a new class. Say Yes. The wizard will create a new dialog class and related files( Newdialog.h & newdialog.cpp) for you. 

Step 8:    Open the header file of your new dialog "NewDialog.h" and add the include directive for <afxwin.h>. Also add the "NewDialog.h" include directive to your project's MFC5.cpp file that you have created in the beginning.

Step 9:    Create a menu resource and add the following code as highlighted in bold letters as follows.

//MFC5.CPP - MFC Tutorial Part 5 from CoderSource.net

#include <afxwin.h>#include "resource.h"#include "newdialog.h"

class MFC_Tutorial_Window :public CFrameWnd

Page 10: MFC Tutorial

{public:    MFC_Tutorial_Window()    {        Create(NULL,"MFC Tutorial Part 5 CoderSource Dialog");    }    void OnClickDialogNew();    DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)    ON_COMMAND(ID_MYDIALOG,OnClickDialogNew)END_MESSAGE_MAP()

void MFC_Tutorial_Window::OnClickDialogNew(){    NewDialog dlg;    dlg.DoModal();}

class MyApp :public CWinApp{    MFC_Tutorial_Window *wnd;?public:    BOOL InitInstance()    {        wnd = new MFC_Tutorial_Window();        m_pMainWnd = wnd;        m_pMainWnd->ShowWindow(1);        return 1;    }};

MyApp theApp;

    Now, if the menu item is clicked, the dialog will be shown with the two default buttons. If either the Enter key or the escape key is pressed, the dialog will be closed. Please find the sample code here. Read here for knowing how to avoid closing the dialog when ENTER or ESCAPE key is pressed.

Modeless Dialog Boxes in MFC   

    The previous tutorial dealt with the Creation of Modal Dialog boxes in MFC. This part of our Tutorial deals with the Creation of Modeless Dialog boxes in MFC. 

    The difference between a modal and modeless dialog box is that, modal dialogs once invoked will not allow the users to access the parent window, where as modeless dialogs will allow the user to work with the parent window. A user cannot enter inputs in any other dialog or invoke a menu option except without explicitly closing the modal dialog, within the application. But the user can leave the modeless dialog open and do anything after the modless dialog is invoked.

Page 11: MFC Tutorial

 

    Modeless Dialog Box handling also is done using CDialog class in MFC. CDialog is a CWnd derived class with some extra facilities for dialog handling. The initialization of the dialog is done using an over-ridable function OnInitDialog. The dialogs are closed by calling the function EndDialog. The dialogs can accommodate a lot of controls like Edit controls, static controls, list boxes, combo boxes, progress bars, list views, tree views and many more. 

    All the above mentioned controls have their own classes for handling themselves. All of them including dialog box, also have their own message handling mechanisms involving message maps. They all are treated as window/s, except with some special characteristics.

    Let us see a step by step procedure for adding a modeless dialog box to our application in this MFC Tutorial. If you look at the above explanation above, it is simply a copy paste of the Modal dialog handling. As such the above code of handling the controls inside a dialog is exactly the same as in Modal dialogs. It is only the way of calling/invoking the dialog which is different. Similar to the previous Modal dialog MFC

Tutorial, this tutorial also needs the knowledge of Creating a windowMFC Tutorial part I and Menu creation as in MFC Tutorial Part IV. 

The sample code and description below demonstrates the creation of Modeless dialogs in MFC.

Step1:    Create a new project of type Win32 application. In the second screen of the wizard, select the first option "Create an empty project". Do not allow the wizard to add any files. 

Step 2:     After the project is created, click on Menu -->Project --> Add to Project -->New and select a .cpp file and give a name to it.

Step 3:    Copy and paste the code below. 

//MFC6.CPP - Modeless Dialogs in MFC from CoderSource.net 

#include <afxwin.h>

class MFC_Tutorial_Window :public CFrameWnd{    public:    MFC_Tutorial_Window()    {        Create(NULL,"MFC Tutorial Part 6 - Modeless Dialog Box");    }    DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)

END_MESSAGE_MAP()

Page 12: MFC Tutorial

class MyApp :public CWinApp{    MFC_Tutorial_Window *wnd; public:    BOOL InitInstance()    {        wnd = new MFC_Tutorial_Window();        m_pMainWnd = wnd;        m_pMainWnd->ShowWindow(1);        return 1;    }};

MyApp theApp;

//This code snippet has the capacity to create a window

    Now we have to add the dialog resource and then add the necessary code for it

Step 4:     Click on the Menu --> Insert --> Resource --> "Dialog" and click New  command button. A default dialog will be created with two command buttons. 

Step 5:    On the left hand side, on the Resources view if the Dialog tree is expanded, the resource id of the newly created dialog will be displayed. Just press Enter key on the dialog box and change the dialog id to IDR_MYDIALOG.

Step 6:    Save the resource. It will give a file name as script1.rc. Be careful to save it to the path of your project. 

Step 7:    Now click on Menu --> View --> Class Wizard or press Ctrl + W. You will be presented with a dialog asking you, if you want to create a new class. Say Yes. The wizard will create a new dialog class and related files( Newdialog.h & newdialog.cpp) for you. 

Step 8:    Open the header file of your new dialog "NewDialog.h" and add the include directive for <afxwin.h>. Also add the "NewDialog.h" include directive to your project's MFC5.cpp file that you have created in the beginning.

Step 9:    Create a menu resource and add the following code as highlighted in bold letters as follows.

//MFC5.CPP - MFC Tutorial Part 5 from CoderSource.net

#include <afxwin.h>#include "resource.h"#include "newdialog.h"

Page 13: MFC Tutorial

class MFC_Tutorial_Window :public CFrameWnd{public:    MFC_Tutorial_Window()    {        Create(NULL,"MFC Tutorial Part 6 - Modeless Dialog Box");    }    void OnClickDialogNew();    DECLARE_MESSAGE_MAP()};

BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)    ON_COMMAND(ID_MYDIALOG,OnClickDialogNew)END_MESSAGE_MAP()

void MFC_Tutorial_Window::OnClickDialogNew(){    NewDialog *dlg;    dlg = new  NewDialog;    dlg->Create(IDR_MYDIALOG);    dlg->ShowWindow(1);}

class MyApp :public CWinApp{    MFC_Tutorial_Window *wnd; public:    BOOL InitInstance()    {        wnd = new MFC_Tutorial_Window();        m_pMainWnd = wnd;        m_pMainWnd->ShowWindow(1);        return 1;    }};

MyApp theApp;

    Now, if the menu item is clicked, the dialog will be shown with the two default buttons. If either the Enter key or the escape key is pressed, the dialog will be closed. Please find the sample code for this article here. Read here for knowinghow to avoid closing the dialog when ENTER or ESCAPE key is pressed. 

Command Buttons in MFC Dialogs   

   The next step after learning Dialog box creation in MFC, are the controls. This article deals with the Command Button control. We'll look at how to use the CButton class in case of the command button controls. This article assumes the user has familiarity with the basic Windows controls. This MFC Tutorial only concentrates on how to manipulate them using MFC.

   Before using the controls, we need to have our base application with a dialog box for this MFC Tutorial. This dialog box will be the container to hold the controls. At least from now on (for easier learning), the Codersource MFC Tutorial articles will start using the wizard to create the base application. 

Page 14: MFC Tutorial

 

To Create the Application:    1. Open the Microsoft Visual Studio 6.00. Click Menu--> File--> New and Select MFC AppWizard(exe) option.    2. In the next MFC AppWizard screen - Step 1, Choose Dialog based application.    3. Click Finish after selecting this. All the files needed for this MFC Tutorial will be created.    4. If the project is built and run, it will open a dialog box, with two command buttons and one static display control.    5. Close the application and come back to the Microsoft Visual studio.

   The application created in the above steps of this MFC Tutorial will be used to add and use the controls.

   The wizard has already created two command buttons with captions OK and Cancel. The wizard has created two automatic handlers for each one of the buttons. When we click them, it just closes the dialog. Delete these two command buttons and the static control. We'll create our own command buttons in our MFC Tutorial.

Adding the command Button:    1. Open the dialog box. There must be a controls tool box appearing on the sides. Click on the command button control and Click on the dialog box, where you want to place the button.     2. The button is placed in the dialog box and its caption is set to "Button1" by default.    3. Click the mouse on the Button and Press Enter key.    4. A Property sheet will appear, showing all the properties of the button.    5. Change the ID to IDC_MYBUTTON and change the caption to "My Button".    6. Now Press the Ctrl+W keys to invoke the class wizard.    7. Ensure that you are in the Message Maps tab.    8. Ensure that the Top right side combo (class name) contains the CMFC_Tutorial_7 class. If you have named your application with a different name, it should have "yourapplicationdlg" selected.    9. Select the IDC_MYBUTTON on the left hand side and BN_CLICKED on the right handside of the dialog. Then click "Add Function". Say ok to the dialog which appears eventually.   10. If you look at the list box down, it will have Onmybutton ON_IDC_MYBUTTON:BN_CLICKED inside the list. Click on Edit Code. This will lead to the MFC_Tutorial_7Dlg.cpp.    11. The following function will be created in this file.

    void MFC_Tutorial_7Dlg::OnMybutton()     {        // TODO: Add your control notification handler code here        MessageBox("My Button Clicked");    }

    12. Add a line "MessageBox("My Button Clicked");" inside the function as highlighted above.     13. Now build and run the application.    14. We'll see the dialog with "My Button" command button placed on the dialog. Click on the button, we'll see a message box.

Page 15: MFC Tutorial

  The subsequent articles in this MFC Tutorial will deal with the other controls in MFC. Please find the Sample code here.

Check Box Usage   

   Check boxes are used to check binary states. Yes or No answers, Male/Female kind of conditional user interface inputs are easier with a check box. This part of Codersource MFC Tutorial explains how to use a Check box in dialog box applications of MFC.

Check box:

   There are quite a few techniques to be learnt with all the MFC Controls. Some of them related to the Check Box control are

Handling of Messages ( Mouse Click, Double Click etc) Getting and Setting check box values DDX mechanism

   The first job for this MFC tutorial will be to create the MFC Dialog based Application. This application will be used to hold the check boxes. This is the same set of code/steps which are used for the MFC Tutorials explaining about the controls.

To Create the Application:

1. Open the Microsoft Visual Studio 6.00. Click Menu--> File--> New and SelectMFC AppWizard(exe) option.

2. In the next MFC AppWizard screen - Step 1, Choose Dialog based application.3. Click Finish after selecting this. All the files needed for this MFC Tutorial will be created.4. If the project is built and run, it will open a dialog box, with two command buttons and one static

display control.5. Close the application and come back to the Microsoft Visual studio.

Adding a check box:   The above application and dialog box will be used for handling check box in the tutorial. The following steps explain how to add a check box for this MFC Tutorial:

1. Open the dialog editor of the previously created application.2. Click on the check box from the controls toolbox and place two checkboxes on the dialog.3. Open the properties dialog of the check box. This is done by first selecting the check box and

pressing the "Enter" key.4. Rename the ID of one of the check boxes as IDC_FIRSTCHECKBOX and the caption as "First

check box"5. Rename the second one's ID as IDC_SECONDCHECKBOX and the caption as Second Check

Box.

   Now we'll look at the different ways of manipulating the check boxes.Event Handling:

   Check box can handle the Mouse Click and Double click events. Let us see how to trap the Mouse click events for the check box.

Page 16: MFC Tutorial

Use our previously created application for this MFC Tutorial now. Open the dialog box and Select the "First Check box" control.

Press the keys Ctrl + W On the Message Maps tab, select IDC_FIRSTCHECKBOX on the Object ID list box and

BN_CLICKED on theMessages list box. Click on Add Function After creating the function, click on the Edit code button. We'll be taken to the implementation of

the click message of the check box. Add a line for invoking a message box. You can use the following code indicated in bold.

 

void CMfc_tutorial_8Dlg::OnFirstcheckbox() {         // TODO: Add your control notification handler code here         MessageBox ("First Check box Clicked");}

Build the application and Run it. If you click on the check box, you should see a message box.

Manipulating the check box:

   A Check box can return a value ofTrue or False. Let's add a Command Button to get the values of check box.

Open the dialog editor. Add a Command Button with a caption "Get Second Box". Name the id with IDC_GETSECONDCHECKBOXVAL.

Press Ctrl+W and create a BN_CLICKED handler for it. On the Message Maps tab, Select IDC_GETSECONDCHECKBOXVAL on theObject ID and select the BN_CLICKED Message. Click on Add functionwith a function name as OnGetSecondBox and add the handler.

On the Member Variables tab, select IDC_SECONDCHECKBOX and click on the "Add Variable". Give the name of the variable asm_ctlSecondCheckBox. On the Category combo, choose Control and theVariable Type will be automatically selected as CButton.

   Now open the "mfc_tutorial_7dlg.cpp" (in your case "YourApplicationNameDlg.cpp") and look for the OnGetSecondBox()function. Add the following code to it.

    void CMfc_tutorial_8Dlg::OnGetSecondBox()     {            // TODO: Add your control notification handler code here           CString l_strCheckBoxVal;           int l_ChkBox = m_ctlSecondCheckBox.GetCheck();           l_strCheckBoxVal.Format("Second Check Box Value : %d",l_ChkBox);           MessageBox(l_strCheckBoxVal);     }

Page 17: MFC Tutorial

   If the Second Check Box  is checked, then the message box will display the string as "Second Check Box Value : 1". If not, it will display the string as "Second Check Box Value : 0". That means, the GetCheck function returns 1 if the control is checked and 0 if it is not.   The variable that we use is m_ctlSecondCheckBox , which was created earlier using the Member variable tab of the class wizard.    In the same way we can use SetCheck function to set the values of the check box.

DDX mechanism:    This part of the check box MFC Tutorial deals with an elegant mechanism. This DDX mechanism is an easier way out of the programming intricacies. MFC itself takes care of all the complexities of programming for us. We don't have to worry about getting or setting the values of check boxes ( or any other controls related), by calling GetCheck  or SetCheck.   This is called as Dynamic Data Exchange mechanism. The MFC Framework itself keeps track of the values on the controls. At any point of time, the values are accessible through the variables declared as the member variables.

1. Click on the Ctrl+W to open the class wizard2. In the Member variables tab, select the IDC_SECONDCHECKBOX and clickAdd Variable3. Enter the variable name as m_SecondCheckBox4. Leave the Category and Variable typesunchanged at Variable and bool. Click ok.5. Add a new command Button with a caption "Get DDX" and add a handler to it.6. We can now get the value of the checkbox without using theGetCheck and SetCheck functions

as follows.

    void CMfc_tutorial_8Dlg::OnButton1()     {          // TODO: Add your control notification handler code here

          CString l_strCheckBoxVal;          UpdateData();          int l_ChkBox = m_SecondCheckBox;          UpdateData(FALSE);          l_strCheckBoxVal.Format("Second Check Box Value : %d",l_ChkBox);          MessageBox(l_strCheckBoxVal);}  

   The new code is highlighted with the bold letters. This is the way MFC handles all the controls from which we need some values to be extracted. This Dynamic Data exchange eases the programmer's job very much. Now we can get the same output as in the manual handling of the check box.

Summary:   This tutorial discusses

The usage of check box associated with the class CButton. Handling the Button Clicked messages Usage of functions GetCheck and SetCheck DDX mechanism  

   Please find the Sample code here List boxes are used to load a list of items. Users will be able to add, select and delete items with the list boxes.

Page 18: MFC Tutorial

CListBox Examples:

   The MFC class CListBox is the one which encapsulates all the functionalities and members of the List Box control. It can handle almost all the common requirements that a GUI programmer will need with a list box. If at all there are any extra features needed, the programmer can derive a new class from this CListBox and implement his own custom functionality.     There are quite a few basic techniques to be learnt with all the MFC Controls. Some of them related to the List Box control are

Retrieving the selected items Adding items Deleting items Handling List box messages

   The first job for this MFC tutorial will be to create the MFC Dialog based Application. This application will be used to hold the list boxes. This is the same set of code/steps which are used for the MFC Tutorials explaining about the controls, are being used in this CListBox Example.

To Create the Application:

1. Open the Microsoft Visual Studio 6.00. Click Menu--> File--> New and SelectMFC AppWizard(exe) option.

2. In the next MFC AppWizard screen - Step 1, Choose Dialog based application.3. Click Finish after selecting this. All the files needed for this CListBox Example MFC Tutorial will

be created.4. If the project is built and run, it will open a dialog box, with two command buttons and one static

display control.5. Close the application and come back to the Microsoft Visual studio.

Adding a List box in a Dialog Editor:   The above application and dialog box will be used for handling List box in the tutorial. The following steps explain how to add a List box for this MFC Tutorial:

1. Open the dialog editor of the previously created application of this CListBox example MFC Tutorial.

2. Click on the List box from the controls toolbox and place one List box control on the dialog.3. Open the properties dialog of the List box. This is done by first selecting the List box and pressing

the "Enter" key.4. Rename the ID of the list box as IDC_MYLISTBOX.5. Add one edit control with ID as IDC_LISTBOXTEXT.6. Add three command buttons, one with ID as IDC_ADD and caption as "Add" and second with ID

as IDC_REMOVE and caption as "Remove". Name the ID of the third one as IDC_GET and the caption as "Get"

   Now we'll look at the different ways of manipulating the List boxes. Before doing this, we need to create member variables for the controls. Do the following.  

Click on the Dialog Editor and Press the Ctrl + W keys or you can instead click on Menu --> View -->Class Wizardto open the Class wizard.

Click on the member variables tab Select the IDC_MYLISTBOX id and click Add Variable. Give the variable name as m_ctlListBox and select control in thecategory combo box.

Page 19: MFC Tutorial

Next, select the IDC_LISTBOXTEXT and click Add Variable. Give the variable name as m_txtListbox and keep the CString selected in thecategory.

Create three different handlers for the command buttons Add, Remove and Get.

Adding Items to the CListBox:

    Adding items to a ListBox is done using AddString function. This is a member function of CListBox.     Now, what we'll do is to add a string in the list box from the Edit box. Whenever we type something in the edit box and click on Add, we'll add it to the list box. The following is the code snippet required for doing the job.  

    void CMFC_Tutorial9Dlg::OnAdd()     {          // TODO: Add your control notification handler code here         CString strText;         UpdateData();         strText = m_txtListbox;         UpdateData(FALSE);

         m_ctlListBox.AddString(strText); //This is where the actual data is added}

  The code required for adding to a list box is shown in bold letters. Now build the application and run it. Type some text in the edit control, and press Add button. The text will be added to the list box.

Retrieving Items from the CListBox:

   The first step is to get the index of the selected item and then retrieving the name. Look at the CListBox example of retrieving the item names below.  GetCurSel() will be used to retrieve the index number and GetText() is used to retrieve the text.

    void CMFC_Tutorial9Dlg::OnGet()     {        // TODO: Add your control notification handler code here        int index;        CString strText;        index = m_ctlListBox.GetCurSel();

        m_ctlListBox.GetText(index,strText);        MessageBox(strText);    }  

Deleting Items from the CListBox:

Page 20: MFC Tutorial

  This part will deal with the deleting the selected items from list box. The first step is to get the index of the selected item and then deleting it by using the index. Look at the CListBox example of deleting below.

    void CMFC_Tutorial9Dlg::OnRemove()     {        // TODO: Add your control notification handler code here

        int index;        CString strText;        index = m_ctlListBox.GetCurSel();

        m_ctlListBox.DeleteString(index);    } We can delete the item directly using DeleteString function, if we know the index number the item to be deleted.

Event Handling:    The list box receives notification messages like the following.  

LBN_SELCHANGE  - Selection changed LBN_DBLCLICK  - Listbox Double clicked

   Let's now deal with the LBN_SELCHANGE message in this CListBox Example.  

1. Open the Control Wizard by Pressing Ctrl + W.2. On the Message Maps tab, click on the List box from the controls toolbox and place one List on

the dialog.3. You'll see a list of Messages for the list box on the right side. Select LBN_SELCHANGE and click

on Add function.4. Copy and paste the highlighted code into the function.

        int index;        CString strText;        index = m_ctlListBox.GetCurSel();

        m_ctlListBox.GetText(index,strText);        MessageBox(strText); 

   When we run the application, on every selection change the list box will display the string selected. Refer to MFC CListBox Example for using Icons in List Box Resource if Icons are to be added to the listbox. 

Summary:   This tutorial on CListBox example discusses

Adding items to list box Retrieving items from list box Deleting items Handling Selection change (LBN_SELCHANGE) message

Page 21: MFC Tutorial

   Please find the Sample code here

MFC Tree usage and example   

   MFC Tree controls are one of the useful controls to show a hierarchical view of items. They can show the folders list, any parent - child relationship items etc.,

   CTreeCtrl is the class which handles all the MFC Tree Control related operations. It has all the necessary methods to Add MFC Tree control items, Retrieve selected items, Remove the items and other event handlers needed.

   This article explains how to Initialize a MFC Tree control, Add items to Tree control, Retrieve items, Delete items and one event, Selection Change.

MFC Tree Control - CTreeCtrl Initialization:

       These are the necessary steps to initialize a Tree Control in MFC.

Add a Tree control Resource to the dialog box in the Resource Assign a Resource ID to the tree control using the properties dialog. Add a CTreeCtrl type member variable to the Tree Control using Class Wizard. (To do this, press

Ctrl + W keys together to invoke the class wizard. In Member Variables Tab, select the tree control's ID and press Add member. Variables can be created now). Let us assume the variable name to be m_MFC_Tree

MFC Tree Control - Adding Items:

   For adding items in Tree control, the function InsertItem is the one to be used. This returns a handle to the tree item type as HTREEITEM. Look at the following samples.

Adding item to the root:

         HTREEITEM hParent = m_MFC_Tree.InsertItem("ItemText",TVI_ROOT);   The InsertItem function returns a handle to HTREEITEM, which can be used for adding items down the levels. This function InsertItem is overloaded and has some more signatures. But for a simple insert of items, this function signature is more than enough for us.

Adding child items to the Parent:

   This is a very simple operation. We need the parent handle of type HTREEITEM for creating the child item.

         HTREEITEM hParent = m_MFC_Tree.InsertItem("ItemText",TVI_ROOT);         HTREEITEM hChild = m_MFC_Tree.InsertItem("Child ItemText",hParent,TVI_LAST);

   Usually adding child items in such Tree controls will use recursive functions. For example if the requirement is to list all the folders under C:\ drive, it has to go through each folder to find the sub-folders. Recursive functions will handle such requests easily. A good example will be Windows Explorer.

   If there are no "+" or "lines" found in the tree, change the Has Buttons and Has Lines properties of the Tree Control resource using the properties dialog box.

MFC Tree Control - Retrieving Selected Items:

Page 22: MFC Tutorial

   There are two steps to this operation. We need to find the handle for the selected item and then retrieve the text for the corresponding item.

                HTREEITEM hItem = m_MFC_Tree.GetSelectedItem();                CString strItemText = m_MFC_Tree.GetItemText(hItem);

MFC Tree Control - Deleting Selected Items:

   This is also very similar to the select operation. First we find the handle of the selected item to be deleted and then delete the item.

HTREEITEM hItem = m_MFC_Tree.GetSelectedItem();m_MFC_Tree.DeleteItem(hItem);

MFC Tree Control Event - Selection Changed:

   To Add a handler for Selection Change:

Open the class wizard Go to the Message maps tab Select the Tree control on the left side object IDs list box and select TVN_SELCHANGED on the

right Messages List box. Click Add function and go to the function.

The following sample shows a Message box whenever there occurs a selection change event in the Tree control.

   void CCoderSourceDlg::OnSelchangedTreectrl(NMHDR* pNMHDR, LRESULT* pResult)    {         NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

         // TODO: Add your control notification handler code here         HTREEITEM hItem = m_MFC_Tree.GetSelectedItem();         CString strItemText = m_MFC_Tree.GetItemText(hItem);

         MessageBox(strItemText);

        *pResult = 0;   }

   Though this article does not cover every thing on the tree control, this should be enough to do some basic level of programming with MFC Tree control.

MFC Toolbars   

Toolbars are components of windows operating system with functionalities to invoke dialogs or other screens. They are usually used as a quick links in the place of menus. This article explains how to use a toolbar in an MFC Window based application.

MFC Tutorial - Adding a Toolbar:

   Step 1: Create a MFC Window application as described in MFC Tutorial - Part I.    Step 2: Click on the Menu --> Insert Resource --> Toolbar. Add two buttons for our purpose with IDs

Page 23: MFC Tutorial

named as IDC_TBBUTTON1 and IDC_TBBUTTON2.   Step 3: Add a member variable in side the class MFC_Tutorial_Window as follows.

       CToolBar myBar;

   Step 4: Add the new set of code as highlighted in the following example to the MFC Window Application.

MFC Tutorial - Toolbar Sample

   #include <afxwin.h>   #include <afxext.h> // MFC extensions   #include "resource.h"

   class MFC_Tutorial_Window :public CFrameWnd // Example window for CToolbar sample   {       CToolBar myBar; //MFC CToolBar based Toolbar variable    public:       MFC_Tutorial_Window()       {             Create(NULL,"MFC Tutorial 11 CoderSource Window ToolBar example");       }      int OnCreate(LPCREATESTRUCT lpCreateStruct);      void OnToolBarButton1();      void OnToolBarButton2();

    DECLARE_MESSAGE_MAP()};

   //MessageMap for MFC Toolbar Sample   BEGIN_MESSAGE_MAP( MFC_Tutorial_Window, CFrameWnd)       ON_WM_CREATE()      ON_COMMAND(IDC_TBBUTTON1,OnToolBarButton1)      ON_COMMAND(IDC_TBBUTTON2,OnToolBarButton2)   END_MESSAGE_MAP()

   void MFC_Tutorial_Window::OnToolBarButton1()   {        MessageBox("Toolbar Button 1 clicked");   }   void MFC_Tutorial_Window::OnToolBarButton2()   {       MessageBox("Toolbar Button 2 clicked");   }

   int MFC_Tutorial_Window::OnCreate(LPCREATESTRUCT lpCreateStruct)   {       if (CFrameWnd::OnCreate(lpCreateStruct) == -1)           return -1;

       if (!myBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP          | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC))      {            MessageBox("Failed to create toolbar\n");            return -1; // fail to create      }

Page 24: MFC Tutorial

     myBar.LoadToolBar(IDR_TOOLBAR1);     myBar.EnableDocking(CBRS_ALIGN_ANY);     EnableDocking(CBRS_ALIGN_ANY);     DockControlBar(&myBar);   }

   class MyApp :public CWinApp   {        MFC_Tutorial_Window *wnd;     public:       BOOL InitInstance()       {          wnd = new MFC_Tutorial_Window();          m_pMainWnd = wnd;          m_pMainWnd->ShowWindow(1);          return TRUE;       }   };

   MyApp theApp;

   The MFC toolbar should be loaded during the WM_CREATE message. This is the time when the window of the class CFrameWnd gets created completely. This WM_CREATE message is sent immediately afterwards. This message is added to the Message Map with a handler.

MFC Tutorial - Important functions:

   Apart from the WM_CREATE message, the 3 important functions to be known for a toolbar program are as follows.

 

CToolBar - Create :

   This function creates the toolbar by calling the Win32 SDK CreateWindow function with relevant parameters.

CToolBar - LoadToolBar :

   This function is used to load the toolbar resource (from .rc file) into the CToolBar class object.

CToolBar - EnableDocking:

   This function enables a toolbar to be docked. The sides specified must match one of the sides enabled for docking in the destination frame window, or the tool bar cannot be docked to that frame window.

   Please download the sample code from here.

 

MFC CFile   

Page 25: MFC Tutorial

   CFile is the class used for handling Files in MFC. This class can be used for creating, reading, writing and modifying files. It directly provides unbuffered, binary disk input/output services, and it indirectly supports text files and memory files through its derived classes.

 

      The first parameter to both the functions (CFile() constructor and Open()) is the physical path of the file in the disk. The second parameter is an enumerated constant. This specifies the mode of opening the file object. The above constants modeCreate implies "create a new file" and modeReadWrite means "open the file for both reading and writing".

   If the file is opened without specifying the mode constant shareDenyNone, this file can be opened in read mode by other programs. This feature will be necessary for text files, logs created by programs. For creating text files we use CFile::typeText and for binary files CFile::typeBinary.

 

 

CFile - Writing to a File:

   The function Write is used to write data to the files. The sample code is as follows.

     CFile cfile_object;     cfile_object.Open( "c:\\test\\codersource_cfile_example.txt", CFile::modeCreate|CFile::modeWrite);

     char szSampleText[100];     strcpy(szSampleText, "Sample Text for CFile Write function Example");     cfile_object.Write (szSampleText,100);  

   If there is any need to write text line by line, it is better to use the class CStdioFile. 

CFile - Reading from a file:

   The function Read is used to read data from files. The sample code is,

     CFile cfile_object;     cfile_object.Open( "c:\\test\\codersource_cfile_example.txt", CFile::modeCreate|CFile::modeWrite);

     char szSampleText[100];     UINT lBytesRead = cfile_object.Read (szSampleText,100); 

   The function returns the number of bytes read from the file. The maximum number of characters read will be the second parameter of the Read function.

CFile - closing the file:

   The Close function is used to close the file. But the close function need not be called, as the destructor will automatically call it if the file is open. So when the object goes out of scope, the destructor calls close function.

 

CFile - Creating a File:

Page 26: MFC Tutorial

   There are two ways of creating files. One way is to instantiate the CFile object with the file path. This creates the file. The second way is to call the Open function. This also creates the file.

 

     CFile cfile_object( "c:\\test\\codersource_cfile_example.txt", CFile::modeCreate|CFile:: modeReadWrite);

     CFile cfile_object;     cfile_object.Open( "c:\\test\\codersource_cfile_example.txt",  CFile::modeCreate|CFile:: modeReadWrite); 

CComboBox Example   

   Combo box controls are space savers. Wherever there is no need for a multi-select from a list of items, combo box is a good choice in such places. This article " CComboBox Example" explains how to use the MFC CComboBox class for manipulation of a list of strings.

CComboBox Example - Initializing a Combo Box:

   It is assumed that the readers of the sample have already created a dialog box (either in a dialog based application or SDI/MDI application) and placed a combo box control from the controls toolbox on the Resource Editor.

   After placing the combo box control on the dialog box, open the class wizard by pressing Ctrl + W keys or Menu --> View --> ClassWizard. In the Member Variables tab, Add a Variable for the CComboBox class. This CComboBox example assumes that the variable name is,

      CComboBox  m_cbExample;

   This m_cbExample will be used further in our CComboBox example MFC code.

 

CComboBox Example - Adding Items to a Combo Box:

   The function AddString is used for adding items to a combo box. If there is a constant set of data, these values can also be added in the Resource Editor itself. The Combo Box control properties dialog has a tab for adding data. Otherwise the data can be added as follows.

    m_cbExample.AddString("StringData1");    m_cbExample.AddString("StringData2");    m_cbExample.AddString("StringData3");

CComboBox Example - Retrieving Items from a Combo Box:

   Usually a requirement for retrieving items from the combo box will arise from selecting the data. This article also assumes the same. Now the data selected in a combo box needs to be retrieved.

   To do this, the first step is to find out the index of the selected item inside the combo box control. Then the item at the corresponding position needs to be pulled out as follows.

Page 27: MFC Tutorial

    int nIndex = m_cbExample.GetCurSel();    CString strCBText;    m_cbExample.GetLBText( nIndex, strCBText);

   In the above CComboBox example code, the value will be retrieved and stored in strCBText variable. There is another overloaded version for GetLBText. But the version which uses CString is the easiest one.

 

CComboBox Example - Finding Items inside a Combo Box:

   This kind of Find operations on a Combo box will most probably be useful in programs that dynamically modify the values in a combo box. The function FindStringExact is used to find the exact string match inside a combo box.

    int nIndex = m_cbExample.FindStringExact(0, "Value to be found");

   The string position inside the combo box control is the return value. It returns CB_ERR if it was unsuccessful in finding the string.

 

CComboBox Example - Deleting Items from a Combo Box:

    This operation can be done by using the CCombobox member function DeleteString. This function needs the index of the item inside the combo box.

     m_cbExample.DeleteString(nIndex);

 

MFC CListCtrl   

   List Control is one of the useful controls to display data in different formats viz., icon view, report view, simple list etc., This article describes how to use CListCtrl for creating report views.

   Before using any control resources in MFC, they must be associated with a class. Use the Member Variable tab of the Class Wizard to create a variable for the List Control. This CListCtrl  variable will be used subsequently for our samples. Make sure that the property of Report is selected for view under style tab of the properties box. Also the stdafx.h file should have afxcmn.h included.

 

CListCtrl - Inserting Columns:

  There are many different signatures of InsertColumn function to this operation. But this article use the simplest of all.

   int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, intnSubItem = -1 );

nCol : This specifies the position of the columns, starting from 0.

Page 28: MFC Tutorial

lpszColumnHeading  : The string specified here will be considered as the Header Row for the list control.

nFormat : For alignments. LVCFMT_LEFT for left, LVCFMT_RIGHT for right and LVCFMT_CENTER for Center.

nWidth : Width in pixels.

   Look at the following sample usage for the InsertColumn function.

   m_ListVw.InsertColumn(0, "Heading 1",LVCFMT_LEFT, 100);   m_ListVw.InsertColumn(1, "Heading 2",LVCFMT_LEFT, 120);

   This will add two column headings to the List control as Heading1 and Heading2.

CListCtrl - Adding Rows:

Adding Row for a Single Column List Control:   

    Adding rows if the control has a single column, will be straightforward. It is enough if we call InsertItem function as below. 

      m_ListVw.InsertItem(0,"Item1");      m_ListVw.InsertItem(1,"Item2");

   The first parameter is the row number of the CListCtrl. This is a number starting from 0. The InsertItem functions returns an index, which can be used to call other functions to operate on the row.

Adding Rows for a Multi column CListCtrl:

   This will need usage of two functions viz., InsertItem and SetItemText as follows.

       int nIndex = m_ListVw.InsertItem(0,"Item1");       m_ListVw.SetItemText(nIndex,1,"Item12");       m_ListVw.SetItemText(nIndex,2,"Item12");

  There are more ways of adding items to the list controls. But this one is probably the simplest. The function SetItemText can also be used to modify the data inside a cell.

CListCtrl - Deleting Rows:

   If one wants to delete all the rows in the List control, the function DeleteAllItems should be used. If someone wants to delete item wise, the function DeleteItem should be called. The following is the sample piece of code for it.

    m_ListVw.DeleteItem(2);

   The above code will delete the 3rd row from the list control. This parameter specifies the Row index starting from 0.

CListCtrl - Reading an item from a Row:

  This article assumes the item read is the currently selected item.

      int nSelected = m_ListVw.GetSelectionMark();      CString strText = m_ListVw.GetItemText(nSelected, 0);

Page 29: MFC Tutorial

  This retrieves the value from the nSelected row and first column. 

MFC CFont   

    CFont class encapsulates the functionalities needed to manipulate the Fonts in Windows programming. A font can be created in 4 ways with a CFont class using CreateFont, CreateFontIndirect, CreatePointFont, or CreatePointFontIndirect functions. This CFont Samples page tries to give a piece of sample code for all of the above functions.

CFont Sample for using CFont :: CreateFont:   The following CFont sample illustrates how to create a font using CreateFont function of the CFont class. 

   CClientDC dc(this);   CFont l_font;   l_font.CreateFont(14, 0, 0, 0, FW_NORMAL,   FALSE, FALSE, FALSE, 0, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,   DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, "Times New Roman");

   CFont* l_old_font = dc.SelectObject(&l_font); dc.TextOut(50, 50, "Hello World");       dc.SelectObject(l_old_font);   // Delete the font object.    l_font.DeleteObject(); 

 

   In the above CFont Sample, the CreateFont function uses all default parameters (either 0 or Default constants), except for the height parameter. If CreateFont is called as above, the MFC framework will select the best fit parameters by itself and create a font accordingly. 

CFont Sample for using CFont :: CreateFontIndirect:    This part of CFont sample illustrates the usage of CreateFontIndirect. 

   CClientDC dc(this);   CFont l_font;   LOGFONT lf;   lf.lfHeight = 12;   strcpy(lf.lfFaceName, "Arial"); // Need a face name "Arial".    l_font.CreateFontIndirect(&lf);    CFont* l_old_font = dc.SelectObject(&l_font);    dc.TextOut(50, 50, "Hello World");    dc.SelectObject(l_old_font);    // Delete the font object.   l_font.DeleteObject(); 

Page 30: MFC Tutorial

The LOGFONT is a structure with all members required for the Font object. 

CFont Sample for using CFont :: CreatePointFont: This part of the sample illustrates the use of CreatePointFont for creating a font.

   CClientDC dc(this);    CFont l_font;    l_font.CreatePointFont(140,"Times New Roman");    CFont* l_old_font = dc.SelectObject(&l_font);   dc.TextOut(50, 50, "Hello World");    dc.SelectObject(l_old_font);    // Delete the font object.    l_font.DeleteObject(); 

The first parameter of the CreatePointFont function is the height of the Font in tenths of a point. The return value of this function is non-zero value if successful. 

CFont Sample for using CFont :: CreatePointFontIndirect: 

   CClientDC dc(this);    CFont l_font;    LOGFONT lf;   lf.lfHeight = 120;    strcpy(lf.lfFaceName, "Arial"); // Need a face name "Arial".    l_font.CreatePointFontIndirect(&lf);    CFont* l_old_font = dc.SelectObject(&l_font);    dc.TextOut(50, 60, "Hello World");    dc.SelectObject(l_old_font);    //  Delete the font object.    l_font.DeleteObject(); 

   Usually it is better to use either CreatePointFont or CreatePointFontIndirect functions as they reduce the head-ache of thinking about the width, weight and such parameters.   Also, in the above CFont sample the l_font is deleted in the end. It is a good programming practice as advised by Windows Programming manuals to delete the Objects after removing them from the current device context. 

MFC CFileDialog   

   CFileDialog MFC class can be used to invoke the Windows Open File and File Save As dialogs. This CFileDialog class encapsulates the functionalities required for retrieving file names, setting up filters, flagging over write prompts etc.,

Page 31: MFC Tutorial

   This CFileDialog can be used in interactive MFC GUI applications wherever we need to browse the Windows File System (and use the file selected). The applications need not worry about the gory background details of enumerating the folders, listing them in a GUI etc., All these functionalities are encapsulated within CFileDialog object.

   Once CFileDialog is instantiated and called, the user can be allowed to select the file and the programmer can use the selected file. The CFile Example explains how to manipulate files using MFC CFile class.

 

CFileDialog - for File Open:

   The following piece of code snippet shows how to use CFileDialog to open text files (*.txt) and comma separated value files(*.csv).

      CFileDialog l_SampleDlg(TRUE,NULL,NULL,OFN_OVERWRITEPROMPT,"Text Files (*.txt)|*.txt|Comma Separated Values(*.csv)|*.csv||");      int iRet = l_SampleDlg.DoModal();      CString l_strFileName;      l_strFileName = l_SampleDlg.GetPathName();

      if(iRet == IDOK)          MessageBox(l_strFileName);      else          MessageBox("No File Selected!"); 

   The above piece of code should be used in an MFC application. This will invoke the File Open dialog (constructed by using CFileDialog), with filters set for listing the *.txt and *.csv files. As seen, DoModal returns IDOK if a file is selected andOpen button is clicked. Otherwise, if cancel button is clicked, it returns IDCANCEL.

   After this DoModal, calling CFileDialog ::GetPathName returns the file path. If only the file name is needed, a call to the function GetFileName will be enough.

Note:   Changing the First Parameter of CFileDialog to FALSE, this dialog will become a Save As dialog.     

   CArray is a collection template which can store all data types. Unlike a normal C++ Array this MFC Collection template can grow and shrink depending on the needs. This allows memory to be utilized efficiently in MFC programs. This template is declared in afxtempl.h. This class can be used wherever there is a need to store a list of similar typed objects.

   This article describes how to add to, access from and remove objects from the MFC Collection template CArray. 

CArray - Adding an element:

Page 32: MFC Tutorial

   The member function Add can be used to add objects to the Array. Before using CArray template, CArray has to be declared to accept the corresponding type of object. This code sample declares and uses CString.

 

#include <Afxwin.h>#include <Afxtempl.h>

void main(){

CString l_strValue;CArray<CString,CString> l_CArray;

for(int i=0;i< 20; i++){

  //Use the CString format function to create different values   l_strValue.Format("Value %d",i);  //Add the formatted CString to CArray  l_CArray.Add(l_strValue);

}

}

CArray - Accessing the elements:

   The member function GetAt can be used to access the data stored in CArray. This returns the object on the type stored. Modifying the value at a given node is carried out by using SetAt function.

#include <Afxwin.h>#include <Afxtempl.h>

void main(){

CString l_strValue;CArray<CString,CString> l_CArray;

for(int i=0;i< 20; i++){

  //Use the CString format function to create different values   l_strValue.Format("Value %d",i);

Page 33: MFC Tutorial

  //Add the formatted CString to CArray  l_CArray.Add(l_strValue);

}

//This part takes care of accessing and printing the data from CArrayCString l_strGetVal;for(i=0;i<=l_CArray.GetUpperBound();i++){    l_strGetVal = l_CArray.GetAt(i);    printf("%s\n",l_strGetVal);} 

}

CArray - Removing the elements:

   There are two different functions to remove the data from CArray. RemoveAll function can be used to remove all the elements. The RemoveAt function can be used to remove an element from a specific location.

           l_CArray.RemoveAll() //This will remove all the elements from CArray

           l_CArray.RemoveAt(10); //This will remove the 10th element from CArray

 

   CString was used in the above example with CArray. But all complex data types can be stored in this MFC Collection template.

CString   

  CString is a boon to all C++ converts of MFC. Good God! it is so much of a pain to use char* in c++. A small mistake could lead to big mishaps, to any programmer's nightmare. CString in MFC gives lot many features to handle strings, weaning away all such bad memories of char *. This article deals with the usage of CString in MFC programs. It also tries to give some small code snippets wherever necessary.

CString Features:

   There are some special features in CString that makes it really unique and attractive. Some of them are

 

CString has no base classes in MFC. So it is light weight. CString is written based on TCHAR type. It can automatically support UNICODE as well as ASCII

strings. CString implements a reference counting mechanism for copy of objects. This saves a lot of

memory usage.

How to Use CString:

Page 34: MFC Tutorial

   CString can be initialized by calling one of its constructors. It can be instantiated with or without parameters. The constructors can accept a char, char*, TCHAR, wchar types as a parameter. The string is constructed according to the parameter passed.

   In case it is created without any parameters, the string will be empty. Values can be assigned with the use of '=' operator.

CString strExample;strExample = "CString sample value";

   To get the length of a CString, the function CString.GetLength() can be used. This returns the length of the string as an integer.

String Concatenation with a CString:

   String concatenation is very easy with CString. CString has an overloaded operator for + sign, which makes a programmer's life easier.

CString strExample1 = "Sample Value ";CString strExample2 = "for concat with CString";

//Concatenation with CString and CStringstrExample1 = strExample1 + strExample2;

//Concatenation with CString and a const char*strExample1 = strExample1 + "for concat without CString";

CString and BSTR:

   CString also provides for conversions to BSTR with functions like AllocSysString and SetSysString. It can allocate memory and copy the data into the allocated space for BSTR.

CString strBstrConv = "Sample for CString to BSTR";BSTR bstrVariable = strBstrConv.AllocSysString();

String Comparisons with CString:

   CString contains an operator member function for the '=' operator. This operator performs a case-sensitive comparison. For case-insensitive comparisons the function CompareNoCase can be used.

CString strCompareString1 = "String Compare Sample";CString strCompareString2 = "sTring Compare Sample";

//Using == operator case sensitive CString comparisonif(strCompareString1 == strCompareString2)  MessageBox("Both Strings are equal - Case Sensitive");

//Using CompareNoCase for case-insensitive CString comparisonif(strCompareString1.ComparNoCase(strCompareString2) == 0)   MessageBox("Both Strings are equal - Case Insensitive");

Page 35: MFC Tutorial

Finding a Character inside CString:

    CString supports find for a single character and also strings. It provides searching a character from the reverse direction.

   CString strFindData = "Finding a Character and a string in forward direction";

//Find a char 'C'int lPos = strFindData.Find('C');

//Find "string"int lPos = strFindData.Find('string');

These find functions return the position of the character or string as an integer.

Using Format Functions in CString:

   The Format function in CString can be used to convert different data types into a string type. This function is similar to the sprintf function.

CString strFormatData;int x = 40;char strdata[] = "Test Data ";

strFormatData.Format("%s %d",x,strdata);

//The output will be "Test Data  40"

   The above is only a small list of the capabilities of CString. There are a lot more of features available with CString. Not all of them can be explained. More of those features will become clear when one starts using it.

CToolTipCtrl   

   CToolTipCtrl can be used to attach tool tips for controls. The tool tips can be placed on any controls using AddTool(), a member function of CToolTipCtrl. This article explains how to show Tool Tips for a command button which is placed on a dialog box.

   Tool tips are shown in a round rectangle adjacent to the controls. They are shown when the Mouse cursor is placed on the control.

 

Tool tips on a dialog - CToolTipCtrl:

Create a new Dialog based MFC Application. The article assumes the application name as  MFCSample.

In the MFCSampleDlg.h file, add a member variable for CToolTipCtrl inside CMFCSampleDlg class as follows.

CToolTipCtrl *m_ToolTip;

Page 36: MFC Tutorial

Add a Command Button to the dialog box. Create a member variable for the button as m_TESTBUTTON.

In the OnInitDialog function of the CMFCSampleDlg class ( MFCSampleDlg.cpp) add the following code.

m_ToolTip= new CToolTipCtrl();m_ToolTip->Create(this);

m_ToolTip->AddTool(&m_TESTBUTTON,"Test Button");

m_ToolTip->Activate(TRUE);

The above code adds a tool tip for the command button. If the mouse cursor is placed on the button, it shows a tool tip as "Test Button".

More controls can be added with the tool tip as above. The following version of PreTranslateMessage should be placed in MFCSampleDlg.cpp, to

override the default one.

BOOL CMFCSampleDlg::PreTranslateMessage(MSG* pMsg) {    // TODO: Add your specialized code here and/or call the base class

    if(m_ToolTip != NULL)       m_ToolTip->RelayEvent(pMsg);

    return CDialog::PreTranslateMessage(pMsg);}

   The above pretranslatemessage version, ensures that Windows gets the notifications required for the Tool tips.

   The above program creates the CToolTipCtrl variable using the new operator. So the memory should be freed at the end of the program by using the delete operator. 

 

  MessageBoxes are simple and effective way of showing errors on input/processing or outputs. They can be used intuitively to communicate the messages in a very clear cut fashion. They can be used to provide 3 kinds of messages. The message can be either an Information, Question or a Warning.

   Messagebox es' can be useful in various places. They can be used inside an MFC application with a window or without a window too. This article discusses how to use message boxes in such different circumstances.

Page 37: MFC Tutorial

MessageBox in an MFC Application:

   This is by far the easiest in an MFC application. It is enough to just pass the message to be displayed and the MessageBox is ready to go. This can be used inside any CWnd derived class in an MFC application.

MessageBox("Text for the MessageBox");

 

AfxMessageBox for a non-CWnd based class:

   The MessageBox function can be replaced with an AfxMessageBox function in any non-window classes. This can even be called inside a console application provided, it includes the necessary headers and libraries required for MFC.

AfxMessageBox ("Test Message from AfxMessageBox function");

   Though showing such a simple message is a very easy task for the programmer, it is not advisable in any standard programs. A MessageBox should always include a Title and an Icon to display the type of message.

AfxMessageBox with Icons:

   When icons are combined with messages in a mesagebox the meanings to the user can be very clear. For example to inform the user "An upload operation is complete", the following function would be appropriate.

AfxMessageBox ("An upload operation is complete!",MB_ICONINFORMATION|MB_OK);

   The above message will really serve the purpose of communicating an information. In case the user has selected an invalid item or a wrong button had been clicked, the following can be an appropriate message.

AfxMessageBox ("Wrong button clicked!",MB_ICONQUESTION|MB_OK);

   Some more useful icons can be MB_ICONWARNING, MB_ICONSTOP etc.,

AfxMessgeBox with return values:

   Sometimes the message boxes might need to take action based on the replies through message boxes. An example is as follows.

int nResult = CWnd.MessageBox("Are you Sure to quit?", MB_YESNO|MB_ICONQUESTION);if(nResult == IDYES){t   //Quit}else{  //Stay}

Page 38: MFC Tutorial

   Thus if these cute little boxes are used with some extra options, they can add a lot of value to the applications.

MFC CEdit   

   The CEdit class provides the functionality of an edit control in Microsoft Windows based systems. It is a rectangular child window which can be used to enter text in GUI Programs. This article explains how to use the CEdit class for some of the important operations to be performed in a dialog based program. This is also applicable in SDI/MDI applications which use a dialog box.

CEdit - Setting up the program:

   The following steps explain how to setup the base application/dialog box for using the edit control. The class CEdit will be used to manipulate the edit control being used. If this basic set up is already done, readers can skip this section and move to the next one.

 

Create a new MFC AppWizard executable project as a dialog based application. The application can also be an SDI/MDI app, where in the dialog can be inserted as a resource

into the SDI/MDI projects. From the controls toolbox, choose the edit control and place it on a dialog box. In the properties

dialog of the edit control, enter the resource ID as IDC_EDTEST. If the edit control is supposed to accept only numbers, in the Edit control --> Properties --> Styles

tab, set the number property to true by checking the checkbox provided. This makes the CEdit based edit control accept only numbers.

Add a class member for the CEdit for the edit control. The code sample in this CEdit article assumes the variable name to be m_Edit.

CEdit - Setting and Retrieving values:

   The member functions of CEdit,  CEdit .SetWindowText() and CEdit .GetWindowText() can be used to set and get the values on the Edit control. The following is the code sample for setting the values in edit controls.

     //Set the value on CEdit     CString l_strValue = "Test Value to be set on CEdit";     m_Edit.SetWindowText(l_strValue);

     //Get the value from the CEdit control     m_Edit.GetWindowText(l_strValue); //This gets the value into the CString variable l_strValue

CEdit - Using DDX mechanism:

   Dynamic Data Exchange offered by MFC is a very useful feature, which allows programmers to ignore the control variables and stick to value based variables. This is an easy way to initialize the values of controls in a dialog box and to retrieve values from the controls. To enable the CEdit control for DDX mechanism the following steps as outlined here may be performed.

Open the Class Wizard. In the Member Variables tab, click Add Variable button.

Page 39: MFC Tutorial

In the Add Member Variable dialog box, choose the Category as Value and choose the Variable type as a suitable one. If the values can be manipulated are in character arrays, choose CString, if numbers are going to be manipulated choose Number etc.,

Click Ok and save the project. The control is now DDX enabled. The following code sample may be used for setting and getting the value on a DDX enabled

CEdit control. The sample assumes the variable name as m_strEdit.

//To set the value on a DDX based CEdit controlvoid DlgName::SetvalueonEdit(){

UpdateData();m_strEdit = "Test Value set for DDX";UpdateData(FALSE);

}//To get the value on a DDX based CEdit controlvoid DlgName::GetvalueFromEdit(){

UpdateData();CString strStoreValue;strStoreValue = m_strEdit ;UpdateData(FALSE);

}

Note: The CEdit control can also be set on a multi-line mode. While working on a multi-line mode the CEdit will give some problems for using the function SetWindowText. The end of line characters won't be shown properly. To solve this problem, for every end of line append the string with a "\r\n".

CProgressCtrl   

   A Progress control is something that an application can use to indicate the progress of an ongoing operation. It consists of a rectangle that is gradually filled, from left to right, with the system highlight color as an operation progresses. This control is can be manipulated by using the class CProgressCtrl.

   This article is a brief about how to use this control with reference to the class CProgressCtrl in an MFC application with dialogs.

CProgressCtrl - Setting up the application:

   The following steps explain how to setup a basic dialog application to hold a progress bar control. If there is a dialog to hold the Progress bar (of CProgressCtrl ) the following steps can be ignored.

 

Create a new MFC AppWizard executable project as a dialog based application. The application can also be an SDI/MDI app, where in the dialog can be inserted as a resource

into the SDI/MDI projects. From the controls toolbox, choose the progress bar control and place it on a dialog box.

Page 40: MFC Tutorial

Add a class member for the CProgressCtrl for the progress bar control. This sample assumes the variable name to be m_Progress.

CProgressCtrl - Sample usage:

   The progress control can be initialized and used wherever needed. A dialog can have multiple operations/functionalities to be supported. For each and every operation, the CProgressCtrl can be initialized and used to indicate the progress of the operation.

   The following is the sample piece of code to show the progress of a CProgressCtrl from 1 to 100 with increments of 2 at every operation.

    m_Progress.SetRange(0,100);    m_Progress.SetStep(2);    for(int i=0;i<50;i++)    {        m_Progress.StepIt();    }

   or instead of the CProgressCtrl.SetStep() and CProgressCtrl.StepIt() combination, a single function CProgressCtrl.StePos can also be used.

   The above piece of code can be applied anywhere the control needs to be manipulated.

   Also it is to be noted that the control need not be used only by the resource editor. It can also be created dynamically by using the CProgressCtrl.Create function.

MFC DLL   

   MFC regular Dll usage has decreased now a days to a large extent. People are now moving towards COM dlls. Though the COM Dlls' have a lot of advantages over regular Dlls' in MFC, the regular dlls are still being used by many developers.

   MFC DLL wizard provides options to create 3 kinds of DLLs. Regular DLL Statically linked to MFC, Regular DLL dynamically linked to MFC and MFC extension DLLs. This article uses MFC regular DLL Dynamically linked to MFC. The output produced by this option (dynamically linked) is a very small DLL. The statically linked DLLs will be of larger size, as they are built with the whole MFC libraries within themselves. 

   A MFC Dll can provide/export with functions, variable values, constants and classes. This article concentrates on exporting a function, which is the mostly used export in DLL.

 

MFC DLL - Building the DLL:

1. Create an MFC AppWizard Dll. Choose the option of Regular MFC DLL - Dynamically Linked to MFC.

2. After the application gets created, add a header file and a source file to the application. The article assumes the file names to be utilities.h, utilities.cpp.

3. Enter a function declaration inside the header file utilities.h with the following syntax.

Page 41: MFC Tutorial

__declspec(dllexport) int AddValues(int a, int b);

4. Add the function definition inside the utilities.cpp file as follows.

int AddValues(int a, int b){       return a+b;}

5. Compile the MFC DLL application. This will produce a ProjectName.lib and ProjectName.dll in the debug folder. These two files are enough for using inside an application.

MFC DLL - Building the application:

1. Create a new MFC AppWizard Executable application. Even a console application will be enough for using the MFC Dll.

2. Copy the utilities.h into the project folder. Copy the ProjectName.lib and ProjectName.dll into debug folder of the project.

3. In the source file of the application include the header file as #include "utilities.h".4. In Project Settings --> Link --> Library/Modules add Debug/ProjectName.lib. This will ensure

linking of the necessary MFC Dll files.5. Call the AddValues function any where necesary.6. Build and run the application. The MFC Dll function will be used.7.   This project illustrates an owner-draw combo box which can show different fonts using CFont. 

The class uses an abstract object to draw the items. In this case a class derived from the abstract object is created to make the control list of fonts using CFont.

8.    The abstract class contains methods that are called from the combo box class only. They are9.

10. virtual void DrawItem(LPDRAWITEMSTRUCT lpdis, bool bHasFocus) = 0;   Actually draws the item using the Win32 DRAWITEMSTRUCT.

virtual void MeasureItem(LPMEASUREITEMSTRUCT lpmis) = 0;   Sets the item size once or every time depending of the owner-draw style: fixed ot variable.

virtual void InitLBox(CListBox* pLBox) = 0;   Initializes the control holding the class if it is a CListBox (or derived from it)

virtual void InitCombo(CComboBox* pCombo) = 0;   Initializes the control holding the class if it is a CComboBox (or derived from it)

virtual int AddItemLst(CListBox* pLBox, UINT nItem) = 0;   Adds an item to the control holding the class if it is a CListBox (or derived from it)

virtual int AddItemCmb(CComboBox* pCombo, UINT nItem) = 0;   Adds an item to the control holding the class if it is a CComboBox (or derived from it)

11.  

Page 42: MFC Tutorial

12.

13.    This class is added to the combo box via it?s method SetDrawC. It must be added before the control is created, so you had better call it in the parent dialog class constructor.The Init() method of the control should be called immediately after it?s creation.Items are added with the AddItem function of the control.Combo boxes using from this type can be created either dynamically or using the dialog editor and after adding a variable of type CComboBox just rename it with CODrawCombo. Don?t forget to call SetDrawC and Init. Combo boxes must be created with the following styles: CBS_DROPDOWNLIST, CBS_HASSTRINGS, CBS_OWNERDRAWFIXED or CBS_OWNERDRAWVARIABLE.

   In this particular example a combo box listing the system fonts is implemented. The init method does the main font initialization routine. The AddItem method is obsolete and is not to be used for this class.

   A class wrapper for the LOGFONT structure is defined for these controls. The LOGFONTX class has an extra variable to store the font type, a copy-constructor and a = operator. The init function of the CFontDrawC class fills the internal list of fonts of the class and then fills the control with the fonts. Notice that it checks if the internal list is filled and if it is doesn?t fill it again. This is done so because getting the system fonts is a relatively time consuming job and it is best to be done as seldom as possible.The internal list is filled with the Win API function EnumFontFamilies which calls a custom function that actually inserts the fonts in the list, which is passed as a parameter between the functions.The control is filled with the names of the fonts as strings, so FindString and SelectString can be used with these controls. Again SetItemData is used to add a pointer to a LOGFONTX class instance for each font.

   After that in the drawing function font is received as a pointer to the LOGFONTX structure and is drawn with that code

14.

15. LOGFONTX* pLF = ( LOGFONTX* )lpdis->itemData;CFont font;font.CreateFontIndirect( pLF );pDC->SelectObject( &font );

16.

17.    When the selection in the combo box is changed an event is raised. We catch this event to update the sample text like this:

18.

19. CFont font;font.CreateFontIndirect((LOGFONT*)m_fontCombo.GetItemData(m_fontCombo.GetCurSel()));m_sampleText.SetFont(&font);

20.

21.    You can see that to get just the pointer to the LOGFONT structure you should write:22. (LOGFONT*)m_fontCombo.GetItemData(m_fontCombo.GetCurSel());23.    Download the Sample Source here. Read here to know the MFC General Owner draw issues &

how to solve them.

MFC Print Tutorial

Page 43: MFC Tutorial

   

Introduction to MFC Printing:

   It's common knowledge that printing is one of the hardest things for properly implementing in your Win32 program. You have probably heard or even experienced how hard printing is with Win32 API. The good news is that we are using MFC which greatly simplifies this task. You get print preview, standartized dialogs(print setup, page setup), print job interruption dialog and OS management for free. If this doesn't look much to you just have a look at the MFC source files involved in printing and print preview.

   Basically with MFC you only have to add drawing code and logic for paginating the document if it consists of multiple pages. Maybe after this you wonder what can this tutorial offer to you. The problem is that MFC hides most of the functionality in members of various classes. This tutorial will start ith basic control over the process and will continue with more advanced modifications of the internal structures involved in printing. I will use a technique i call "copy&modify for your needs". For this you will need the MFC source code. You will find further instructions in the examples. Now proceed to Step 1.

 

Creating the MFC Visual C++ Printing program:

For this tutorial we will create a simple program. Start Visual C++ and use MFC AppWizard(exe). In step 1 select "Single document". Make sure the check box is selected.  Skip step 2 and in step 3 you can disable "ActiveX Controls" since we won't use them. In step 4 set the number of files to 0 and click on Advanced and delete the two bottom lines (File

new name(short) and (long)). Otherwise the program will add its document type in the right click menu in "New->" and you wouldn't want this. Press "Finish" and the project is ready.

Printing Functions provided by MFC in Visual C++:

   The program has a class CTutorialView with some member functions. The ones involved in printing are OnPreparePrinting, OnBeginPrinting, OnEndPrinting, OnPrepareDC, OnDraw and OnPrint. 

   We have two options for printing:

1. To use OnDraw paint the window and OnPrint to print or paint in print preview mode.Right click the class CTutorialView and select "Add Virtual Function...". Find the function OnPrint and press "Add and Edit". You are then taken to the function body and you should see this code 

CView::OnPrint(pDC, pInfo);

which you may safely delete(or better add // for commenting it).

   It is possible to make output both for the display and printer in OnDraw. If you want this you should use pDC->IsPrinting() which returns TRUE if printing and FALSE if displaying. You don't need OnPrint function.

  Now start the program and press the Print button in the toolbar or press Ctrl+P. You should see the Print dialog. Note that Page range is set to all and the text box next to "pages" shows 1-65535. This is the default for MFC which causes it to print only one page. The page range can be easily changed in OnPreparePrinting by using pInfo. Default selection and the other settings are harder and explained in later pInfo contains all the data related to printing. It's best to look in the help for "CPrintInfo" where you will find all the information about member variables. For now just note that you can use pInfo->SetMinPage and pInfo->SetMaxPage to set the range.

Page 44: MFC Tutorial

Example: use  pInfo->SetMaxPage(1); to limit your printing job to exactly 1 page.

   It is possible to know how much pages your application needs. If it prints out something really small you can safely assume it needs 1 page. If you print fixed-height objects like lines of text you can get the size of the page and the text and calculate how much pages you need. If your program is printing a highly specific thing like a 640X480 bitmap or four 20X15 inches charts you will be able to easily determine what you need. 

Example 1: You know exactly how much pages you need

BOOL CTutorialView::OnPreparePrinting(CPrintInfo* pInfo){pInfo->SetMaxPage(6); // or the number you needreturn DoPreparePrinting(pInfo);}

   Example 2: You don't know the how much pages you need before you get the user seletions form the "Print" or "Print Setup" dialogs.

void CTutorialView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo){int nPageHeight=pDC->GetDeviceCaps(VERTRES);int nDocLength=GetDocument()->DocLength();int MaxPage=max(1, (nDocLength+nPageHeight-1)/nPageHeight);pInfo->SetMaxPage(nMaxPage);}

   Note: In OnBeginPrinting you have a pointer to the initialized device context and you can use it to get some important information about the environment like the size of the selected font. This can be used to determine how much can be printed on one page. GetDeviceCaps is explained later. For now think that nPageHeight is the page height in pixels and nDocLength is the document size in pixels. You can easily modify the code so that nPageHeight is the amount of text lines printed on a page and nDocLength is the total amount of lines in the document.

   If you print the entire document contents rather than printing only the current page you will have to implement the virtual function OnPrepareDC which is called before printing every page and can be used to set the viewport. Otherwise your program will print the first page every time OnPrint(or OnDraw) is called.

void CTutorialView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo){CView::OnPrepareDC(pDC, pInfo);if(pDC->IsPrinting())

Page 45: MFC Tutorial

{int y=(pInfo->m_nCurPage-1)*m_nPageHeight;pDC->SetViewportOrg(0, -y); // remove the minus sign if you are printing in MM_TEXT}}

   Now the printing code will print only the appropriate lines of text. The printing code will look like this:

for(int a=0;a<numStrings;++a){Cpoint point(0,0); // start point for drawingpDC->TextOut(str[a], point.x, point.y);point.y-=nHeight; // if map mode is MM_TEXT change this to +=}

   Note: For big documents scrolling in print preview will work slow because the entire document is printed. If this is a problem you should use code like the one below.

   If you don't know how much pages are needed you can start printing and determine when to stop while printing. 

Example:You have an array of CString objects. OnPrint could look like this (this is only part of code and won't work by itself):

// x and y are some starting positions on x and y axis// for MM_TEXT the point (0,0) is the top left corner of the screen and coordinates increase to the right and down// for MM_HIMETRIC, MM_LOMETRIC, MM_HIENGLISH and MM_LOENGLISH // the start is the bottom left point and coordinates decrease(become negative) upwards and increase to the right.// for MM_ISOTROPIC and MM_ANISOTROPIC they are user-definedCPoint(x,y);// get the current page number (for first page returns 1, for second - 2 and so on)nCurPage=pInfo->m_nCurPage;// get the index of the first CString in the array that has to be printed in this pagenStartPos=(nCurPage-1)*linesPerPage;// calculate the index of the last CStringnEndPos=nStartPos+linesPerPage;// fill a TEXTMETRIC struct with various information about the selected fontTEXTMETRIC tm;pDC->GetTextMetrics(&tm);

Page 46: MFC Tutorial

int nHeight=tm.tmHeight+tm.tmExternalLeading;for(int a=nStartPos;a<nEndPos && a<numStrings;++a){pDC->TextOut(str[a], point.x, point.y);point.y-=nHeight; // if map mode is MM_TEXT change this to +=}if(a>=numStrings)// will stop printing if all strings are printedpInfo->m_bContinuePrinting=FALSE; 

Printing:

   There are several ways to print your document but first you need to know something about mapping modes. Printers have fixed physical measures. Most printers support at least 600X600 dpi. This means a printer can print 600 "pixels in one inch" while a monitor has something like 10. So if you print in MM_TEXT mode where one logical unit means one pixel the display might work for the screen but the printed images will be very small or invisible at all. So you should either use some of the MM_[HI/LO][ENGLISH/METRIC] map modes:

MM_HIMETRIC: Each logical unit is converted to 0.01 millimeterMM_LOMETRIC: Each logical unit is converted to 0.1 millimeterMM_HIENGLISH: Each logical unit is converted to 0.001 inchesMM_LOENGLISH: Each logical unit is converted to 0.01 inches

These are usefull when printing charts and tables:

MM_TWIPS is very usefull when printing with text. Each logical unit is converted to 1/20 of a point. A piont is the unit used in font measuring. The size which you select in Word for example is in points. Also the standard "Select font" dialog uses this measure.

-or-

Get the sizes of the sheet of paper and size your output according to it. Here's how to do this:

// GetDeviceCaps can give much important information about the display deviceint horzsize=pDC->GetDeviceCaps(HORZSIZE); // gives the width of the physical display in millimetersint vertsize=pDC->GetDeviceCaps(VERTSIZE); // gives the height of the physical display in millimetersint horzres=pDC->GetDeviceCaps(HORZRES); // gives the height of the physical display in pixelsint vertres=pDC->GetDeviceCaps(VERTRES); // gives the width of the physical display in pixelsint hdps=horzres/horzsize; // calculate the horizontal pixels per millimeterint vdps=vertres/vertsize; // calculate the verticalpixels per millimeter// note 1: if the resolution of the printer is 600X600, 1200X1200 or anything ***X*** hdps will be equal to vdps// note 2: multiply hdps and vdps by 2.54 to receive the dpi// since you didn't set the map mode it is still MM_TEXT// now when calculating sizes in millimeters multiply them by hdps or vdps and the sizes will be correctCRect rectDraw=pInfo->m_rectDraw;// this assumes the page is A$, the printer can print without margins// (this is not very good to assume but will work for now)// and the page is in landscape mode (297mmx210mm)CRect rectOut(rectDraw.left,rectDraw.top,rectDraw.left+297*hdps,rectDraw.top+210*vdps);// now print only inside this rectangle...

Page 47: MFC Tutorial

Advanced settings - MFC Printing:

   Maybe your printer supports many types of paper(A3, A4, B3 ,B4, Envelope, Letter, etc.) but you want your program to print on a certain type. You can set the printer defaults but sometimes the user may need the defaults or you can't set al the user's settings. In this case it is best to set the type of paper and orientation (portrait or landscape) in your program. The users won't have to worry about setting anything. But this is not as simple as it sounds. The pInfo has a member m_pPD of type CPrintDialog* which is a pointer to the printer settings dialog. You can use it to make changes before the user opens the dialog or when starting the print job. The key is m_pPD->m_pd which is PRINTDLG struct(actually it is a pseudanim but it the same for our purposes). It contains the hDevMode member which is a handle to a DEVMODE data structure containing information about the device initialization and environment of a printer.

   Through this  pInfo->m_pPD->m_pd.hDevMode (The path to hDevMode) handle you gain total control over the printing process but since it is a handle you can't just set it to what you want. You have to lock the memory to it and access it instead. But before the DoPreparePrinting function the handle is not set so you can't access the data. If you access it after calling DoPreparePrinting the changes will take effect at the next print job. So you have to do something else. My best solution was to take the code of DoPreparePrinting and modify it according to my needs.  

   If you want to control the defaults when the user selects Print Setup from File menu you have to associate the message with your function. Press Ctrl+W to open ClassWizard. Select CtutorialApp for Class name and ID_FILE_PRINT_SETUP for Object ID. Associate the COMMAND message with a function(the default is OnFilePrintSetup). Now add this code instead whatever is there:

CPrintDialog pd(TRUE);if (GetPrinterDeviceDefaults(&pd.m_pd)){LPDEVMODE dev = pd.GetDevMode();GlobalUnlock(dev);dev->dmOrientation=DMORIENT_LANDSCAPE;dev->dmPaperSize=DMPAPER_A4;}DoPrintDialog(&pd); 

The default function does only this:

CPrintDialog pd(TRUE);DoPrintDialog(&pd); 

The function has to be a CTutorialApp member because DoPrintDialog is only accessible from the application class (try to put this code in a member function of the View or MainFrame and see the error messages).

   Sometimes you will want to know if the user has right clicked on a document and selected print from there. There is a variable cmdInfo in InitInstance. It contains the information about how is the program started. Unfortunately it is processed by ProcessShellCommand which you have to copy and paste in InitInstance. Have in mind that ProcessShellCommand returns a boolean value in several cases and you don?t want this to happen in InitInstance. Just replace all the ?return ?? lines with this bResult=? where bResult is a boolean variable. Then when the copied function ends just decide what to do with the result you have in bResult (it will be the same as if you have called the function). Now back to ProcessShellCommand. It has a case block and one of the cases is this:

case CCommandLineInfo::FilePrintTo:case CCommandLineInfo::FilePrint:

Page 48: MFC Tutorial

Just add your code before or after the original depending on your needs

   It?s always best to run the code step by step in the debugger. Thus you can see which part of code is executed currently and the order of called functions ending with the current(call stack). Example: You want to see what and when happens in OnPreparePrinting. The way to check is to set a breakpoint at the beginning of the function body after the opening curly bracket ( ?{? ), start the program in the debugger by pressing F5(you will have to build in Win32 Debug mode. Then when the program stops in the function use ?Step Into? to go to the desired function and copy its source.

Note: If you add a breakpoint in some functions like the ones involved in printing the program will break only if you start printing/open the print setup dialog. 

Please download the sample project here. 

 

CTabCtrl   

   Tab control managed using CTabCtrl MFC class is a good replacement candidate for Property Sheets. But these Tab Controls are less used and discussed still less. This article explains how to use the CTabCtrl class for manipulating a Tab Control and hold 2 different dialog boxes. The sample given here can be extended to add more dialog boxes.

   The article had been revised to support the child controls inside the dialog boxes placed on the CTabCtrl. There had been a lot of queries from our visitors on this issue. We had not been able to reply to each one of them. Sorry about that. We've revised the article.

 

Creating the Tab Holder Dialog for CTabCtrl:

   As a first step for using this tab control, a placeholder dialog needs to be created. This place holder could be a Form View or a Dialog box. This example illustrates CTabCtrl usage with a Dialog box.

Create an MFC Dialog based application. Modify the Title of the dialog to "Tab control Holder Dialog". This is to differentiate the parent dialog from the rest of the child dialog boxes.

Place a Tab Control on the dialog box. The article uses the ID of the tab control as IDC_TABCTRL1.

A derived class of CTabCtrl has to be created now. This class will handle initializing the tab sheet dialogs, activating each of them at every selection etc.,

Creating the Derived class for CTabCtrl:

Open the class wizard by pressing the key combination Ctrl + W. Click on the Add Class --> New button. We'll use this interface to add a derived class for CTabCtrl.

Enter the name of the derived class (of CTabCtrl ) in the empty text box. This article uses MyTabCtrl as the class name for the derived class. Select the CTabCtrl as the Base Class. Two Files will be created as MyTabCtrl.h and MyTabCtrl.cpp.

Add the following data and function members to the MyTabCtrl class, in the MyTabCtrl.h file.

//Array to hold the list of dialog boxes/tab pages for CTabCtrlint m_DialogID[2];

Page 49: MFC Tutorial

//CDialog Array Variable to hold the dialogs CDialog *m_Dialog[2];

//Function to Create the dialog boxes during startupvoid InitDialogs();

//Function to activate the tab dialog boxes void ActivateTabDialogs();

Open the class wizard for MyTabCtrl and add a handler for TCN_SELCHANGE event (of CTabCtrl). This can be done through the Class Wizard --> Message Maps tab.

Open the MyTabCtrl.cpp file and paste the following functions. All these functions except ActivateTabDialogs() and InitDialogs() are simple modifications to the original functions, which were generated by the wizard.

We will have to include the Child dialog header files in this MyTabCtrl.cpp.

//Constructor for the class derived from CTabCtrlMyTabCtrl::MyTabCtrl(){   m_DialogID[0] =IDD_DIALOG1;   m_DialogID[1] =IDD_DIALOG2;

   m_Dialog[0] = new MyDlg1();   m_Dialog[1] = new MyDlg2();

   m_nPageCount = 2;

}

//This function creates the Dialog boxes oncevoid MyTabCtrl::InitDialogs(){m_Dialog[0]->Create(m_DialogID[0],GetParent());m_Dialog[1]->Create(m_DialogID[1],GetParent());}

//Selection change event for the class derived from CTabCtrlvoid MyTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult) {   // TODO: Add your control notification handler code here   ActivateTabDialogs();   *pResult = 0;}

void MyTabCtrl::ActivateTabDialogs(){  int nSel = GetCurSel();  if(m_Dialog[nSel]->m_hWnd)     m_Dialog[nSel]->ShowWindow(SW_HIDE);

  CRect l_rectClient;  CRect l_rectWnd;

Page 50: MFC Tutorial

  GetClientRect(l_rectClient);  AdjustRect(FALSE,l_rectClient);  GetWindowRect(l_rectWnd);  GetParent()->ScreenToClient(l_rectWnd);  l_rectClient.OffsetRect(l_rectWnd.left,l_rectWnd.top);  for(int nCount=0; nCount < m_nPageCount; nCount++){     m_Dialog[nCount]->SetWindowPos(&wndTop, l_rectClient.left, l_rectClient.top, l_rectClient.Width(), l_rectClient.Height(), SWP_HIDEWINDOW);  }  m_Dialog[nSel]->SetWindowPos(&wndTop, l_rectClient.left, l_rectClient.top, l_rectClient.Width(), l_rectClient.Height(), SWP_SHOWWINDOW);

  m_Dialog[nSel]->ShowWindow(SW_SHOW);

}

Now the above can be enough for a basic tab control with CTabCtrl, which can be made to hold 2 dialog boxes or tab sheets.

   The next step will be to create two dialog boxes which will be used as the Tab sheets.

Creating the Tab Sheets for CTabCtrl:

Create two Dialog boxes by using the Visual Studio --> Menu --> Insert Resource --> Dialog. Ensure that their ids are IDD_DIALOG1, IDD_DIALOG2. The sample in this article uses these IDs

marked in Blue. Put some controls or some sample text on the dialog boxes for differentiating both of them from

each other. For both the dialogs, set the Properties Dialog --> Styles --> Style equal to Child. Also Un-check the Properties Dialog --> Styles --> Title bar and System Menu. They should be

set to false. Because the tab sheets cannot have a title bar. Set the Properties Dialog --> More Styles --> Visible style to True. For both the dialogs create two dialog classes by using the class wizard.

Initializing and Activating the Tab Sheets in CTabCtrl:

Open the Parent dialog which holds the Tab Control. Open the class wizard. In the Class wizard --> Member Variables tab, add a variable for the Tab control. Use the

MyTabCtrl as the class representing the Tab Control, instead of CTabCtrl. This sample uses the variable name as m_tbCtrl. The greencolored items relate the tab control ID and the member variable for the tab control.

After this, in the OnInitDialog of the same class, add the following lines of code.

          m_tbCtrl.InitDialogs();m_tbCtrl.InsertItem(0,"Sample Tab 1");m_tbCtrl.InsertItem(1,"Sample Tab 2");

m_tbCtrl.ActivateTabDialogs();   Now the application is ready to be launched. Build the application and execute it. The application will have 2 tab sheets and upon clicking the tab buttons, the dialogs get activated correspondingly.

Page 51: MFC Tutorial

   Do not forget to include the Child dialog header files in the MytabCtrl.cpp.

   There will be a small problem if you press ESC key or Enter keys. The tab sheets will disappear. To avoid this refer to,  How to avoid closing of the dialog boxes when ESCAPE key or ENTER key is pressed.

   The sample program for the above article is available at CTabCtrl Sample.

Note:

   There was a problem in the sample code