Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / MFC
Article

Change the background color of the frame area of an MDI application.

Rate me:
Please Sign up or sign in to vote.
4.93/5 (29 votes)
12 Apr 20072 min read 81.2K   891   31   13
This article describes how to change the color of Frame Windows client area by subclassing the control which draws the background.

Screenshot - MDIFrameBackground.jpg

Introduction

This is actually a very simple task. The hard thing to figure out is the fact that the background part of the main frame Window isn't really handled by the frame Window itself. It contains another Window that fills the area inside the frames border. This Window is known as m_hWndMDIClient.

Background

To get this task done, my first instinct was to catch the WM_ERASEBKGND in CMainFrame and do the FillSolidRect there. But I soon realized that approach didn't do anything other than make the frame flicker and show red only when it's being resized, otherwise the gray background was completely intact. Not exactly what I was looking for. Suddenly it became a little mystery. Why doesn't the background of the frame change when I fill it with a color in the frame's WM_ERASEBKGND handler? So I went on a hunt, I went through a lot of the CMDIFrameWnd and CFrameWnd code looking for methods that would draw on the frame, and there was not much there. I finally ended up at CMainFrame::OnCreate method, I set a breakpoint and stepped through the CMDIFrameWnd::OnCreate method. After what seemed to be hours of searching I came across the following code in CMDIFrameWnd::CreateClient:

C++
// Create MDICLIENT control with special IDC
if ((m_hWndMDIClient = ::CreateWindowEx(dwExStyle, _T("mdiclient"), NULL,
          dwStyle, 0, 0, 0, 0, m_hWnd, (HMENU)AFX_IDW_PANE_FIRST,
          AfxGetInstanceHandle(), (LPVOID)&ccs)) == NULL)
{
   TRACE(traceAppMsg, 0, _T("Warning: CMDIFrameWnd::OnCreateClient: 
                                             failed to create MDICLIENT.")
            _T(" GetLastError returns 0x%8.8X\n"), ::GetLastError());
   return FALSE;
}

It is pretty clear that the frame Window is creating another Window to act as its center (To this day I don't really know the purpose behind this). So that's where this code comes in. By subclassing the client Window m_hWndMDIClient I was able to cleanly change the color of the MDI frame Window.

Using the code

To change the color of the background, first we must create a new CWnd derived class which handles the WM_ERASEBKGND message and fills the client area of the Window with a different color. So let's add a class called CClientWnd which inherits from CWnd:

C++
#pragma once

// CClientWnd
class CClientWnd : public CWnd
{
   DECLARE_DYNAMIC(CClientWnd)
public:

   CClientWnd();
   virtual ~CClientWnd();

protected:

   afx_msg BOOL OnEraseBkgnd(CDC* pDC);
   DECLARE_MESSAGE_MAP()
};

And implement the OnEraseBkgnd method:

C++
// ClientWnd.cpp : implementation file

#include "stdafx.h"
#include "ClientWnd.h"

// CClientWnd

IMPLEMENT_DYNAMIC(CClientWnd, CWnd)

CClientWnd::CClientWnd()
{
}

CClientWnd::~CClientWnd()
{
}

BEGIN_MESSAGE_MAP(CClientWnd, CWnd)
   ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

// CClientWnd message handlers
BOOL CClientWnd::OnEraseBkgnd(CDC* pDC)
{
   CRect Rect;
   GetClientRect(&Rect);

   //fill the entire client area with Red!
   pDC->FillSolidRect(&Rect,RGB(255,0,0));

   //return TRUE to indicate that we took care of the erasing
   return TRUE;
}

Now the only thing left to do is to subclass the Window m_hWndMDIClient. To do that we are going to overwrite CMainFrame::OnCreateClient method, and declare m_Client in CMainFrame's class declaration as a private variable.

C++
class CMainFrame : public CMDIFrameWnd
{
......
protected:
   virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);

private:
   CClientWnd   m_Client;
};

Implementation of OnCreateClient should look like this:

C++
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
   if (CMDIFrameWnd::OnCreateClient(lpcs, pContext))
   {
      m_Client.SubclassWindow(m_hWndMDIClient);
      return TRUE;
   }

   return FALSE;
}

Have fun!

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
Architect
United States United States
Ali Rafiee has been developing windows applications using C++ since 1991, and he hasn't looked back since. Ali has been a software development consultant for must of his career, but he has finally settled down and has been working for an educational software company since 2000. While he is not working, he is either learning C#, flying airplanes, playing with his daughter, or answering peoples question on newsgroups, he finds that to be a great learning tool for himself.

Ali is also a Microsoft Visual C++ MVP.

Comments and Discussions

 
QuestionThank you + try gradients Pin
Member 968830920-Jun-13 14:51
Member 968830920-Jun-13 14:51 
GeneralThank you! Pin
Nguyen Van Thai23-Jul-11 4:32
Nguyen Van Thai23-Jul-11 4:32 
GeneralThanks Pin
bilelbenfredj15-May-08 23:18
bilelbenfredj15-May-08 23:18 
GeneralI like your approach Pin
#realJSOP28-Apr-07 1:18
mve#realJSOP28-Apr-07 1:18 
GeneralAnother way Pin
Piotr Szewczyk17-Apr-07 4:57
Piotr Szewczyk17-Apr-07 4:57 
good work.
Ther is another way which can be used for eqample in reaction on event.

void CMainFrame::OnButColor()
{
// TODO: Add your command handler code here

HBRUSH hBrush=CreateSolidBrush(RGB(0,0,255));
SetClassLong(m_hWndMDIClient,GCL_HBRBACKGROUND,(LONG)hBrush);
::InvalidateRect(m_hWndMDIClient,0,TRUE);
}
GeneralRe: Another way Pin
Ali Rafiee18-Apr-07 14:40
Ali Rafiee18-Apr-07 14:40 
GeneralThanks Pin
James Armstrong16-Apr-07 22:52
James Armstrong16-Apr-07 22:52 
GeneralThank You Pin
shawkins16-Apr-07 8:16
shawkins16-Apr-07 8:16 
GeneralRe: I got a rating of 2 Pin
Hans Dietrich12-Apr-07 20:06
mentorHans Dietrich12-Apr-07 20:06 
GeneralRe: I got a rating of 2 Pin
Ali Rafiee13-Apr-07 5:00
Ali Rafiee13-Apr-07 5:00 
GeneralRe: I got a rating of 2 Pin
kenearle14-Apr-07 7:55
kenearle14-Apr-07 7:55 
GeneralRe: I got a rating of 2 Pin
code_discuss19-Apr-07 4:34
code_discuss19-Apr-07 4:34 
GeneralRe: I got a rating of 2 Pin
Ali Rafiee19-Apr-07 4:53
Ali Rafiee19-Apr-07 4:53 

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.