给对话框加上背景皮肤

本文介绍了一种在Windows对话框上添加皮肤的简单方法,通过使用DIBToRgn函数将位图转换为区域,实现对话框背景跟随皮肤图片自动调整大小。该方法涉及创建DIBSection、处理颜色差异、创建区域以及处理WM_ERASEBKGND消息等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对话框的skin

前段时间有些学生问我,怎么给我们做的对话框加上漂亮的skin,特别是就像qq游戏的登录以及游戏界面一样(qq游戏的登录界面就是一个对话框)。

经过一些曲折,我在www.codeproject.com中找到了一些给对话框及控件加skin的方式,在下面我通过一个例子给出了其中一种最简单的方法,通过这种方式作出的对话框会根据skin图片的大小调整。

在我的例子中,我用了首先做了一个简单的基于对话框的程序。然后给我们的工程插入一个图片资源。给这个bitmap资源一个资源IDIDB_MAIN。为对话框类加入以下的数据成员和成员函数。

 

CSkinDlg : public CDialog

{

public:

        CSkinDlg();

    HBITMAP m_hBmp;

    HRGN m_hWndRgn;

    HRGN DIBToRgn(HBITMAP hBmp,COLORREF BkColor,BOOL Direct); // Handle the Skin

//…

};

 

在构造函数中加入以下代码:

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

}

 

在你的对话框类中插入函数HRGN DIBToRgn(HBITMAP hBmp, COLORREF BkColor, BOOL Direct)并加入以下的代码:

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 (hDib32)

            {

                //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;

  }

 

加入一个ON_WM_ERASEBKND消息,在这里面删除对话框的背景:

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

}

 

最后在OnInitDialog中写入以下代码

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

}

 

这就是所有的过程,通过这个过程以后,我们的对话框的背景变为了我们引入的bitmap图片。

 

                                                    Tuesday, September 20, 2005

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值