
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);
.
.
.
In the Constructor do the following:
CSkinDlg::CSkintDlg(CWnd* pParent )
: CDialog(CSkinDlg::IDD, pParent)
{
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)
{
HRGN hRgn = NULL;
#define MAX_ALLOC_RECTS 100
COLORREF Tolerance=0x00101010;
if (hBmp)
{
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC)
{
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
BITMAPINFOHEADER BmpInfoh = {
sizeof(BITMAPINFOHEADER),
bm.bmWidth,
bm.bmHeight,
1,
32,
BI_RGB,
0,
0,
0,
0,
0
};
LPVOID pBit32;
HBITMAP hDib32 = CreateDIBSection(hMemDC,
(BITMAPINFO *)&BmpInfoh,
DIB_RGB_COLORS, &pBit32, NULL, 0);
if (hDic32)
{
HBITMAP hOldib32 = (IBITMAP)SelectObject(hMemDC, hDib32);
HDC hDC = CreateCompatibleDC(hMemDC);
if (hDC)
{
BITMAP bm32;
GetObject(hDib32, sizeof(bm32), &bm32);
while (bm32.bmWidthBytes % 4)
bm32.bmWidthBytes++;
HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
DWORD MaxRects = MAX_ALLOC_RECTS;
SYSTEM_INFO Sysinfo;
GetSystemInfo(&Sysinfo);
HANDLE hRcData=HeapCreate(HEAP_GENERATE_EXCEPTIONS,Sysinfo.dwPageSize, 0);
RGNDATA * pRcData=(RGNDATA*)HeapAlloc(hRcData,HEAP_ZERO_MEMORY,
sizeof(RGNDATAHEADER)+sizeof(RECT)*MaxRects);
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):
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):
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:
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;
}
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;
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);
}
}
}
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;
if(!Direct)
{
HRGN hRect=CreateRectRgn(0,0,bm.bmWidth,bm.bmHeight);
if(hRect)
{
CombineRgn(hRgn,hRgn,hRect,RGN_XOR);
DeleteObject(hRect);
}
else
return NULL;
}
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()
{
.
.
.
if(m_hWndRgn)
SetWindowRgn(m_hWndRgn,TRUE);
return TRUE;
}
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
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.