Click here to Skip to main content
11,431,829 members (64,990 online)
Click here to Skip to main content

Skins in a Dialog Based Application

, 9 Jun 2002
Rate this:
Please Sign up or sign in to vote.
An Easy way to skin a Dialog Based Application

Sample Image

Introduction

This is a very simple example to implement a skin in a Dialog Based Application. The code is actually written by a friend (sun@codefinger.de ) of mine, so thanks go to him. I am just showing you how simple it is to use. Also thanks to Davide Calabro who gave me permission to use his CButtonST class.

Example

In my example I am using a simple Dialog based App called “Skin”. Import a Bitmap you like for your Dialog. In our case it's labeled IDB_MAIN. Create the following variables and function in your Dialog header file.

CSkinDlg : public CDialog
{
public:
        CSkinDlg();
    HBITMAP m_hBmp;
    HRGN m_hWndRgn;
    HRGN DIBToRgn(HBITMAP hBmp,COLORREF BkColor,BOOL Direct); // Handle the Skin
    .
    .
    .
In the Constructor do the following:
CSkinDlg::CSkintDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CSkinDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CSkinDlg)
    //}}AFX_DATA_INIT
    m_hBmp=(HBITMAP)LoadImage(AfxGetApp()->m_hInstance,
                                   MAKEINTRESOURCE(IDB_MAIN),
                                   IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);

    m_hWndRgn=DIBToRgn(m_hBmp,0x00ff00,FALSE);
}

Insert the function called HRGN DIBToRgn(HBITMAP hBmp, COLORREF BkColor, BOOL Direct) to your Dialog class and paste the following code to it.

HRGN CSkinDlg ::DIBToRgn(HBITMAP hBmp, COLORREF BkColor, BOOL Direct)
{
    // use to return the handle of the HGRN
      HRGN hRgn = NULL;                    
    #define MAX_ALLOC_RECTS  100
    //the difference of the color
    COLORREF  Tolerance=0x00101010;
    if (hBmp)
    {
        //creat the dib to save the dc
        HDC hMemDC = CreateCompatibleDC(NULL);        
        if (hMemDC)
        {
            BITMAP bm;
            //get the info of the bitmap
            GetObject(hBmp, sizeof(bm), &bm);    

            BITMAPINFOHEADER BmpInfoh = {     // the struct of the bitmap
                    sizeof(BITMAPINFOHEADER), // biSize
                    bm.bmWidth,               // biWidth;
                    bm.bmHeight,              // biHeight;
                    1,                        // biPlanes;
                    32,                       // biBitCount
                    BI_RGB,                   // biCompression;
                    0,                        // biSizeImage;
                    0,                        // biXPelsPerMeter;
                    0,                        // biYPelsPerMeter;
                    0,                        // biClrUsed;
                    0                         // biClrImportant;
            };
            //design a void point to point to the bitmap
            LPVOID pBit32; 
            //creat a DIB
            HBITMAP hDib32 = CreateDIBSection(hMemDC, 
                    (BITMAPINFO *)&BmpInfoh, 
                    DIB_RGB_COLORS, &pBit32, NULL, 0);
            if (hDic32)
            {
                //copy dib to DC
                HBITMAP hOldib32 = (IBITMAP)SelectObject(hMemDC, hDib32);
                // create a DC to save orgin bitmap
                HDC hDC = CreateCompatibleDC(hMemDC);
                if (hDC)
                {
                    BITMAP bm32;
                    // get the new 34 bit Dib size
                    GetObject(hDib32, sizeof(bm32), &bm32);
                    //make sure the 32Dib's every line pilex's is 4 's times
                    while (bm32.bmWidthBytes % 4)
                        bm32.bmWidthBytes++;
                    //copy the orginal dib to DC
                    HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
                    //copy dib to memory DC
                    BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
                    DWORD MaxRects = MAX_ALLOC_RECTS;
                    SYSTEM_INFO  Sysinfo;
                    //get memory size
                    GetSystemInfo(&Sysinfo);
                    //make a stack which can chang big
                    //alloct memory
                    HANDLE hRcData=HeapCreate(HEAP_GENERATE_EXCEPTIONS,Sysinfo.dwPageSize, 0);
                    RGNDATA * pRcData=(RGNDATA*)HeapAlloc(hRcData,HEAP_ZERO_MEMORY,
                        sizeof(RGNDATAHEADER)+sizeof(RECT)*MaxRects);
                     //fill the the RGNDATA struck
                    pRcData->rdh.dwSize = sizeof(RGNDATAHEADER);
                    pRcData->rdh.iType = RDH_RECTANGLES;
                    pRcData->rdh.nCount = pRcData->rdh.nRgnSize = 0;
                    SetRect(&pRcData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
                             BYTE hr,hg,hb,lr,lg,lb;
                    switch(BkColor)
                    {
                    case RGB(255,255,255):    //if the bkcolor is white
                        hr = GetRValue(BkColor);
                        hg = GetGValue(BkColor);
                        hb = GetBValue(BkColor);
                        lr = min(0xff, hr - GetRValue(Tolerance));
                        lg = min(0xff, hg - GetGValue(Tolerance));
                        lb = min(0xff, hb - GetBValue(Tolerance));
                        break;
                    case RGB(0,0,0):    //if the bkcolor is black
                        lr = GetRValue(BkColor);
                        lg = GetGValue(BkColor);
                        lb = GetBValue(BkColor);
                        hr = min(0xff, lr + GetRValue(Tolerance));
                        hg = min(0xff, lg + GetGValue(Tolerance));
                        hb = min(0xff, lb + GetBValue(Tolerance));
                        break;
                    default:        //if the bkcolor is other color
                        Tolerance=0x111111;
                        lr =max(0, GetRValue(BkColor)-GetRValue(Tolerance));
                        lg = max(0,GetGValue(BkColor)-GetGValue(Tolerance));
                        lb = max(0,GetBValue(BkColor)-GetBValue(Tolerance));
                        hr=min(0xff,GetRValue(BkColor)+GetRValue(Tolerance));
                        hg=min(0xff,GetGValue(BkColor)+GetGValue(Tolerance));
                        hb=min(0xff,GetBValue(BkColor)+GetBValue(Tolerance));
                        break;
                    }
                    // Get the bit point and do the search
                    BYTE *pBits = (BYTE *)bm32.bmBits + 
                                         (bm32.bmHeight - 1) * bm32.bmWidthBytes;
                    for (int y = 0; y < bm.bmHeight; y++)
                    {
                        for (int x = 0; x < bm.bmWidth; x++)
                        {
                            int x0 = x;
                            DWORD *pColor = (DWORD *)pBits + x;
                            BYTE dr,dg,db;
                            while (x < bm.bmWidth)
                            {
                                dr=GetRValue(*pColor);
                                dg=GetGValue(*pColor);
                                db=GetBValue(*pColor);

                                if ((dr>= lr && dr<= hr) && (dg>=lg&&dg<=hg) 
                                                         && (db>=lb&&db<=hb))
                                {
                                    if(Direct)
                                        break;
                                    else
                                    {
                                        pColor++;
                                        x++;
                                    }
                                  }
                                else if(Direct)
                                {
                                    pColor++;
                                    x++;
                                }
                                else
                                    break;

                            }
                            if (x > x0)
                            {
                                if (pRcData->rdh.nCount >= MaxRects)
                                {
                                    MaxRects += MAX_ALLOC_RECTS;
                                    //re alloc the stack
                                    pRcData=(RGNDATA*)HeapReAlloc(
                                    hRcData,HEAP_ZERO_MEMORY,pRcData, 
                                    sizeof(RGNDATAHEADER)+sizeof(RECT)*MaxRects);
                                }
                                RECT *pr = (RECT *)&pRcData->Buffer;
                                SetRect(&pr[pRcData->rdh.nCount], x0, y, x, y+1);
                                pRcData->rdh.rcBound.left = x0;
                                pRcData->rdh.rcBound.top = y;
                                pRcData->rdh.rcBound.right = x;
                                pRcData->rdh.rcBound.bottom = y+1;
                                pRcData->rdh.nCount++;

                                if (pRcData->rdh.nCount == 3000)
                                {    
                                    HRGN tmphRgn = ExtCreateRegion(NULL,
                                    sizeof(RGNDATAHEADER) + (sizeof(RECT) * MaxRects),
                                    pRcData);
                                    if (hRgn)
                                    {
                                        CombineRgn(hRgn, hRgn, tmphRgn, RGN_OR);
                                        DeleteObject(tmphRgn);
                                    }
                                    else
                                        hRgn = tmphRgn;
                                    pRcData->rdh.nCount = 0;
                                    SetRect(&pRcData->rdh.rcBound, 
                                    MAXLONG, MAXLONG, 0, 0);
                                }
                            }
                        }

                        // search next line
                        pBits -= bm32.bmWidthBytes;
                    }
                    HRGN tmphRgn = ExtCreateRegion(NULL, 
                            sizeof(RGNDATAHEADER) + (sizeof(RECT) * MaxRects), pRcData);
                    if (hRgn)
                    {
                        CombineRgn(hRgn, hRgn, tmphRgn, RGN_OR);
                        DeleteObject(tmphRgn);
                    }
                    else
                        hRgn = tmphRgn;
                    // make a rect ,use this rect xor to the  BkColor
                    //then we can get the rect we want
                    if(!Direct)
                    {
                        HRGN hRect=CreateRectRgn(0,0,bm.bmWidth,bm.bmHeight);
                                        if(hRect)
                        {
                            CombineRgn(hRgn,hRgn,hRect,RGN_XOR);
                            DeleteObject(hRect);
                        }
                        else
                            return NULL;
                    }
                    //release the memory
                    HeapFree(hRcData,HEAP_NO_SERIALIZE,pRcData);
                    SelectObject(hDC, holdBmp);
                    DeleteDC(hDC);
                    DeleteObject(holdBmp);
                }
                SelectObject(hMemDC,hOldib32);
                DeleteDC(hMemDC);
                DeleteObject(hOldib32);
                DeleteObject(hDib32);
            }
            else
                DeleteDC(hMemDC);
        }
    }
    return hRgn;
  }

Add a handler for the ON_WM_ERASEBKND message to erase the background of the Dialog:

BOOL CSkinDlg::OnEraseBkgnd(CDC* pDC) 
{
    if(m_hBmp)
    {
        BITMAP bm;
        GetObject(m_hBmp,sizeof(bm),&bm);
        HDC hMemdc=CreateCompatibleDC(pDC->m_hDC); 
        if(hMemdc)
        {
           HBITMAP hOldBmp=(HBITMAP)SelectObject(hMemdc,m_hBmp);
           if(hOldBmp)
           {
               BitBlt(pDC->m_hDC,0,0,bm.bmWidth,bm.bmHeight,hMemdc,0,0,SRCCOPY);
               SelectObject(hMemdc,hOldBmp);
               DeleteDC(hMemdc);
               DeleteObject(hOldBmp);
               return TRUE;
           }
           else
             DeleteDC(hMemdc);
        }
    }
    return CDialog::OnEraseBkgnd(pDC);
}

In your OnInitDialog enter the following code:

BOOL CSkinDlg::OnInitDialog()
{
    .
    .
    .
    // Show the Skin
    if(m_hWndRgn)
        SetWindowRgn(m_hWndRgn,TRUE);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

The 'minimise' and 'close' boxes on the dialog are implemented using Davide Calabro's CButtonST class

That's it ! Run your app and you will see your Great Skin. This Article is Provided by www.codefinger.de

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

Share

About the Author

Sonu Kapoor

Canada Canada
No Biography provided

Comments and Discussions

 
Generalhttp://www.appspeed.com/ Pin
Tome11113-Apr-03 8:50
sussTome11113-Apr-03 8:50 
GeneralRe: SkinMagic Toolkit Pin
The ~Coder13-Apr-03 7:39
sussThe ~Coder13-Apr-03 7:39 
GeneralRe: SkinMagic Toolkit Pin
ActiveSkin13-Apr-03 8:55
sussActiveSkin13-Apr-03 8:55 
GeneralRe: SkinMagic Toolkit Pin
The ~Coder13-Apr-03 9:23
sussThe ~Coder13-Apr-03 9:23 
GeneralSkinMagic SUCKS!!! Pin
Bill SerGio, The Infomercial King25-May-03 1:07
memberBill SerGio, The Infomercial King25-May-03 1:07 
Generalwont work Pin
m1k3d3s23-Jan-03 8:34
memberm1k3d3s23-Jan-03 8:34 
GeneralRe: wont work Pin
Sonu Kapoor13-Apr-03 21:13
memberSonu Kapoor13-Apr-03 21:13 
GeneralRe: The better solution for skinnable application GUI Pin
The Coder12-Apr-03 13:42
sussThe Coder12-Apr-03 13:42 
GeneralRe: The better solution for skinnable application GUI Pin
GoodTool13-Apr-03 9:02
sussGoodTool13-Apr-03 9:02 
GeneralRe: The better solution for skinnable application GUI Pin
The ~Coder13-Apr-03 9:24
sussThe ~Coder13-Apr-03 9:24 
GeneralRe: The better solution for skinnable application GUI Pin
Misty_Blue10-Oct-04 18:51
memberMisty_Blue10-Oct-04 18:51 
QuestionTransparent background? Pin
mykone22-Dec-02 21:22
membermykone22-Dec-02 21:22 
QuestionWhere is the AppIcon? Pin
Michael Manske12-Aug-02 1:48
sussMichael Manske12-Aug-02 1:48 
AnswerRe: Where is the AppIcon? Pin
sunyuzhe13-Aug-02 14:55
susssunyuzhe13-Aug-02 14:55 
Generalthe bitmap moves! Pin
NightBlade17-Jul-02 11:07
memberNightBlade17-Jul-02 11:07 
GeneralRe: the bitmap moves! Pin
Sonu Kapoor17-Jul-02 21:07
memberSonu Kapoor17-Jul-02 21:07 
GeneralRe: the bitmap moves! Pin
NightBlade18-Jul-02 8:08
memberNightBlade18-Jul-02 8:08 
GeneralRe: the bitmap moves! Pin
Sonu Kapoor18-Jul-02 8:22
memberSonu Kapoor18-Jul-02 8:22 
GeneralRe: the bitmap moves! Pin
Anonymous6-Aug-02 18:17
sussAnonymous6-Aug-02 18:17 
Generalcouple of typo corrections Pin
Otyug13-Jul-02 15:13
memberOtyug13-Jul-02 15:13 
Questionnot really a skin class...? Pin
Mario M.11-Jun-02 11:20
memberMario M.11-Jun-02 11:20 
AnswerRe: not really a skin class...? Pin
Sonu Kapoor11-Jun-02 12:17
memberSonu Kapoor11-Jun-02 12:17 
GeneralRe: not really a skin class...? Pin
Mario M.11-Jun-02 14:14
memberMario M.11-Jun-02 14:14 
GeneralRe: not really a skin class...? Pin
Sonu Kapoor11-Jun-02 21:44
memberSonu Kapoor11-Jun-02 21:44 
GeneralNice Pin
Thomas Freudenberg11-Jun-02 1:37
memberThomas Freudenberg11-Jun-02 1:37 
GeneralRe: Nice Pin
Sonu Kapoor11-Jun-02 4:22
memberSonu Kapoor11-Jun-02 4:22 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150428.2 | Last Updated 10 Jun 2002
Article Copyright 2002 by Sonu Kapoor
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid