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 me, so I am not the one who wrote the code, thanks to him. I am just showing you how simple it is to use. Also thanks to “Davide Calabro” who gave me the Permission to use the CButtonST class.
Contents:
Source Code
A Simple Example
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 its the IDB_MAIN. Create the following variables and function in your Dialog header file.
CSkinDlg : public CDialog { public: CSkinDlg(); HBITMAP m_hBmp; HRGN m_hClientRgn; 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_hClientRgn=CreateEllipticRgn(33,34,34,35); 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; }
Overrite the ON_WM_ERASEBKND
function 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 }
That`s it ! Run your app and you will see your Great Skin.
Codefinger was founded 2000 by Sonu Kapoor. Sonu has studied E-Commerce in India and currently lives in Germany. After graduation he worked for several companies in Germany. He currently works as a Network Consultant and Software Developer. He has written many applications in various programming languages like VC++, ASP, ASP.NET, XML or XSL. Besides his passion for developing applications, Sonu writes articles for several major websites like Developer.com. He also works as a freelancer for CodeGuru.