Irregular Shaped Bitmap Dialog

The CBitmapDialog class allows you to create a dialog that has a bitmap background, and to have a specified color in the background be transparent. This allows the dialog to be in other shapes than a box, like the one shown above.

Usage

Use this class like CDialog, but there are several extra functions that you can use:


// ** Constructors **

// Use the normal CDialog constructors plus the following 
// as the last four parameters:
// 
// LPCTSTR	lpszResourceName
// UINT		nIDResource
// LPCTSTR	lpszFilename
// CBitmap	*pBitmap
// 
// Example:
// CDialog(int,CWnd*)):CBitmapDialog(IDD_MAINDIALOG, 
                                     this, 
                                     NULL, 
                                     IDB_BITMAP, 
                                     NULL, 
                                     NULL);
//
// Use at most one of these parameters and leave the rest 
// NULL or 0. If you do not want to set a bitmap in the 
// constructor, look below.

// ** Bitmap Setting **

// Loads a bitmap from a resource string or filename.
//  Leave either lpszResourceName or lpszFilename NULL.
BOOL LoadBitmap (LPCTSTR lpszResourceName, 
                 LPCTSTR lpszFilename);

// Loads a bitmap from a resource ID
BOOL LoadBitmap (int nIDResource);

// Makes a copy of a given bitmap and uses the copy.  
// This is like SetBitmap but you are not responsible 
// for handling the bitmap.
BOOL CopyBitmapFrom (CBitmap *pBitmap);

// Uses the bitmap you specify.  NOTE: You are responsible 
// for handling the bitmap.
void SetBitmap (CBitmap *pBitmap);

// ** Transparency **

// Specifies whether the window should use transparency.
//  TRUE for transparent, FALSE for opaque. (default is 
//  FALSE)
void SetTransparent (BOOL bTransparent);
BOOL GetTransparent ();

// Specifies the color that you want to be transparent.
void SetTransColor (COLORREF col);
COLORREF GetTransColor ();

// Specifies whether static (text) controls have a 
// transparent background.
//  TRUE for transparent, FALSE for opaque. (default 
//  is TRUE)
void SetStaticTransparent (BOOL bTransparent);
BOOL GetStaticTransparent ();

// ** Dragging **

// With a transparent dialog, you usually won't have a 
// caption (like my example). 
//  These functions make it so that you can drag anywhere 
//  on the dialog to move it.  TRUE is on and FALSE is off. 
//  (default is FALSE)
void SetClickAnywhereMove (BOOL bMove);
BOOL GetClickAnywhereMove ();


Tips

* In the resource editor, you can't tell exactly how big the dialog will need to be to hold the entire bitmap. You could either try out different sizes, or if you don't have "show window contents while dragging" (windows option) enabled, you could drag the dialog and see how much extra dialog you have on the edge when it shows you the frame.

* Dialogs that use transparency usually look best without a caption or a border. In the resource editor for your dialog, uncheck "title bar" and set "border" to "none."

How it works

It overrides CWnd::OnEraseBackground() to draw the bitmap as the background.
It overrides CWnd::OnCtlColor() to make static controls transparent.
It makes parts of the window transparent by combining many small window regions. (look at CBitmapDialog::MakeWindowRgn())
It allows you to drag anywhere to move by making Windows think that you clicked on the caption (even if there is no caption bar).

Downloads

Download demo project (include Release build) - 100 Kb
Download source - 5 Kb


Comments

  • More concessions with herveleger, more nick!

    Posted by jonemspf on 04/26/2013 11:08am

    maidenlackeybe in intensity withget hold ofstrongrep

    Reply
  • Fix for black ComboBox Dropdown

    Posted by Anarchi on 05/13/2009 02:58am

    Add this to CBitmapDialog::OnCtlColor()
    
    
    	// Combo Box
    	if (_tcscmp(lpszClassName, "ComboLBox")== 0)
    	{
    		return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    	}
    
    

    Reply
  • Problem with combo box under Win XP

    Posted by Harald Dietewich on 05/24/2005 06:35am

    Under Windwos XP the listbox portion of a combo box is drwan transparently. Any idea how to avoid this?

    Reply
  • workaround to avoid XP bug with transparent checkboxes

    Posted by Legacy on 02/04/2004 12:00am

    Originally posted by: Mario Schlesinger

    When running this application under Windows XP using a
    
    corresponding manifest-file "BmpDlg.exe.manifest" (to
    activate the usage of Luna style), a bug becomes visible:
    all checkboxes (and some other controls) won't be displayed
    transparent but completely in black color. There were
    different approaches to avoid this behaviour, but none of
    them seemed to take effect like i was exspecting. So i
    burned a few brain cells to find a new way for a workaround.

    Simply change the OnCtlColor method the following way:

    HBRUSH CBitmapDialog::OnCtlColor(CDC* pDC,
    CWnd* pWnd,
    UINT nCtlColor)
    {
    TCHAR lpszClassName[255];
    CDC dcSrc;
    RECT rc;

    GetClassName(pWnd->m_hWnd,
    lpszClassName, 255);

    // special handling for sliders, frames
    // and checkboxes
    if ((pWnd->GetStyle() & BS_CHECKBOX) ||
    (pWnd->GetStyle() & BS_RADIOBUTTON) ||
    (pWnd->GetStyle() & BS_AUTORADIOBUTTON) ||
    (_tcscmp(lpszClassName, TRACKBAR_CLASS)
    == 0)){
    COLORREF col;
    dcSrc.CreateCompatibleDC(NULL);
    dcSrc.SelectObject(m_bmBitmap);
    pWnd->GetWindowRect(&rc);
    pWnd->GetParent()->ScreenToClient(&rc);
    if (_tcscmp(lpszClassName,
    TRACKBAR_CLASS) == 0)
    col = GetPixel(dcSrc,
    rc.left+4, rc.top+4);
    else
    col = GetPixel(dcSrc,
    rc.left, rc.top);
    dcSrc.DeleteDC ();
    pDC->SetBkMode(TRANSPARENT);
    return (HBRUSH)CreateSolidBrush(col);
    }

    // don't customize editfields
    if (_tcscmp(lpszClassName, "Edit") == 0)
    return CDialog::OnCtlColor(pDC, pWnd,
    nCtlColor);

    // default handling: transparent
    pDC->SetBkMode(TRANSPARENT);
    return m_brushHollow;
    }

    By doing this, the application forces critical controls to
    use explicit background-colors, which are determined
    directly from the background-bitmap at the appropriate
    position. This won't give you controls which are really
    transparent, but looks a lot better than just black boxes.
    And: it even works correctly under GUI-transformers
    like WindowBlinds.

    By combining "empty" checkboxes (without text) with a
    static text on the right side of this checkbox, you'll get
    almost perfect looking controls, even under Luna XP.

    PS: Probably my code could be improved by managing the
    needed solid brushes at dialog initialization, so that
    they'll be created just once for each control and then
    being used automatically. My example should be an approach only.

    PPS: Don't blame me for my english. I'm not a native
    speaker. :-)


    Reply
  • Some Problem in function LoadBitmap (LPCTSTR lpszResourceName, LPCTSTR lpszFilename)

    Posted by Legacy on 01/08/2004 12:00am

    Originally posted by: 박경로

    Thank David Forrester.
    Your Source Code was very Good. And I used it in my project. Using your code I corrected some function like below. Sorry My English is poor. Have a nice day!

    LoadBitmap (LPCTSTR lpszResourceName, LPCTSTR lpszFilename)
    ......
    else
    {
    // Load the bitmap from a file
    HBITMAP hbm = (HBITMAP) LoadImage (NULL, szFilename, IMAGE_BITMAP, 0, 0,
    LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    if (hbm == NULL) return FALSE;

    // Get the CBitmap object
    CopyBitmapFrom (CBitmap::FromHandle(hbm));
    DeleteObject(hbm); //Add To prevent memory leack
    }

    and I recommend MakeWindowRgn()

    ........
    // Go through all rows
    for (int y=0; y<height; y++)
    {
    // Start looking at the beginning
    row_start = 0;

    // Go through all columns
    for (int x=0; x<width; x++)
    {
    // If this pixel is transparent
    if (dcImage.GetPixel(x, y) == m_colTrans)
    {
    // If we haven't found an opaque pixel yet, keep searching
    if (row_start == x) row_start ++;
    else
    {
    // We have found the start (row_start) and end (x) of
    // an opaque line. Add it to the region.
    CRgn rgnAdd;
    rgnAdd.CreateRectRgn (row_start,
    y, x, y+1);
    rgn.CombineRgn (&rgn, &rgnAdd, RGN_OR);
    row_start = x+1;
    }
    }
    }

    // If the last pixel is still opaque, make a region.
    if (row_start != x)
    {
    CRgn rgnAdd;

    rgnAdd.CreateRectRgn (row_start, y,
    x, y+1);

    rgn.CombineRgn (&rgn, &rgnAdd, RGN_OR);
    }
    }
    dcImage.SelectObject(pOldBitmap);
    SetWindowRgn (rgn, TRUE);
    }

    Reply
  • Check box doesn't work with Windows XP & Theme

    Posted by Legacy on 12/23/2003 12:00am

    Originally posted by: Sergej

    Check box background get's completelly black once you return HOLLOW_BRUSH for the static control in OnCtrlColor.

    But only with Windows XP and themes enabled.
    Any idea?

    Steps to reproduce: just create a manifest file for the test application and run it under windows XP with standard theme (Luna)

    Reply
  • Irregular Dialog

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

    Originally posted by: Ebadul Hossain

    Nice solution to build up another shapped dialog.

    Reply
  • Error with Group Box and Picture static controls

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

    Originally posted by: Kyselgov E.N.

    This class has error while drawing transparent group box and picture static controls.

    When you add picture static control with icon, it will be draw incorrect. Namely, almost all icons have transparent region (background), and when you use picture static with icon, this region is dialog background color (background are determinate by dialog background brush). But, CBitmapDialog::OnCtlColor() sets HOLLOW_BRUSH as dialog background brush for all static control (except TRACKBAR_CLASS controls), evidently, picture static draws with BLACK background.

    Group box with text header is drawn whit similar error. CBitmapDialog::OnCtlColor() sets TRANSPARENT method for text output. Consequently, text header (caption) will be strikethrough by group box border.

    All others static controls are drawn correctly.

    P.S. As is well known, .NET window form have background image feature, and if all child static controls has transparent background color then form draws without any artifacts. Does anybody know how it works?

    Reply
  • Adding Checkbox and combobox in tool bar

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

    Originally posted by: Ahmad, Lahore

    How can I add a checkbox and radio buttons in a tool bar in VC++.

    Reply
  • Debug Assertion Failed

    Posted by Legacy on 02/21/2003 12:00am

    Originally posted by: Sara

    I try this code, and I get several of these messages windows that Say:

    Debug Assertion Failed
    Program: etc etc
    file:afxwin2.inl
    line: 90 (also 96 and a few others)

    can anyone think of a reason this might happen?

    thanks
    Sara

    Reply
  • Loading, Please Wait ...

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 …

  • Stories about devastating cyberattacks are plaguing the news. Why? The DNS protocol is easy to exploit. See your network the way hackers do—as an easy target. Learn how you can effectively secure your DNS infrastructure today.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds