Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C++
Article

Introduce Yourself to VC++

Rate me:
Please Sign up or sign in to vote.
3.98/5 (106 votes)
3 Jan 200524 min read 489.1K   3.6K   144   47
To the Beginner to begin. In this article, I have given some information about the following title which I came across while studying. This may help you.

Image 1

Contents

Part I

  1. Introduction to MFC
  2. Messages and Events
  3. Windows Messages
  4. Keyboard Messages
  5. Mouse Messages
  6. Conditional Messages
  7. Sending Messages

Part II

  1. Frames Fundamentals
  2. Windows Resources
  3. The Document/View Architecture
  4. The Graphical Device Interface
  5. GDI Accessories and Tools: Colors

Part III

  1. GDI Accessories and Tools: Pens
  2. GDI Orientation and Transformations
  3. Characteristics of a Window's Frame
  4. Fundamentals of Windows Controls
  5. Dialog Boxes
  6. Forms

Part IV

  1. Controls Designs on Forms and Dialog Boxes
  2. Strings
  3. Building from the Command Line
  4. SQL Server Data Entry
  5. A Popup Window

All the titles are covered in the Document format, only some of them are in the web page for sample.

Introduction to MFC

Introduction to Applications

The Microsoft Foundation Class (MFC) library is a set of data types, functions, classes, and constants used to create applications for the Microsoft Windows family of operating systems.

The first thing you should do to start a program is to create an application. In Win32, an application is created by a call to the WinMain() function and building a WNDCLASS or WNDCLASSEX structure. In MFC, this process has been resumed in a class called CWinApp (Class-For-A-Windows-Application). Based on this, to create an application, you must derive your own class from CWinApp.

An application by itself is an empty thing that only lets the operating system know that you are creating a program that will execute on the computer. It doesn't display anything on the screen. If you want to display something, the CWinApp class provides the InitApplication() method that you must override in your class. InitApplication() is a Boolean method. If it succeeds in creating the application, it returns TRUE. If something went wrong when trying to create the application, it would return FALSE. The minimum skeleton of an application would appear as follows:

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

BOOL CExerciseApp::InitInstance()
{
    return TRUE;
}

After creating the application, to make it available to other parts of the program, you must declare a global variable of your class. It is usually called theApp but you can call it anything you want.

The fundamental classes of MFC are declared in the afxwin.h header file. Therefore, this is the primary header you may have to add to each one of your applications. Based on this, a basic application can be created as follows:

#include <AFXWIN.H>

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

BOOL CExerciseApp::InitInstance()
{
    return TRUE;
}

CExerciseApp theApp;

Introduction to Frames

As its name implies, a frame of a window includes the borders, the location, and the dimensions of a window. There are two types of MFC applications: those that use a frame and those that don't. A frame-based application uses a concept known as the Document/View Architecture. This allows the frame to serve as a place holder for other parts of an application (such as the document and the view).

To create a frame, the MFC library provides various classes. One of these is called CFrameWnd and it is the most commonly used frame class. To use a frame, you can derive your own class from CFrameWnd as follows:

class CApplicationFrame : public CFrameWnd
{
};

Because there can be many frames or various types of frames in an application, the first or main frame is usually called CMainFrame, we will follow the same habit but you can call your frame class anything you want:

class CMainFrame : public CFrameWnd
{
};

The skeleton of this frame only serves as a foundation for your class. You must actually create a window frame that would display to the user. To create a window frame, the CFrameWnd class provides the Create() method. Its syntax is:

BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
       DWORD dwStyle = WS_OVERLAPPEDWINDOW, const RECT& rect = rectDefault,
       CWnd* pParentWnd = NULL, LPCTSTR lpszMenuName = NULL, DWORD dwExStyle = 0,
       CCreateContext* pContext = NULL );

As you can see, the only two required arguments are the class name and the window name. We will come back to all these arguments when we study window classes in more detail. For now, a minimum frame can be created by simply passing the class name as NULL and the window name with a null-terminated string. Here is an example:

class CMainFrame : public CFrameWnd
{
public:
    CMainFrame();
};

CMainFrame::CMainFrame()
{
    Create(NULL, "MFC Fundamentals");
}

In order to provide a window to the application, you must create a thread. This would be done using the CWinThread class. To make this a little easy, CWinThread is equipped with a public member variable called m_pMainWnd. This variable can be used to create a thread for the main window of the application. One of its advantages is that it makes sure that your application terminates smoothly when the user decides to close it. CWinThread is the base class of CWinApp and therefore makes m_pMainWnd available to any CWinThread derived class such as CFrameWnd. Based on this, to create a thread for the main window to display, you can assign a pointer of your frame class to m_pMainWnd. After this assignment, m_pMainWnd can be used as the window object to display the frame, which is usually done by calling the ShowWindow() method. This would be done as follows:

BOOL CExerciseApp::InitInstance()
{
    m_pMainWnd = new CMainFrame;
    m_pMainWnd->ShowWindow(SW_NORMAL);

    return TRUE;
}

This application was created as follows:

  1. Start Microsoft Visual C++ or Visual Studio.
  2. On the main menu, click either File -> New... or File -> New Project...
  3. In the New dialog box, click Projects or, in the New Project dialog box, click Visual C++ Projects.
  4. Click either Win32 Application or Win32 Project.
  5. Type a name for the application in the Name edit box. An example would be MFCFundamentals1.
  6. Click OK.
  7. Specify that you want to create a Windows Application as an Empty Project and click Finish.
  8. To use MFC in MSVC 6, click Project -> Settings... In MSVC 7, in the Solutions Explorer property page, right-click the project name (MFCFundamentals1) and click Properties.
  9. In the Microsoft Foundation Classes combo box or in the Use of MFC combo box, select Use MFC In A Shared DLL.
  10. Click OK.
  11. To add a file to create the application, on the main menu of MSVC 6, click File -> New... or, for MSVC 7, on the main menu, click Project -> Add New Item...
  12. Click C++ (Source) File and, in the Name edit box, type a name for the file. An example would be Exercise.
  13. Click OK or Open.
  14. In the empty file, type the above code:
    #include <AFXWIN.H>
    
    class CExerciseApp : public CWinApp
    {
    public:
      virtual BOOL InitInstance();
    };
    
    class CMainFrame : public CFrameWnd
    {
    public:
      CMainFrame();
    };
    
    CMainFrame::CMainFrame()
    {
      Create(NULL, "MFC Fundamentals");
    }
    
    BOOL CExerciseApp::InitInstance()
    {
      m_pMainWnd = new CMainFrame;
      m_pMainWnd->ShowWindow(SW_NORMAL);
    
      return TRUE;
    }
    
    CExerciseApp theApp;
  15. Execute the application.
  16. Close it and return to MSVC.

Messages and Events

Introduction to Messages

Some of your applications will be made of various objects. Most of the time, more than one application is running on the computer. These two scenarios mean that the operating system is constantly asked to perform some assignments. Because there can be so many requests presented unpredictably, the operating system leaves it up to the objects to specify what they want, when they want it, and what behavior or result they expect. The Microsoft Windows operating system cannot predict what kinds of requests one object would need to be taken care of and what type of assignment another object would need. To manage all these assignments and requests, the objects send messages, one message at a time, to the operating system. For this reason, Microsoft Windows is said to be a message-driven operating system.

The messages are divided in various categories but as mentioned already, each object has the responsibility to decide what message to send and when. Therefore, most of the messages we will review here are part of a window frame. Others will be addressed when necessary.

Once a control has composed a message, it must send it to the right target which could be the operating system. In order to send a message, a control must create an event. It is also said to fire an event. To make a distinction between the two, a message's name usually starts with WM_ which stands for Windows message. The name of an event usually starts with On which indicates an action. Remember, the message is what needs to be sent. The event is the action of sending the message.

A Map of Messages

For the compiler to manage messages, they should be included in the class definition. The list of messages starts on a section driven by, but that ends with, the DECLARE_MESSAGE_MAP macro. The section can be created as follows:

#include <AFXWIN.H>

class CSimpleFrame : public CFrameWnd
{
public:
    CSimpleFrame();

    DECLARE_MESSAGE_MAP()
};

The DECLARE_MESSAGE_MAP macro should be provided at the end of the class definition. The actual messages (as we will review them shortly) should be listed just above the DECLARE_MESSAGE_MAP line. This is just a rule. In some circumstances, and for any reason, you may want, or have, to provide one message or a few messages under the DECLARE_MESSAGE_MAP line.

To implement the messages, you should/must create a table of messages that your program is using. This table uses two delimiting macros. It starts with a BEGIN_MESSAGE_MAP and ends with a END_MESSAGE_MAP macro. The BEGIN_MESSAGE_MAP macro takes two arguments, the name of your class and the MFC class you derived your class from. An example would be:

BEGIN_MESSAGE_MAP(CSimpleFrame, CFrameWnd)

Like the DECLARE_MESSAGE_MAP macro, END_MESSAGE_MAP takes no argument. Its job is simply to specify the end of the list of messages. The table of messages can be created as follows:

#include <AFXWIN.H>
#include "resource.h"

class CMainFrame : public CFrameWnd
{
public:
    CMainFrame ();

    DECLARE_MESSAGE_MAP()
};

CMainFrame::CMainFrame()
{
    LoadFrame(IDR_MAINFRAME);
}

class CMainApp: public CWinApp
{
public:
    BOOL InitInstance();
};

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

END_MESSAGE_MAP()

BOOL CMainApp::InitInstance()
{
    m_pMainWnd = new CMainFrame ;
    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();

    return TRUE;
}

CMainApp theApp;

There are various categories of messages the operating system receives. Some of them come from the keyboard, some from the mouse, and some others from various other origins. For example, some messages are sent by the application itself while some other messages are controlled by the operating system.

Practical Learning: Creating a Map of Messages

  1. Create a new and empty Win32 Project located in C:\Programs\MSVC Exercises and set its name to Messages1.
  2. Specify that you want to use MFC in a Shared DLL.
  3. Create a C++ file and name it Exercise.
  4. To create a frame for the window, in the Exercise.cpp file, type the following:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
    Create(NULL,"WindowsApplication",WS_OVERLAPPEDWINDOW, 
                           CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    
    END_MESSAGE_MAP()
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  5. Test the application and return to MSVC.

Windows Messages

Window Creation

WM_CREATE: When an object, called a window, is created, the frame that creates the object sends a message identified as ON_WM_CREATE. Its syntax is:

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

This message calls the CFrameWnd::Create() method to create a window. To do that, it takes one argument, which is a pointer to a CREATESTRUCT class. The CREATESTRUCT class provides all the information needed to create a window. It is defined as follows:

typedef struct tagCREATESTRUCT {
   LPVOID    lpCreateParams;
   HANDLE    hInstance;
   HMENU     hMenu;
   HWND      hwndParent;
   int       cy;
   int       cx;
   int       y;
   int       x;
   LONG      style;
   LPCSTR    lpszName;
   LPCSTR    lpszClass;
   DWORD     dwExStyle;
} CREATESTRUCT;

This class provides the same type of information as the WNDCLASS object. When sending the OnCreate() message, the class is usually created without your intervention but when calling it, you should check that the window has been created. This can be done by checking the result returned by the OnCreate() message from the parent class. If the message returns 0, the window was created. If it returns -1, the class was not created or it would simply be destroyed. This can be done as follows:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    // Create the window and make sure it doesn't return -1
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    // else is implied
    return 0;
}

To use this message, in the class definition, type its syntax. In the message table, type the name of the message ON_WM_CREATE():

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_WM_CREATE()
END_MESSAGE_MAP()

Practical Learning: Creating a Window

  1. To create an ON_WM_CREATE message, change the file as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        // Call the base class to create the window
        if( CFrameWnd::OnCreate(lpCreateStruct) == 0)
        {
            // If the window was successfully created, 
            //let the user know
            MessageBox("The window has been created!!!");
            // Since the window was successfully created, return 0
            return 0;
        }
        // Otherwise, return -1
        return -1;
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the application and return to MSVC.

Window's Showing State

WM_SHOWWINDOW: After creating a window, it needs to be displayed. Also, if the window was previously hidden, you can decide to show it. On the other hand, if a window is displaying, you may want to hide it, for any reason you judge necessary. To take any of these actions, that is, to show or hide a window, you must send the ON_WM_SHOWWINDOW message. The syntax of this message is:

afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);

When using this message, bShow, a boolean argument, determines what state to apply to the window. If it is TRUE, the window needs to be displayed. If it is FALSE, the window must be hidden.

nStatus is a positive integer that can have one of the following values:

  • SW_PARENTCLOSING: If the window that sent this message is a frame, the window is being minimized. If the window that sent this message is hosted by another window, the window is being hidden.
  • SW_PARENTOPENING: If the window that sent this message is a frame, the window is being restored. If the window that sent this message is hosted by another window, the window is displaying.
  • 0: The message was sent from a CWnd::ShowWindow() method.

Practical Learning: Showing a Window

  1. To maximize the window at startup, change the program as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_SHOWWINDOW()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        // Call the base class to create the window
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) 
    {
        CFrameWnd::OnShowWindow(bShow, nStatus);
        
        // TODO: Add your message handler code here
        ShowWindow(SW_MAXIMIZE);
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the program and return to MSVC.

Window Activation

WM_ACTIVATE: When two or more windows are running on the computer, only one can receive input from the user, that is, only one can actually be directly used at one particular time. Such a window has a title bar with the color identified in Control Panel as Active Window. The other window(s), if any, display(s) its/their title bar with a color called Inactive Window.

To manage this setting, the windows are organized in a three dimensional coordinate system and they are incrementally positioned on the Z coordinate, which defines the (0, 0, 0) origin on the screen (actually on the top-left corner of your monitor) with Z coordinate coming from the screen towards you.

In order to use a window other than the one that is active, you must activate it. To do this, you can send a message called ON_WM_ACTIVATE. The syntax of this message is:

afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);

This message indeed does two things: it activates a window of your choice, or brings it to the front, and deactivates the other window(s) or sends it/them to the back of the window that is being activated. The nState argument specifies what action to apply. It is a constant that can assume one of the following values:

  • WA_ACTIVE: Used to activate a window without using the mouse, may be by pressing Alt + Tab.
  • WA_INACTIVE: Used to deactivate a window.
  • WA_CLICKACTIVE: Used to activate a window using the mouse.

If this message was sent by the window that is being activated, pWndOther designates the other window, the one being deactivated. If this message was sent by the window that is being deactivated, pWndOther designates the other window, the one being activated.

If the window that sent this message is being restored from its deactivation, pass the bMinimized value as TRUE.

When calling this message, before implementing the custom behavior you want, first call its implementation from the parent class:

void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
{
    CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
    
    // TODO: Add your message handler code here
}

Practical Learning: Activating a Window

  1. To activate a window that has been created, change the file as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
        afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
    Create(NULL, "WindowsApplication", WS_OVERLAPPEDWINDOW, 
                             CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_SHOWWINDOW()
        ON_WM_ACTIVATE()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        // Call the base class to create the window
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) 
    {
        CFrameWnd::OnShowWindow(bShow, nStatus);
        
        // TODO: Add your message handler code here
        //ShowWindow(SW_SHOW);
    }
    
    void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
    {
        CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
        
        // TODO: Add your message handler code here
        switch( nState )
        {
        case WA_ACTIVE:
            SetWindowText("This window has been activated, without the mouse!");
            break;
        case WA_INACTIVE:
            SetWindowText(
                "This window has been deactivated and cannot be changed now!!");
            break;
        case WA_CLICKACTIVE:
            SetWindowText("This window has been activated using the mouse!!!");
            break;
        }    
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the application. While it is displaying, open Notepad.
  3. Display each window using the mouse. Then activate your window using Alt+Tab.
  4. Return to MSVC.

Window Painting

WM_PAINT: Whether you have just created a window or you want to show it, you must ask the operating system to display it, showing its appearance. To display such a window, the operating system would need its location (left and top measures) and its dimension (width and height). This is because the window must be painted. Also, if the window was hidden somewhere such as behind another window or was minimized, when it comes up, the operating system needs to paint it. To do this, the window that needs to be painted must send a message called ON_WM_PAINT. This message does not return anything, but in its body, you can define what needs to be painted and how you want the job to be done. The syntax of this message is simply:

afx_msg void OnPaint()

Practical Learning: Using the Paint Message

  1. To use the structure of the WM_PAINT message, change the program as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
        afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
        afx_msg void OnPaint();
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_SHOWWINDOW()
        ON_WM_ACTIVATE()
        ON_WM_PAINT()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) 
    {
        CFrameWnd::OnShowWindow(bShow, nStatus);
        
        // TODO: Add your message handler code here
        //ShowWindow(SW_SHOW);
    }
    
    void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
    {
        CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
        
        // TODO: Add your message handler code here
        switch( nState )
        {
        case WA_ACTIVE:
            SetWindowText("This window has been activated, without the mouse!");
            break;
        case WA_INACTIVE:
            SetWindowText(
                "This window has been deactivated and cannot be changed now!!");
            break;
        case WA_CLICKACTIVE:
            SetWindowText("This window has been activated using the mouse!!!");
            break;
        }    
    }
    
    void CMainFrame::OnPaint() 
    {
        CFrameWnd::OnPaint();
    
        SetWindowText("The window has been painted<==>");
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the application and return to MSVC.

Window Sizing

WM_SIZE: When using an application, one of the actions a user can perform on a window is to change its size, provided the window allows this. Also, from time to time, if the window allows it, the user can minimize, maximize, or restore a window. Whenever any of these actions occur, the operating system must keep track of the size of a window. When the size of a window has changed, the window sends the ON_WM_SIZE message. Its syntax is:

afx_msg void OnSize(UINT nType, int cx, int cy);

The nType argument specifies what type of action to take. It can have one of the following values:

  • SIZE_MINIMIZED: The window has been minimized.
  • SIZE_MAXIMIZED: The window has been maximized.
  • SIZE_RESTORED: The window has been restored from being maximized or minimized.
  • SIZE_MAXHIDE: Another window, other than this one, has been maximized.
  • SIZE_MAXSHOW: Another window, other than this one, has been restored from being maximized or minimized.

The cx argument specifies the new width of the client area of the window.

The cy argument specifies the new height of the client area of the window.

To use this message, you should first call its implementation in the parent class before implementing the behavior you want. This can be done as follows:

void CAnyWindow::OnSize(UINT nType, int cx, int cy) 
{
    CParentClass::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here
}

WM_SIZING: While the user is changing the size of a window, a message called ON_WM_SIZING is being sent. Its syntax is:

afx_msg void OnSizing(UINT nSide, LPRECT lpRect);

When a user is resizing a window, he or she typically drags one of the borders or corners on a direction of his or her choice. The first argument, nSize, indicates what edge is being moved when resizing the window. It can have one of the following values:

  • WMSZ_BOTTOM: Bottom edge
  • WMSZ_BOTTOMLEFT: Bottom-left corner
  • WMSZ_BOTTOMRIGHT: Bottom-right corner
  • WMSZ_LEFT: Left edge
  • WMSZ_RIGHT: Right edge
  • WMSZ_TOP: Top edge
  • WMSZ_TOPLEFT: Top-left corner
  • WMSZ_TOPRIGHT: Top-right corner

Window Moving

WM_MOVE: When a window has been moved, the operating system needs to update its location. Therefore, the window sends a message called ON_WM_MOVE. Its syntax is:

afx_msg void OnMove(int x, int y);

The first argument of this message specifies the left horizontal location of the left border of the window after the window has been moved. The second argument represents the vertical position of the top border of the window after the window has been moved.

If you want to send this message, you should first call its implementation in the parent class.

WM_MOVING: While the user is moving a window, it (the window) sends an ON_WM_MOVING message. Its syntax is:

afx_msg void OnMoving( UINT nSide, LPRECT lpRect );

The first argument, nSide, is the edge of the window that is being moved. It is the same as for the ON_MOVE message.

The lpRect is the target dimension of the window that is being moved. That is, it contains the new dimensions of the window as it is being moved.

Practical Learning: Moving a Window

  1. To see the effect of moving a window, change the file as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void O
    nShowWindow(BOOL bShow, UINT nStatus);
        afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
        afx_msg void OnPaint();
        afx_msg void OnSize(UINT nType, int cx, int cy);
        afx_msg void OnMove(int x, int y);
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_SHOWWINDOW()
        ON_WM_ACTIVATE()
        ON_WM_PAINT()
        ON_WM_SIZE()
        ON_WM_MOVE()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) 
    {
        CFrameWnd::OnShowWindow(bShow, nStatus);
        
        // TODO: Add your message handler code here
        //ShowWindow(SW_SHOW);
    }
    
    void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
    {
        CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
        
        // TODO: Add your message handler code here
        switch( nState )
        {
        case WA_ACTIVE:
            SetWindowText("This window has been activated, without the mouse!");
            break;
        case WA_INACTIVE:
            SetWindowText(
              "This window has been deactivated and cannot be changed now!!");
            break;
        case WA_CLICKACTIVE:
            SetWindowText("This window has been activated using the mouse!!!");
            break;
        }    
    }
    
    void CMainFrame::OnPaint() 
    {
        CFrameWnd::OnPaint();
    
        SetWindowText("The window has been painted<==>");
    }
    
    void CMainFrame::OnSize(UINT nType, int cx, int cy) 
    {
    /*    CMainFrame::OnSize(nType, cx, cy);
        
        // TODO: Add your message handler code here
        char *MsgToShow = new char[20];
        char *MsgCoord  = new char[20];
        
        switch(nType)
        {
        case SIZE_MINIMIZED:
            strcpy(MsgToShow, "Minimized ");
            break;
        case SIZE_MAXIMIZED:
            strcpy(MsgToShow, "Maximized ");
            break;
        case SIZE_RESTORED:
            strcpy(MsgToShow, "Restored ");
            break;
        case SIZE_MAXHIDE:
            strcpy(MsgToShow, "Maximized Not Me ");
            break;
        case SIZE_MAXSHOW:
            strcpy(MsgToShow, "Restored Not Me ");
            break;
        }
    
        sprintf(MsgCoord, "Left = %d | Top = %d", cx, cy);
        strcat(MsgToShow, MsgCoord);
        SetWindowText(MsgToShow);
    */
    }
    
    void CMainFrame::OnMove(int x, int y) 
    {
        CFrameWnd::OnMove(x, y);
        
        // TODO: Add your message handler code here
        char *MsgCoord  = new char[20];
    
        sprintf(MsgCoord, "Left = %d | Top = %d", x, y);
        
        SetWindowText(MsgCoord);
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the application:

    Image 2

  3. Return to MSVC

Window Destruction

WM_DESTROY: Once the window has been used and the user has closed it, the window must send a message to the operating system to destroy it. The message sent is called ON_WN_DESTROY and its syntax is:

afx_msg void OnDestroy( );

This message takes no argument but you can use its body to do any last minute assignment as needed. For example, you can use it either to prevent the window from being closed or you can enquire whether the user really wants to close the window.

Command Messages

Definition

One of the main features of a graphical application is to present Windows controls and resources that allow the user to interact with the machine. Examples of controls that we will learn are buttons, list boxes, combo boxes, etc. One type of resource we introduced in the previous lesson is the menu. Such controls and resources can initiate their own messages when the user clicks them. A message that emanates from a Windows control or a resource is called a command message.

Creating a Command Message.

You can start by declaring a framework method. Here is an example:

afx_msg void OnLetItGo();

Then you can define the method as you see fit:

void CMainFrame::OnLetItGo()
{
    // Something to do here
}

The framework allows you to associate a member function to a command message. This is done using the ON_COMMAND macro. Its syntax:

ON_COMMAND(IDentifier, MethodName);

The first argument, IDentifier, of this macro must be the identifier of the menu item or Windows control you want to associate with a method. The second argument, MethodName, must be the name of the member function that will implement the action of the menu item or Windows control such as a button. Imagine you have a menu item Identified as ID_ACTION_LETITGO that you want to associate with the above OnLetItGo() method. You can use the ON_COMMAND macro as follows:

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_COMMAND(ID_ACTION_LETITGO, OnLetItGo)
END_MESSAGE_MAP()

In the same way, you can create as many command messages as necessary.

Keyboard Messages

The Key Down Effect

When we think of the keyboard, the first thing that comes in mind is to press a key. When a keyboard key is pressed, a message called WM_KEYDOWN is sent. Its syntax is:

afx_msg void OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags );

The first argument, nChar, specifies the virtual code of the key that was pressed.

The second argument, nRepCnt, specifies the number of times counted repeatedly as the key was held down.

The nFlags argument specifies the scan code, extended-key flag, context code, previous key-state flag, and transition-state flag.

Practical Learning: Sending Key Down Messages

  1. To experiment with the ON_KEYDOWN message, change the file as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_KEYDOWN()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
        switch(nChar)
        {
        case VK_RETURN:
            SetWindowText("You pressed Enter");
            break;
        case VK_F1:
            SetWindowText("Help is not available at the moment");
            break;
        case VK_DELETE:
            SetWindowText("Can't Delete This");
            break;
        default:
            SetWindowText("Whatever");
        }
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the application and return to MSVC.

The Key Up Effect

When we think of the keyboard, the first thing that comes in mind might refer to typing, which consists of pressing a key and releasing it immediately. As this is done, a key is pressed down and brought back up. When the user is releasing a key a WM_KEYUP message is sent. Its syntax is:

afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);

The first argument, nChar, is the code of the key that was pressed. The second argument, nRepCnt, specifies the number of times counted repeatedly as the key was held down.

The nFlags argument specifies the scan code, extended-key flag, context code, previous key-state flag, and transition-state flag.

Mouse Messages

Introduction

The mouse is another object that is attached to the computer allowing the user to interact with the machine. The mouse and the keyboard can each accomplish some tasks that are not normally available on the other and both can accomplish some tasks the same way.

The mouse is equipped with two, three, or more buttons. When a mouse has two buttons, one is usually located on the left and the other is located on the right. When a mouse has three buttons, one is in the middle of the other two. The mouse is used to select a point or position on the screen. Once the user has located an item, which could also be an empty space, a letter or a word, he or she would position the mouse pointer on it. To actually use the mouse, the user would press either the left, the middle (if any), or the right button. If the user presses the left button once, this action is called Click. If the user presses the right mouse button, the action is referred to as Right-Click. If the user presses the left button twice and very fast, the action is called Double-Click.

Mouse-Down Messages

Imagine the user has located a position or an item on a document and presses one of the mouse buttons. While the button is pressed and is down, a button-down message is sent, depending on the button that was pressed. If the left mouse button was pressed, an ON_WM_LBUTTONDOWN message is sent. The syntax of this message is:

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

If the right mouse button was pressed, an ON_WM_RBUTTONDOWN message is sent. Its syntax is:

afx_msg void OnRButtonDown(UINT nFlags, CPoint point);

The first argument, nFlags, specifies what button is down or what keyboard key and what mouse button are down. It is a constant integer that can have one of the following values:

  • MK_CONTROL: A Ctrl key is held down.
  • MK_LBUTTON: The left mouse button is down.
  • MK_MBUTTON: The middle mouse button is down.
  • MK_RBUTTON: The right mouse button is down.
  • MK_SHIFT: A Shift key is held down.

The point argument specifies the measure from the left and the top borders of the window to the mouse pointer.

Practical Learning: Sending a Mouse Down Message

  1. To experiment with the mouse down effect, change the program as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
        afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_KEYDOWN()
        ON_WM_LBUTTONDOWN()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
        switch(nChar)
        {
        case VK_RETURN:
            SetWindowText("You pressed Enter");
            break;
        case VK_F1:
            SetWindowText("Help is not available at the moment");
            break;
        case VK_DELETE:
            SetWindowText("Can't Delete This");
            break;
        default:
            SetWindowText("Whatever");
        }
    }
    
    void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) 
    {
        char *MsgCoord  = new char[20];
    
        sprintf(MsgCoord, "Left Button at P(%d, %d)", point.x, point.y);
        
        SetWindowText(MsgCoord);
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Test the program:

    Image 3

  3. Return to MSVC.

The Mouse-Up Messages

After pressing a mouse button, the user usually releases it. While the button is being released, a button-up message is sent and it depends on the button, left or right, that was down.

If the left mouse is being released, the ON_WM_LBUTTONUP message is sent. Its syntax is:

afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

If the right mouse is being released, the ON_WM_TBUTTONUP message is sent. Its syntax is:

afx_msg void OnRButtonUp(UINT nFlags, CPoint point);

The first argument, nFlags, specifies what button, right or middle, is down or what keyboard key and what mouse button were down. It is a constant integer that can have one of the following values:

  • MK_CONTROL: A Ctrl key was held down.
  • MK_MBUTTON: The middle mouse button was down.
  • MK_RBUTTON: The right mouse button was down.
  • MK_SHIFT: A Shift key was held.

The point argument specifies the measure from the (0, 0) origin of the window to the mouse pointer.

Practical Learning: Sending a Mouse Down Message

  1. To experiment with a mouse up message, change the program as follows:
    #include <AFXWIN.H>
    
    class CMainFrame : public CFrameWnd
    {
    public:
        CMainFrame ();
    
    protected:
        afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
        afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
        afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
        afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    
        DECLARE_MESSAGE_MAP()
    };
    
    CMainFrame::CMainFrame()
    {
        // Create the window's frame
        Create(NULL, "Windows Application", WS_OVERLAPPEDWINDOW,
               CRect(120, 100, 700, 480), NULL);
    }
    
    class CExerciseApp: public CWinApp
    {
    public:
        BOOL InitInstance();
    };
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
        ON_WM_CREATE()
        ON_WM_KEYDOWN()
        ON_WM_LBUTTONDOWN()
        ON_WM_RBUTTONUP()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        return 0;
    }
    
    void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
        switch(nChar)
        {
        case VK_RETURN:
            SetWindowText("You pressed Enter");
            break;
        case VK_F1:
            SetWindowText("Help is not available at the moment");
            break;
        case VK_DELETE:
            SetWindowText("Can't Delete This");
            break;
        default:
            SetWindowText("Whatever");
        }
    }
    
    void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) 
    {
        char *MsgCoord  = new char[20];
    
        sprintf(MsgCoord, "Left Button at P(%d, %d)", point.x, point.y);
        
        SetWindowText(MsgCoord);
    }
    
    void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point) 
    {
        SetWindowText("Right Mouse Button Up");
    }
    
    BOOL CExerciseApp::InitInstance()
    {
        m_pMainWnd = new CMainFrame ;
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
        return TRUE;
    }
    
    CExerciseApp theApp;
  2. Execute the program. To test it, click in the middle of the window and hold the mouse down.
  3. Then release the mouse. Notice that the title bar displays the new message only when the mouse is up.
  4. Return to MSVC.

The Double-Click Message

Instead of pressing and simply releasing a mouse button, a classic action the user can perform with the mouse is to double-click an object. When this is done, a double-click message is sent. The message to consider actually depends on the button that was double-pressed.

If the double-click was performed using the left mouse button, the WM_LBUTTONDBLCLK message is sent and its syntax is:

afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);

If the action was performed using the right mouse button, the WM_RBUTTONDBLCLK message would be sent. Its syntax is:

afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);

In both cases the nFlags argument specifies the button that was double-clicked. This argument can have one of the following values:

  • MK_CONTROL: A Ctrl key was held down when the user double-clicked.
  • MK_LBUTTON: The left mouse button is down.
  • MK_MBUTTON: The middle mouse button is down.
  • MK_RBUTTON: The right mouse button is down.
  • MK_SHIFT: A Shift key was held down when the user double-clicked.

The point argument specifies the location of the mouse pointer in x (horizontal) and y (vertical) coordinates.

Mouse Moving

After pressing one of the mouse buttons, depending on the requirement, the user may not need to immediately release the button. Another action performed with the mouse consists of clicking and holding the mouse button down, then dragging in a chosen direction. This action refers to the mouse moving. When this is done a WM_MOUSEMOVE message is sent. Its syntax is:

afx_msg void OnMouseMove(UINT nFlags, CPoint point);

The nFlags argument specifies what button is held down or what key is pressed in combination with the button that is held down while the mouse pointer is moving. This argument can have one of the following values:

  • MK_CONTROL: A Ctrl key is held down.
  • MK_LBUTTON: The left mouse button is down.
  • MK_MBUTTON: The middle mouse button is down.
  • MK_RBUTTON: The right mouse button is down.
  • MK_SHIFT: A Shift key was held down.

The point argument specifies the current location of the mouse pointer in x (horizontal) and y (vertical) coordinates at the time the message is captured.

Conditional Messages

Introduction

The messages we have used so far belong to specific events generated at a particular time by a window. Sometimes in the middle of doing something, you may want to send a message regardless of what is going on. This is made possible by a function called SendMessage(). Actually, there are two SendMessage() versions available.

The Win32 API version of the SendMessage() function has the following syntax:

LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

The MFC version is defined as follows:

LRESULT SendMessage(UINT Msg, WPARAM wParam, LPARAM lParam);

Because the Win32 version is considered global, if you want to use it, you must precede it with the scope access operator "::" as in:

::SendMessage(WhatToDo);

The hWnd argument is the object or control that is sending the message.

The Msg argument is the message to be sent.

The wParam and the lParam values depend on the message that is being sent.

The advantage of using the SendMessage() function is that, when sending this message, it would target the procedure that can perform the task and this function would return only after its message has been processed.

Sending Messages

In order to send a message using the SendMessage() function, you must know what message you are sending and what that message needs in order to be complete. For example, to change the caption of a window at any time, you can use the WM_SETTEXT message. The syntax to use would be:

SendMessage(WM_SETTEXT, wParam, lParam);

Obviously you would need to provide the text for the caption you are trying to change. This string is carried by the lParam argument as a null-terminated string. For this message, the wParam is ignored.

Practical Learning: Sending Messages

  1. To process a message using the SendMessage() function, change the OnRButtonUp() event as follows:
    void CMainFrame::OnRButtonUp(UINT nFlags, CPoint point)
    {
        const char *Msg = "This message was sent";
        SendMessage(WM_SETTEXT, 0, (LPARAM)(LPCTSTR)Msg);
    }
  2. Test the application and return to MSVC.

License

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

A list of licenses authors might use can be found here


Written By
Web Developer
India India
I am baladevan programmer in VC++ ATL COM for Software Company based in Trichy, India.
I am B.E (Comp Sci.)

Comments and Discussions

 
QuestionQuestion in SendMessage() method. Pin
Debanka_Basu27-Nov-12 2:21
Debanka_Basu27-Nov-12 2:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.