用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();
】;
VC绘制不规则窗口(只适合对话框程序)
最新推荐文章于 2019-03-10 20:48:15 发布