VC绘制不规则窗口(只适合对话框程序)

来源:互联网 发布:美工论坛怎么注册 编辑:程序博客网 时间:2024/05/16 01:15

用BMP位图绘制不规则窗口(只适合对话框程序)
原理就是把一张BMP位图上的指定颜色的像素点抠掉,其他地方正常显示,由此生成一个窗口区域,这样就可以实现不规则窗口了;
首先要有一张BMP图片,在上面绘图软件在上面绘好你要显示的内容,然后把你不想要显示的部分全部用一种颜色填充(注意,这种颜色只能出现在你想抠掉的区域中,如果其他地方也有这种颜色,那么到时候也会把哪些地方给抠掉)
.h头文件中声明

    CBitmap m_bmp;
    CRgn* m_rgnWnd;
    CRgn* BitmapToRegion(HBITMAP hBmp,COLORREF cTransparentColor=0,COLORREF cTolerance=0x101010);
;

.cpp源文件

    //这个函数体内部具体实现的暂不用管,只要知道怎么用,直接拿去用就成了
    CRgn* CXXXDlg::BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance)
{
    cTransparentColor=RGB(0,0,255);//要抠掉部分的颜色
    HRGN hRegion = NULL;
    if (hBmp)
    {
        //创建内存DC
        HDC hMemDC = CreateCompatibleDC(NULL);
        if (hMemDC)
        {
            // 取得位图大小
            BITMAP bm;
            GetObject(hBmp, sizeof(bm), &bm);
            BITMAPINFOHEADER RGB32BITSBITMAPINFO = {sizeof(BITMAPINFOHEADER),bm.bmWidth,bm.bmHeight,1,32,BI_RGB,0,0,0,0,0};
            VOID * pbits32;
            HBITMAP hBmp32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
            if (hBmp32)
            {
                HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hBmp32);
                // 创建复制位图到内存DC的DC
                HDC hDC = CreateCompatibleDC(hMemDC);
                if (hDC)
                {
                    BITMAP Bmp32;
                    GetObject(hBmp32, sizeof(Bmp32), &Bmp32);
                    while (Bmp32.bmWidthBytes % 4)
                        Bmp32.bmWidthBytes++;
                    //复制位图到内存DC
                    HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
                    BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
                    #define ALLOC_UNIT  100
                    DWORD maxRects = ALLOC_UNIT;
                    HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
                    RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
                    pData->rdh.dwSize = sizeof(RGNDATAHEADER);
                    pData->rdh.iType = RDH_RECTANGLES;
                    pData->rdh.nCount = pData->rdh.nRgnSize = 0;
                    SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
                    BYTE lr = GetRValue(cTransparentColor);
                    BYTE lg = GetGValue(cTransparentColor);
                    BYTE lb = GetBValue(cTransparentColor);
                    BYTE hr = min(0xff, lr + GetRValue(cTolerance));
                    BYTE hg = min(0xff, lg + GetGValue(cTolerance));
                    BYTE hb = min(0xff, lb + GetBValue(cTolerance));
                    BYTE *p32 = (BYTE *)Bmp32.bmBits + (Bmp32.bmHeight - 1) * Bmp32.bmWidthBytes;
                    for (int y = 0; y < bm.bmHeight; y++)
                    {
                        //从左到右扫描位图像素
                        for (int x = 0; x < bm.bmWidth; x++)
                        {
                            // 处理非透明色
                            int x0 = x;
                            LONG *p = (LONG *)p32 + x;
                            while (x < bm.bmWidth)
                            {
                                BYTE b = GetRValue(*p);
                                if (b >= lr && b <= hr)
                                {
                                    b = GetGValue(*p);
                                    if (b >= lg && b <= hg)
                                    {
                                        b = GetBValue(*p);
                                        if (b >= lb && b <= hb)                                        
                                            break;//这个像素是透明的
                                    }
                                }
                                p++;
                                x++;
                            }
                            if (x > x0)
                            {
                                if (pData->rdh.nCount >= maxRects)
                                {
                                    GlobalUnlock(hData);
                                    maxRects += ALLOC_UNIT;
                                    hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
                                    pData = (RGNDATA *)GlobalLock(hData);
                                }
                                RECT *pr = (RECT *)&pData->Buffer;
                                SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
                                if (x0 < pData->rdh.rcBound.left)
                                    pData->rdh.rcBound.left = x0;
                                if (y < pData->rdh.rcBound.top)
                                    pData->rdh.rcBound.top = y;
                                if (x > pData->rdh.rcBound.right)
                                    pData->rdh.rcBound.right = x;
                                if (y+1 > pData->rdh.rcBound.bottom)
                                    pData->rdh.rcBound.bottom = y+1;
                                pData->rdh.nCount++;

                                if (pData->rdh.nCount == 2000)
                                {
                                    HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
                                    if (hRegion)
                                    {
                                        CombineRgn(hRegion, hRegion, h, RGN_OR);
                                        DeleteObject(h);
                                    }
                                    else
                                        hRegion = h;
                                    pData->rdh.nCount = 0;
                                    SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
                                }
                            }
                        }
                        p32 -= Bmp32.bmWidthBytes;
                    }
                    HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
                    if (hRegion)
                    {
                        CombineRgn(hRegion, hRegion, h, RGN_OR);
                        DeleteObject(h);
                    }
                    else
                        hRegion = h;
                    SelectObject(hDC, holdBmp);
                    DeleteDC(hDC);
                }
                DeleteObject(SelectObject(hMemDC, holdBmp));
            }
            DeleteDC(hMemDC);
        }
    }
    return CRgn::FromHandle(hRegion);
}

OnInitDialog函数中
        m_bmp.LoadBitmap(IDB_NOTEDLG);
    m_rgnWnd = BitmapToRegion((HBITMAP)m_bmp.GetSafeHandle());//生成不规则图形
    SetWindowRgn((HRGN)m_rgnWnd->GetSafeHandle(),true);
OnPaint函数中
    CPaintDC dc(this);
    BITMAP bm;
    CDC dcMem;

    VERIFY(m_bmp.GetObject(sizeof(bm),(LPVOID)&bm));

    dcMem.CreateCompatibleDC(&dc);
    CBitmap *pOldBMP=(CBitmap *)dcMem.SelectObject(&m_bmp);

    CRect rect;
    GetClientRect(rect);
    dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcMem, 0, 0, SRCCOPY);
    dcMem.SelectObject(pOldBMP);
    dcMem.DeleteDC();

】;

原创粉丝点击