hn4u @ Last updated 21/11/04 22:42
Go to my homepage at http://4u.jcisio.com
Full version available at http://4u.jcisio.com/r/article341.htm

Không rõ

Thay đổi skin của của sổ dialog

Trong ví dụ này một dialog được gọi là Skin.Chọn một hình bitmap cho dialog của bạn

Mã lệnh (C++)
CSkinDlg : public CDialog
{
 public: CSkinDlg();
 HBITMAP m_hBmp;
 HRGN m_hWndRgn;
 HRGN DIBToRgn(HBITMAP hBmp,COLORREF BkColor,BOOL Direct);
 // Handle the Skin . . .
}

Trong  Constructor Sẽ làm những việc sau đây:

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);
}

Thêm một hàm  HRGN DIBToRgn(HBITMAP hBmp, COLORREF BkColor, BOOL Direct)đến lớp Dialog của bạn
và dán đoạn code sau:
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)
   {
     //create 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 orginal 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 change big
                 //allocate 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 struct
                 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;
 }

thêm một  handler cho thông báo(message) ON_WM_ERASEBKND để xoá nền của 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);
}

Trong OnInitDialog, Thêm dòng code:

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

 return TRUE;
}


hainam4u @ Last updated 21/11/04 22:42
Go to my homepage at http://4u.jcisio.com