Thursday, September 19, 2024

An easy way to use Skins in a Dialog based Application

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)
{
&nbsp &nbsp if(m_hBmp)
&nbsp&nbsp {
&nbsp&nbsp&nbsp&nbsp BITMAP bm;
&nbsp&nbsp&nbsp&nbsp GetObject(m_hBmp,sizeof(bm),&bm);
&nbsp&nbsp&nbsp&nbsp HDC hMemdc=CreateCompatibleDC(pDC->m_hDC);
&nbsp&nbsp&nbsp&nbsp if(hMemdc)
&nbsp&nbsp&nbsp&nbsp {
&nbsp&nbsp&nbsp HBITMAP hOldBmp=(HBITMAP)SelectObject(hMemdc,m_hBmp);
&nbsp&nbsp&nbsp&nbsp if(hOldBmp)
&nbsp&nbsp&nbsp&nbsp {
&nbsp&nbsp&nbsp BitBlt(pDC->m_hDC,0,0,bm.bmWidth,bm.bmHeight,hMemdc,0,0,SRCCOPY);
&nbsp&nbsp&nbsp SelectObject(hMemdc,hOldBmp);
&nbsp&nbsp&nbsp DeleteDC(hMemdc);
&nbsp&nbsp&nbsp DeleteObject(hOldBmp);
&nbsp&nbsp&nbsp return TRUE;
&nbsp&nbsp &nbsp }
&nbsp&nbsp&nbsp else
&nbsp&nbsp&nbsp DeleteDC(hMemdc);
&nbsp&nbsp&nbsp }
&nbsp&nbsp}
&nbsp&nbspreturn CDialog::OnEraseBkgnd(pDC);
&nbsp}

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.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles

Floxclicknews provides all latest ai tools and software tools news at one place discover the trending tool. 41 آمار وب سایت درباره ترافیک و ترجیحات کاربر.