ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel

Visual C++ MFC - Understanding Message Handling with an Example

Updated on December 28, 2016

1. What is Message Handling?

The user interacts with the application through the basic external peripherals like Keyboard and Mouse. In MFC, hardware events from these devices are seen as "Windows Messages". As an MFC application programmer responding to these windows messages are called "Message Handling".

For Example, Let us say; a user clicks Left Mouse button in the "Windows Client Area" of an MFC SDI Application, and after that, a message box appears greeting "Hello there". Here, the "Mouse Click" is sent to the application as Windows Message, and a "Handler Function" is displaying the message box by responding to the received message.

In this example, we will see how to respond to the Left and Right mouse button clicks.

2. Create an SDI MFC Application

Create a "Single Document Interface" MFC Application project and Name it as MessageHndl. Creating the application is shown in the below video (Use Full Screen Mode):


Creating SDI Application for Message Handling Example

By following the steps shown in the above video, you now have a "Do nothing" MFC SDI Application. We will use this application to add code and learn message handling.

3. Add Handler Functions For WM_LBUTTONUP, WM_RBUTTONUP

The mouse click is a combination of two events. They are pressing down the button and then releasing it. Here, we are going to respond to the mouse button release action as it looks like a mouse click. In MFC, BUTTONUP is the best way to track the mouse clicks.

The below video shows adding the handler code for the window messages "WM_LBUTTONUP", "WM_LBUTTONDOWN". Once handler code is in hand, we can start writing the code. Now follow the steps explained in the video below:


Providing MFC Message Handler

4. Message Handlers added by the IDE

By following the steps shown in the above video, our application is modified by the Visual Studio IDE (Interactive Development Environment) to provide the skeleton code to handle the Left and Right mouse button clicks. Let us look at these pieces code before adding our own one.

4.1 DECLARE_MESSAGE_MAP()

This macro is added to the header file and it will do the declaration of internal functions and structures written as part of Microsoft Foundation Classes (MFC). These declarations together provide support for handling the windows messages.

4.2 BEGIN_MESSAGE_MAP, END_MESSAGE_MAP

The Visual Studio IDE adds these macros to the CPP file. The window messages which are handled in the CPP file is wrapped between these macros. The "BEGIN_MESSAGE_MAP" first provides the implementation for the functions declared by the macro "DECLARE_MESSAGE_MAP". Then, it populates the array of type "AFX_MSGMAP_ENTRY". The population of the array is done by the message map entries added in between Begin and End message map pair.

The macro "END_MESSAGE_MAP" closes the MessageEntry initialization. This macro also populates one more structure of type "AFX_MSGMAP". This structure has two entries. One is message map entries initialized by the message map pair and the another entry is a function pointer which when called returns the "AFX_MSGMAP" for the base class.

Now, when a message handler is not found in the current class implementation, the function pointer is used to search the handler in the base class. Likewise, the message handler is searched till the very base class. When a handler for the message is found, the handler gets called.

4.3 Handler function prototype added by the IDE

The below screenshot shows the handler function signature added by the IDE:

Handler Functions Prototype
Handler Functions Prototype | Source

Here, the "Flags" parameter is used to check button status. For example one can check weather shift button is down when a mouse button is released. Look at the Table1 below to know the flag constant used for the check:

Table1: Flags for OnLButtonUp, OnRButtonUp

Flag Constant
Used to Test
MK_CONTROL
Set if the CTRL key is down.
MK_MBUTTON
Set if the middle mouse button is down.
MK_RBUTTON
Set if the right mouse button is down.
MK_SHIFT
Set if the SHIFT key is down.

4.4 Mouse Handler Dummy Implementation

The IDE also added the dummy implementation functions in the "View CPP File" for you. The below screenshot shows the implementation added by the class property:

Mouse handler dummy implementation
Mouse handler dummy implementation | Source

5 Code for the Mouse button handlers

In the previous section, we reviewed the code added by the Visual Studio. Now, let us add our code and experiment the mouse handler. Follow steps listed below.

5.1 Declare variables in the MessageHndlView.h

Declare the variable m_bluerect of type bool. We will use this variable to alternate the colour of the rectangle between blue and green. Next, add a CRect type variable called m_rctUpdateArea. This is used for defining the Update Area of the client window. We will see about this in more detail later. Below is the code snippet:

Variable Declarations
Variable Declarations | Source

5.2 Initialize Data Members

Have a look at the screenshot below.

First, the boolean variable m_bluerect is initialized to true (Marked as 1). The draw function will check this variable and draws the rectangle in blue colour when the variable is holding the true. Next, a bounding box for updating the client area is defined by initializing the data member m_rctUpdateArea (Marked as 2). This bounding box is supplied to the draw function so that it only erases and redraws the content defined by it (Or enclosed by it). The bounding box is shown as green below and we are going to draw the rectangle inside this bounding box. In MFC, we usually call this bounding box as "Clipping Region" which marks portion of area in client to be redrawn.

Defining the Redraw clipping region
Defining the Redraw clipping region | Source

5.3 Draw Rectangle in CMessageHndlView::OnDraw(CDC* pDC)

The function "OnDraw()" gets called by the Windows OS whenever the application requires a redraw. Some well-known examples are given below:

  1. Let us say a user minimized our application and then restored it. In this case, redraw of the client area is required.
  2. User stacked a notepad application on top our application and then closed the notepad application. The area, hidden by the Notepad requires a redraw.
  3. The user moved our window one location to other location. Here also a redraw is required.

Now, look at the code snippet below:

MFC OnDraw() and drawing a rectangle
MFC OnDraw() and drawing a rectangle | Source

In the above code snippet, first, the Rectangle that we are going to draw is defined in terms of Top, Left, Bottom, Right (Marked as 1) just like how we defined the Clipping region. After defining the rectangle, the Draw function checks the Boolean flag m_bluerect. When this boolean flag is true, a blue rectangle is drawn and green rectangle is drawn otherwise (Marked as 2 and 3).

When we compile and run the application at this stage we always see a blue rectangle. Now, let us start writing some code in the mouse button handler so that we can change the boolean flag.

5.4 Implement OnLButtonUp, OnRButtonUp Handlers

All Set. Now we will set the boolean member m_bluerect to true in the OnLButtonUp() handler and we set the same boolean variable as false in the OnRButtonUp() handler (Marked as 3 and 4). Now, when the user clicks the left mouse button, the boolean is set to true and when right mouse button click will set is as false.

In both the handler, we are making a call to "InvalidateRect()" function by supplying the bounding box (Marked as 1 and 2). This means that we are asking windows to redraw the portion of the "ClientArea" marked by the passed-in rectangle. And the windows will call the OnDraw() function and the OnDraw first clears the background of the clipping region and then draws either Blue and Green Rectangle. The screenshot below shows the code snippet:

Left and Right mouse button handler
Left and Right mouse button handler | Source

Note that when we call Invalidate, the entire client area gets redrawn. Watch the video below which explains the InvalidateRect and how it works by running the application with some sligh code changes:

WM_LBUTTONUP, WM_RBUTTONUP, InvalidateRect Explained

6. Code Listing and Sample application Download

Below are the code modified for the Application.

MessageHndlView.h

// MessageHndlView.h : interface of the CMessageHndlView class
//
#pragma once

class CMessageHndlView : public CView
{
protected: // create from serialization only
	CMessageHndlView();
	DECLARE_DYNCREATE(CMessageHndlView)

// Attributes
public:
	CMessageHndlDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
	virtual void OnDraw(CDC* pDC);  // overridden to draw this view
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

//Sample 01: Variable to store current rectangle colour
private:
	bool m_bluerect;
	CRect m_rctUpdateArea;

// Implementation
public:
	virtual ~CMessageHndlView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
};

#ifndef _DEBUG  // debug version in MessageHndlView.cpp
inline CMessageHndlDoc* CMessageHndlView::GetDocument() const
   { return reinterpret_cast<CMessageHndlDoc*>(m_pDocument); }
#endif

MessageHndlView.cpp

// MessageHndlView.cpp : implementation of the CMessageHndlView class
//

#include "stdafx.h"
#include "MessageHndl.h"

#include "MessageHndlDoc.h"
#include "MessageHndlView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMessageHndlView

IMPLEMENT_DYNCREATE(CMessageHndlView, CView)

BEGIN_MESSAGE_MAP(CMessageHndlView, CView)
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONUP()
END_MESSAGE_MAP()

// CMessageHndlView construction/destruction

CMessageHndlView::CMessageHndlView()
{
	//Sample 02a: Initialize the Mode
	m_bluerect = true;

	//Sample 02b: Initialize the Update Rectangle
	m_rctUpdateArea.top = 5;
	m_rctUpdateArea.left = 5;
	m_rctUpdateArea.bottom = 170;
	m_rctUpdateArea.right = 170;
}

CMessageHndlView::~CMessageHndlView()
{
}

BOOL CMessageHndlView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

// CMessageHndlView drawing

void CMessageHndlView::OnDraw(CDC* pDC)
{
	CMessageHndlDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: add draw code for native data here
	//Sample 03: Draw the Rectangle
	CRect rct(10,10,160,160);
	if (m_bluerect == true)
	{
		pDC->FillSolidRect(rct, RGB(0,0,255));
	}
	else
	{
		pDC->FillSolidRect(rct, RGB(0,255,0));
	}

}


// CMessageHndlView printing

BOOL CMessageHndlView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMessageHndlView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMessageHndlView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}


// CMessageHndlView diagnostics

#ifdef _DEBUG
void CMessageHndlView::AssertValid() const
{
	CView::AssertValid();
}

void CMessageHndlView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMessageHndlDoc* CMessageHndlView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMessageHndlDoc)));
	return (CMessageHndlDoc*)m_pDocument;
}
#endif //_DEBUG


// CMessageHndlView message handlers

void CMessageHndlView::OnLButtonUp(UINT nFlags, CPoint point)
{
	//Sample 04: Set the Rct colour to Blue
	m_bluerect = true;
	InvalidateRect(m_rctUpdateArea);

	CView::OnLButtonUp(nFlags, point);
}

void CMessageHndlView::OnRButtonUp(UINT nFlags, CPoint point)
{
	//Sample 05: Set the blue rectangle to false
	m_bluerect = false;
	InvalidateRect(m_rctUpdateArea);

	CView::OnRButtonUp(nFlags, point);
}

Download SourceCode

Sample Application Download: Link

Comments

    0 of 8192 characters used
    Post Comment

    No comments yet.

    working

    This website uses cookies

    As a user in the EEA, your approval is needed on a few things. To provide a better website experience, hubpages.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

    For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: https://hubpages.com/privacy-policy#gdpr

    Show Details
    Necessary
    HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
    LoginThis is necessary to sign in to the HubPages Service.
    Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
    AkismetThis is used to detect comment spam. (Privacy Policy)
    HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
    HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
    Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
    CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
    Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
    Features
    Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
    Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
    Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
    Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
    Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
    VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
    PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
    Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
    MavenThis supports the Maven widget and search functionality. (Privacy Policy)
    Marketing
    Google AdSenseThis is an ad network. (Privacy Policy)
    Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
    Index ExchangeThis is an ad network. (Privacy Policy)
    SovrnThis is an ad network. (Privacy Policy)
    Facebook AdsThis is an ad network. (Privacy Policy)
    Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
    AppNexusThis is an ad network. (Privacy Policy)
    OpenxThis is an ad network. (Privacy Policy)
    Rubicon ProjectThis is an ad network. (Privacy Policy)
    TripleLiftThis is an ad network. (Privacy Policy)
    Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
    Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
    Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
    Statistics
    Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
    ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
    Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)