Click here to Skip to main content
Click here to Skip to main content

Tile, center and stretch a bitmap as your MFC dialog background

By , 6 Jun 2002
 

Screenshots

Adding the class to your project

There are three steps you have to follow before you can use this class in your project.

  1. Add BDialog.cpp and BDialog.h to your project
  2. Replace all instances of CDialog with  CBDialog. Do this to both the cpp and h file of your dialog class. For example if your project is called Test, make the changes to TestDlg.cpp and TestDlg.h. You'll have to use Find and Replace.
  3. #include BDialog.h to your dialog header file

So basically we have derived our dialog class from CBDialog instead of CDialog, but since CBDialog is derived from CDialog, you won't have any problems with your existing code.

Using the class

Basically there are just two methods that you need to call.

void CBDialog::SetBitmapStyle(int style)

style - This is used to set the bitmap background style. You can use one of the following three styles.

  • StyleTile - The background image will be tiled
  • StyleStretch - The background image will be stretched
  • StyleCenter - The background image will be centered, if it is smaller than the client area of the dialog

You can call this method either from OnInitDialog() or from any other place in your dialog class. If you call it outside OnInitDialog() you'll also have to call Invalidate() to force a repaint of the dialog client area.

int CBDialog::SetBitmap(UINT nIDResource)

nIDResource - This specifies the resource ID number of the bitmap resource

Return Value

The return value is zero on success and non-zero on failure.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nish Sivakumar
United States United States
Member
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
 
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.
 
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.
 
Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
 
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionCan you add a video please?memberRalph David Abernathy4 May '13 - 9:08 
Can you add a video of a step-by-step solution? Thank you very much.
-obliviga

GeneralMy vote of 3memberRalph David Abernathy4 May '13 - 9:06 
You should add a video. Thanks.
QuestionStatic control background 2memberpippo pioppo21 Dec '11 - 23:23 
How I change the background color of a Static Control (on the dialog) to the color of the bitmap (it's a gradient one, so i can't set static control background to bitmap color. Transparent background take dialog color, not image one)?
 
10x
Sandro

QuestionButton background image stretchmemberMember 33126532 Jul '11 - 2:01 
Hi Nishant,
 
Very nice article. I am new to VC++ and wanted to apply dialog a stretch background image. Your article resolved it. More to that I want to apply stretch background image to button. How can I achieve this?
 
Thanks,
Questionfor win32memberperry.p23 Sep '10 - 21:02 
Hi,
 
How can we implement image background in win32 (dailog based) application ?
GeneralChanging the bitmapmembergilmar6 Jan '10 - 4:31 
Hi,
 
Is it possible to change the bitmap?
General[modified] got error LNK2001: unresolved external symbol : problem solvedmemberInair3 Apr '08 - 0:45 
Why I got this error message when try to build my project? Did I miss some step?

 
Sorry, my mistake... Big Grin | :-D it is really helpful. great job.
 
Thanks a lot.
 
modified on Thursday, April 3, 2008 8:54 PM

GeneralReally need help plz plz plzmemberMathewsimpson3 Nov '07 - 14:19 
Please Help i really need to do this but when i try to do what think is right it highlight's #include pleaase help me please i use Dev cpp
GeneralShow Static textmembernugroho231 Oct '07 - 5:44 
This code is wonderful for a beginner like me. However, I have Static Text in my dialog, and it seems that the text will not show up when I use this code. Could anybody please help?
GeneralRe: Show Static textmemberAnu Koshy27 May '10 - 23:15 
try BringWindowToTop(); with the static text control.
GeneralRe: Show Static textmemberRamveer Singh from Gurgaon, Haryana22 May '11 - 20:41 
Hello
I am facing the same problem. Can you please help me that how can i solve this?
I tried BringWindowToTop() but it not worked.
GeneralWorks like a charm - Thx!memberJunky695 Apr '07 - 9:57 
Simply needed to drop something in to handle a background image on a splash screen, and this worked perfectly. Thx.
 
David
GeneralRe: Works like a charm - Thx!memberJunky695 Apr '07 - 9:59 
PS: I added a header block and fully referenced you - give credit where due!
QuestionHow to add a .BMP as a resource (IDB_BITMAP1)memberleevonk8 Jun '06 - 9:54 
add a bitmap as a resource to your project:
 
Make a 256 color bitmap, save it in the 'res' folder of your project.
 
In vc++, add the file to your projects resource folder in vc++ (click on 'file view' in left frame, right click on resources folder, click add file)
 
Click on the 'Insert' menu (at the top of vc++), click 'resource', add your bitmap.
 
Click on 'ResourceView' in the left frame of vc++, you should see IDB_BITMAP1 in the 'bitmap' folder.
GeneralDebug AssertionmemberSalloum Sotiris30 Jul '05 - 7:55 
Hi thanks for the code, while I'm trying to change the background inside my code I get a Debug Assertion fault while loading the new bitmap. If this error ignored on a release version after 30 changes of the bitmap the application ignores tottaly the command. I solved this problem by changing your implementation from static CBitmap to CBitmap* more specificaly:
 
BDialog.h

#if !defined(AFX_BDIALOG_H__A303185C_4254_4F5F_B5A8_462531A59B83__INCLUDED_)
#define AFX_BDIALOG_H__A303185C_4254_4F5F_B5A8_462531A59B83__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
 

#define StyleTile 0
#define StyleCenter 1
#define StyleStretch 2
 
class CBDialog : public CDialog
{
// Construction
public:
int SetBitmap(UINT nIDResource);
void SetBitmapStyle(int style);
 
CBDialog(UINT nIDTemplate, CWnd* pParent = NULL); // standard constructor
 
// Dialog Data
//{{AFX_DATA(CBDialog)
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
 

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBDialog)
protected:
//}}AFX_VIRTUAL
 
// Implementation
protected:
 
// Generated message map functions
//{{AFX_MSG(CBDialog)
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
CBitmap* m_bitmap;
int m_style;
};
 
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_BDIALOG_H__A303185C_4254_4F5F_B5A8_462531A59B83__INCLUDED_)
 

 
BDialog.cpp
 

// BDialog.cpp : implementation file
//
 
#include "stdafx.h"
#include "BDialog.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
/////////////////////////////////////////////////////////////////////////////
// CBDialog dialog
 

CBDialog::CBDialog(UINT nIDTemplate, CWnd* pParent /*=NULL*/)
: CDialog(nIDTemplate, pParent)
{
//{{AFX_DATA_INIT(CBDialog)
// NOTE: the ClassWizard will add member initialization here
m_style=StyleTile;
m_bitmap=new CBitmap();
//}}AFX_DATA_INIT
}
 

BEGIN_MESSAGE_MAP(CBDialog, CDialog)
//{{AFX_MSG_MAP(CBDialog)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CBDialog message handlers
 
BOOL CBDialog::OnEraseBkgnd(CDC* pDC)
{
CDialog::OnEraseBkgnd(pDC);
if(!m_bitmap->m_hObject)
return true;

CRect rect;
GetClientRect(&rect);
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = dc.SelectObject(m_bitmap);
int bmw, bmh ;
BITMAP bmap;
m_bitmap->GetBitmap(&bmap);
bmw = bmap.bmWidth;
bmh = bmap.bmHeight;
int xo=0, yo=0;
 
if(m_style == StyleTile)
{
for (yo = 0; yo < rect.Height(); yo += bmh)
{
for (xo = 0; xo < rect.Width(); xo += bmw)
{
pDC->BitBlt (xo, yo, rect.Width(),
rect.Height(), &dc,
0, 0, SRCCOPY);
}
}
 
}
 
if(m_style == StyleCenter)
{
if(bmw < rect.Width())
xo = (rect.Width() - bmw)/2;
else
xo=0;
if(bmh < rect.Height())
yo = (rect.Height()-bmh)/2;
else
yo=0;
pDC->BitBlt (xo, yo, rect.Width(),
rect.Height(), &dc,
0, 0, SRCCOPY);
}
 
if(m_style == StyleStretch)
{
pDC->StretchBlt(xo, yo, rect.Width(),
rect.Height(), &dc,
0, 0,bmw,bmh, SRCCOPY);
}
 

dc.SelectObject(pOldBitmap);
 

return true;
}
 
void CBDialog::SetBitmapStyle(int style)
{
if((style==StyleTile)||
(style==StyleCenter)||
(style==StyleStretch))
{
m_style = style;
}
 
}
 
int CBDialog::SetBitmap(UINT nIDResource)
{
delete m_bitmap;
m_bitmap=new CBitmap();
if(m_bitmap->LoadBitmap(nIDResource))
return 0;
else
return 1;//error
}

 
Enjoy and again thanks for your code Big Grin | :-D
QuestionHow to set the bitmap to menus and status barmemberKoundinya18 Aug '04 - 2:46 
Hello Nishanth,
 
That was nice article Big Grin | :-D . If I want to set the image (what you are doing with dialog) to other window controls like Menu and status bar,How can I do that?
 
Best Regards
Sudhakar Chavali Sharma
Blush | :O Wink | ;) Smile | :) Big Grin | :-D
QuestionHow to make DPI independent dialogmemberkmAshif20 Jul '04 - 20:05 
When DPI is changed then the dialog size also changed...how could it possible to keep it size fix when DPI is changed..for examnple when i create a dialog in 96 dpi then its size will not increase in 120 dpi environment..thanks...Ashif
Generalstatic, radio button, checkbox, menumemberbrian scott18 Nov '03 - 5:36 
Hi! This works really well for a dialog background. However, in the app on which I am working (as a not-very experienced programmer), I need to use static text, radio buttons, check boxes and a menu bar. If I want the dialog background to be a simple colour, then the override for OnCtlColor() works fine. However, I really want to use a textured background, so that the text is set against that and not a background colour. Is there a way to set the background of, say, a radio button to the same texture as that of the main dialog?
 
Confused | :confused: Confused | :confused: Confused | :confused:
 
brian
Generalrounded XP buttonsmemberJason Henderson22 Oct '03 - 11:21 
I'm not using a bitmap as a background but I'm doing a FillSolidRect and rounded buttons have a white line around them where the button rect should be. Any clue on how I could fix it?
 
"It is better to remain silent and be thought a fool than to open one's mouth and remove all doubt." - Abraham Lincoln
Jason Henderson
blog | articles

GeneralLoad hi-res bitmap from filememberdelta00317 Oct '03 - 19:38 
I wanted more than the 256 colors from a resource bitmap so I modified the code to load the bitmap from a file, including higher resolutions bitmaps (I've tested it w/ a 24-bit color bitmap).
 
Modifications are as follows:
CBDialog.h
1. Change CBitmap m_bitmap; to CBitmap *m_bitmap;
2. Change the int SetBitmap(UINT nIDResource); fucntion def to
int SetBitmap(const char *cszBitmapFile);
 
CBDialog.cpp
1. Throughout the whole file, change any reference of &m_bitmap or
m_bitmap. to m_bitmap or m_bitmap-> (correspondingly)
2. In the constructor, add m_bitmap = 0; somewhere
3. In OnEraseBkgnd(), change the line if(!m_bitmap.m_hObject) to
if(!m_bitmap || !m_bitmap->m_hObject)
4. Change the whole SetBitmap() function to:
int CBDialog::SetBitmap(const char *cszBitmapFile)
{
   HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, cszBitmapFile, IMAGE_BITMAP,
      0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
 
   if(!hBitmap)
      return 1; // error; cszBitmapFile probably points to a non-existent file
 
   m_bitmap = CBitmap::FromHandle(hBitmap);
 
   if(m_bitmap)
      return 0;
   else
      return 2;//error
}

GeneralNow You Can Implement Transparent BackgroundmemberSadru10 Oct '03 - 5:34 
I have modify the code so that it can also implement the transparent background to the dialog ---- So you can watermark your company logo on the background.
 
Create the bitmap you want to display and also create the mask. (In the mask, whatever is white need to be converted to black and all other color needed to convert the black)
 

 
Modify BDialog.h
#define StyleTile 0
#define StyleCenter 1
#define StyleStretch 2
 
class CBDialog : public CDialog
{
// Construction
public:
int SetBitmap(UINT nIDResource,UINT nIDResourcemask=0);
void SetBitmapStyle(int style);
CBDialog(UINT nIDTemplate, CWnd* pParent = NULL); // standard constructor
 
// Dialog Data
//{{AFX_DATA(CBDialog)
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
 

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CBDialog)
protected:
//}}AFX_VIRTUAL
 
// Implementation
protected:
 
// Generated message map functions
//{{AFX_MSG(CBDialog)
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
CBitmap m_bitmap;
CBitmap m_bitmap_mask;
int m_style;
};
 
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
 
#endif // !defined(AFX_BDIALOG_H__A303185C_4254_4F5F_B5A8_462531A59B83__INCLUDED_)
 

 
Modify the BDialog.cpp
 
// BDialog.cpp : implementation file
//
 
#include "stdafx.h"
#include "BDialog.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
/////////////////////////////////////////////////////////////////////////////
// CBDialog dialog
 

CBDialog::CBDialog(UINT nIDTemplate, CWnd* pParent /*=NULL*/)
: CDialog(nIDTemplate, pParent)
{
//{{AFX_DATA_INIT(CBDialog)
// NOTE: the ClassWizard will add member initialization here
m_style=StyleTile;
//}}AFX_DATA_INIT
}
 

BEGIN_MESSAGE_MAP(CBDialog, CDialog)
//{{AFX_MSG_MAP(CBDialog)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CBDialog message handlers
 
BOOL CBDialog::OnEraseBkgnd(CDC* pDC)
{
CDialog::OnEraseBkgnd(pDC);
if(!m_bitmap.m_hObject && !m_bitmap_mask.m_hObject)
return true;
 
if (!m_bitmap_mask.m_hObject){ //old way
CBitmap* pOldBitmap = NULL;
CRect rect;
CDC dc;
int bmw, bmh ;
BITMAP bmap;
int xo=0, yo=0;

GetClientRect(&rect);
dc.CreateCompatibleDC(pDC);
pOldBitmap = dc.SelectObject(&m_bitmap);
m_bitmap.GetBitmap(&bmap);
bmw = bmap.bmWidth;
bmh = bmap.bmHeight;
 
if(m_style == StyleTile){
for (yo = 0; yo < rect.Height(); yo += bmh){
for (xo = 0; xo < rect.Width(); xo += bmw){
pDC->BitBlt (xo, yo, rect.Width(),
rect.Height(), &dc,
0, 0, SRCCOPY);
}
}
}
 
if(m_style == StyleCenter){
if(bmw < rect.Width())
xo = (rect.Width() - bmw)/2;
else
xo=0;
if(bmh < rect.Height())
yo = (rect.Height()-bmh)/2;
else
yo=0;
pDC->BitBlt (xo, yo, rect.Width(),
rect.Height(), &dc,
0, 0, SRCCOPY);
}
 
if(m_style == StyleStretch){
pDC->StretchBlt(xo, yo, rect.Width(),
rect.Height(), &dc,
0, 0,bmw,bmh, SRCCOPY);
}
 

dc.SelectObject(pOldBitmap);
::DeleteObject(dc);
}
else {
// transparent background image
CRect rect;
int x0=0, y0=0;
int cx = 0, cy = 0;
GetClientRect(&rect);
int bmw, bmh ;
BITMAP bmap;
m_bitmap.GetBitmap(&bmap);
bmw = bmap.bmWidth;
bmh = bmap.bmHeight;
x0 =rect.left;
x0 =rect.top;
cx = rect.Width();
cy = rect.Height();
 
if(m_style == StyleCenter){
if(bmw < cx)
x0 = (cx - bmw)/2;
else
x0=0;
if(bmh < cy)
y0 = (cy-bmh)/2;
else
y0=0;
}
 

CDC dcBmp,dcMask;
dcBmp.CreateCompatibleDC(pDC);
dcBmp.SelectObject(&m_bitmap);
dcMask.CreateCompatibleDC(pDC);
dcMask.SelectObject(&m_bitmap_mask);
 
CDC hdcMem;
hdcMem.CreateCompatibleDC(pDC);
CBitmap hBitmap;
if(m_style == StyleCenter)
hBitmap.CreateCompatibleBitmap(pDC,bmw,bmh);
else if(m_style == StyleStretch || m_style == StyleTile)
hBitmap.CreateCompatibleBitmap(pDC,cx,cy);
else{
}
hdcMem.SelectObject(hBitmap);
 
hdcMem.BitBlt(0,0,bmw,bmh,pDC,0,0,SRCCOPY);
hdcMem.BitBlt(0,0,bmw,bmh,&dcBmp,0,0,SRCINVERT);
hdcMem.BitBlt(0,0,bmw,bmh,&dcMask,0,0,SRCAND);
hdcMem.BitBlt(0,0,bmw,bmh,&dcBmp,0,0,SRCINVERT);
if(m_style == StyleCenter)
pDC->BitBlt (x0,y0,bmw,bmh,&hdcMem,0,0,SRCCOPY);
else if(m_style == StyleStretch)
pDC->StretchBlt (0,0,cx,cy,&hdcMem,0,0,bmw,bmh,SRCCOPY);
else{
for (y0 = 0; y0 < rect.Height(); y0 += bmh){
for (x0 = 0; x0 < rect.Width(); x0 += bmw){
pDC->BitBlt (x0, y0, bmw, bmh, &hdcMem, 0, 0, SRCCOPY);
}
}
}
 
hdcMem.DeleteDC();
hBitmap.DeleteObject();
DeleteDC(dcMask);
DeleteDC(dcBmp);
}
return true;
}
 
void CBDialog::SetBitmapStyle(int style)
{
if((style==StyleTile)||
(style==StyleCenter)||
(style==StyleStretch))
{
m_style = style;
}
 
}
 
int CBDialog::SetBitmap(UINT nIDResource,UINT nIDResourcemask)
{
if(m_bitmap.LoadBitmap(nIDResource)){
if (nIDResourcemask > 0){
if(!m_bitmap_mask.LoadBitmap(nIDResource))
return 1;
}
return 0;

}
return 1;//error
}

 
Have fun!
QuestionIs it possible?memberWolfSupernova27 Sep '03 - 9:22 
Hi Nishant,
 
Please forgive my "newbiness" if you will, but is there another way to make this so that you don't have to do the whole CDialog thing? The reason I ask is because there's another class that I'm already using that requires this.
 
Thanks in advance, Smile | :)
Don
 

AnswerRe: Is it possible?editorNishant S27 Sep '03 - 17:57 
I assume that this class you use is a CDialog derived class, right? I guess all you need to do is to change that class so that it derives from CBDialog instead of from CDialog. Now you can use your class and it will also have the CBDialog stuff by default.
 
Regards
Nish
 

Extending MFC Applications with the .NET Framework [NW] (coming soon...)
Summer Love and Some more Cricket [NW] (My first novel)
Shog's review of SLASMC [NW]
Come with me if you want to live

GeneralRe: Is it possible?memberWolfSupernova28 Sep '03 - 11:24 
It's the well-known CResizableDialog
class from Paolo Messina. If not that one, one similar, but they too require that you find and replace all instances of "CDialog" in the header and source file.
 
I'm building a skinnable Winamp sort of application and it seems like every class I find that would be useful, without having to re-invent any wheels that is, requires the same thing.
 
I guess there's a way to bundle up all of these classes into one source, and just make sure that there's no duplicate function names/variables, etc., and have them all derived from the same base? I'm sure it's possible, but I'm new to C++, not programming, just this language, which seems to be a little like going from Pig Latin to Japanese.
 
Having said that, any further details/advice that you can give me on this endeavor will be tremendously appreciated. Wink | ;)
 
Cheers,
Don
GeneralThank you!memberHosam Aly Mahmoud12 Aug '03 - 17:56 
Thank you very much!
 
<marquee behavior = "alternate">

Hosam Aly Mahmoud

</marquee>

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 7 Jun 2002
Article Copyright 2002 by Nish Sivakumar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid