A Custom MDI Client Class

Environment: The code has been tested using VC5 and VC6 under Win98 and WinNT 4.0 and it works fine.

What's this?

The CMDIClient is a quite simple CWnd-derived class that allows you to display any bitmap image in MDIClient area or choose any background color. You can load the image from file as well as from the resource and you can choose the mode what the image will be displayed in. Available modes are: tile, center, stretch and custom. In the last mode you can set manually left-top coordinates of the image and display it at any position you wish. Additionally, the class provides two functions for saving/restoring current settings to the registry. The saving/restoring can be done automatically (on WM_DESTROY and PreSubclassWindow() ) if m_bAutoSaveRestore flag is set to TRUE (in fact, that's set by default). When the bitmap is loaded from the resource, you can map some colors to the system colors using the COLORMAP structure, (e.g. you can map light gray to COLOR_3DFACE and so on, see the demo project for more details).

The bitmap is drawn in CMDIClient's OnPaint() message handler (the original OnPaint() isn't called at all). There's no palette support in this version so don't expect good effects when you are in 256 (or less) color mode and you try to display a 256 color bitmap. The demo project includes a simple dialog, which allows you to set all properties at runtime, so just try it!

CMDIClient properties

Set or get the background color. For painting the background we use FillRect (not FillSolidRect for some reasons), so we need a brush. The brush is created based on a supplied color when SetBkColor is called.


COLORREF GetBkColor() const;
void SetBkColor( COLORREF clrValue );
Load background bitmap from given file.

BOOL SetBitmap( LPCTSTR lpszFileName, UINT uFlags =  LR_LOADMAP3DCOLORS );
Load background bitmap from resource. You can map some colors using the COLORMAP struct (see LoadMappedBitmap in MSDN for details how to use it).

BOOL SetBitmap( UINT nBitmapID, COLORMAP* pClrMap = NULL, int nCount = 0 );
Set or get the current display mode (dispTile, dispCenter, dispStretch or dispCustom).

void SetDisplayMode( DisplayModesEnum eDisplayMode );
DisplayModesEnum GetDisplayMode() const;
Specify or retrieve the coordinates of image top-left corner. Used when dispCustom is selected. If bRedraw is set to TRUE, the entire window is invalidated.

void SetOrigin( int x, int y, BOOL bRedraw = TRUE );
void SetOrigin( const CPoint& point, BOOL bRedraw = TRUE );
const CPoint& GetOrigin() const;
Return the current image size. If there's no image, (0,0) is returned.

const CSize& GetImageSize() const;
Return the filename of the bitmap. Empty string if there's no image or if the image was loaded from the resource.

const CString& GetFileName() const;
If set to TRUE, the current state is automatically saved on WM_DESTROY and restored on PreSubclassWindow(). If you would like to control this manually, set it to FALSE and call SaveState()/RestoreState() when you want.

void SetAutoSaveRestore( BOOL bNewValue );
BOOL GetAutoSaveRestore() const;

CMDIClient methods

Restore original (system-wide) settings for the MDIClient and repaint the window.


void Reset();
Load/store current settings in the registry

void SaveState();
void RestoreState();
For further information look at the CMDIClient header and implementation files.

How to use it?

First, add to your CMainFrame class implementation file a member variable of type CMDIClient. A good practice is to keep the variables protected (or private) and uses an inline functions to gain access to them, if needed. Then within OnCreate() handler add a following code.


// Subclass the MDI client window
VERIFY( GetMDIClient().SubclassWindow( m_hWndMDIClient ) );
After that you can set the desired MDIClient properties by calling appropriate functions.

Download demo project - 37 KB

Download source - 5 KB

Date Last Updated: April 3, 1999



Comments

  • stop MDI statusbar flicker?

    Posted by Legacy on 09/03/2003 12:00am

    Originally posted by: tot eu

    Hello,
    Could anybody give a hint over the general problem of the flickering of MDI bars (statusbar at least, just because is docked at the bottom - in the update area of MDICLIENT) against a SDI - where nothing like that happens, maybe it's the MDICLIENT where the solution is.
    Or at least if not possible, maybe somebody could tell me why not?

    Reply
  • Hope People Still check this page

    Posted by Legacy on 04/29/2003 12:00am

    Originally posted by: Mark

    Hi, I am trying to display a view inside the CMDIFrameWnd. I am not too familiar with MFC. Whenever I use this code, I can't display my view. Whenever I use CFrameWnd, it displays properly. I don't see why CMDIFrameWnd, a child class of CFrameWnd, would have problem displaying this.

    Reply
  • A problem in CFrameWnd

    Posted by Legacy on 03/17/2002 12:00am

    Originally posted by: Gempin

    This is great, but i found there will not success if it's in a CFrameWnd but CMDIFrameWnd, In CMDIFrameWnd, there has a m_hWndMDIClient, you can subclass to it, but CFrameWnd only has a m_hWnd, subclassing it will make a application crash, yes, you can test it...

    Reply
  • Resource leak (and correction)

    Posted by Legacy on 12/01/2000 12:00am

    Originally posted by: Vincent Terraillon

    The Bitmap should be selected out of the DC or it will not be deleted correctly.
    
    

    In the OnPaint method change these lines:

    CBitmap bmp;
    should be:
    CBitmap bmp, *oldbmp = NULL;

    memDC.SelectObject( &bmp );
    should be:
    oldbmp = memDC.SelectObject( &bmp );

    and add these just after the last dc.BitBlt

    if (oldbmp != NULL)
    memDC.SelectObject( oldbmp );


    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • QA teams don't have time to test everything yet they can't afford to ship buggy code. Learn how Coverity can help organizations shrink their testing cycles and reduce regression risk by focusing their manual and automated testing based on the impact of change.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds