矩形非金属补偿器,非矩形窗口示例


#include
#include
#include
#include "resource.h"
#define DRAGGING 0x01
#define IMAGE_NAME _T("Rgn.bmp")
HINSTANCE g_hInstance;
HDC g_dcBkGrnd;
DWORD g_dwWidth;
DWORD g_dwHeight;
int g_ptMouseX;
int g_ptMouseY;
DWORD g_dwFlags;
HRGN CreateRgnFromFile(HBITMAP hBmp, COLORREF color)
{
// 得到图片属性
BITMAP bmp = { 0 };
GetObject(hBmp, sizeof(BITMAP), &bmp);
// 为图片扩展信息分配内存
LPBITMAPINFO bi = (LPBITMAPINFO)new BYTE[sizeof(BITMAPINFO) + 8];
memset(bi, 0, sizeof(BITMAPINFO) + 8);
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// 设置图片大小
g_dwWidth = bmp.bmWidth; // 图片宽度
g_dwHeight = bmp.bmHeight; // 图片高度
// 创建临时DC
HDC dc = CreateIC(_T("DISPLAY"), NULL, NULL, NULL);
// 得到图片扩展信息
DWORD res = GetDIBits(dc, hBmp, 0, bmp.bmHeight, 0, bi, DIB_RGB_COLORS);
// 分配图片数据内存
LPBYTE pBits = new BYTE[bi->bmiHeader.biSizeImage + 4];
// 分配颜色表
if (bi->bmiHeader.biBitCount == 8)
{
// 真正的颜色表应该加上BITMAPINFO头
LPBITMAPINFO old_bi = bi;
// 255 - 还有一个在BITMAPINFOHEADER
bi = (LPBITMAPINFO)new char[ sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD) ];
memcpy( bi, old_bi, sizeof(BITMAPINFO) );
delete old_bi;
}
// 得到图片信息头
BITMAPINFOHEADER& bih = bi->bmiHeader;
// 得到颜色表
LPDWORD clr_tbl = (LPDWORD)&bi->bmiColors;
// 填充位缓存
res = GetDIBits(dc, hBmp, 0, bih.biHeight, pBits, bi, DIB_RGB_COLORS);
DeleteDC( dc );
BITMAP bm;
GetObject(hBmp, sizeof(BITMAP), &bm);
LPBYTE pClr = (LPBYTE)&color;
// 交换红色和蓝色部分
BYTE tmp = pClr[0]; pClr[0] = pClr[2]; pClr[2] = tmp;
// 如果当前DC是16-bit (5:6:5)
if ( bih.biBitCount == 16 )
{
color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
((DWORD)(pClr[1] & 0xfc) << 3) |
((DWORD)(pClr[2] & 0xf8) << 8);
}
const DWORD RGNDATAHEADER_SIZE = sizeof(RGNDATAHEADER);
const DWORD ADD_RECTS_COUNT = 40;
BYTE Bpp = bih.biBitCount >> 3; // 每像素位数
DWORD m_dwAlignedWidthBytes = (bmp.bmWidthBytes & ~0x3) + (!!(bmp.bmWidthBytes & 0x3) << 2);
// DIB图像是反的,所以我们从最后一行开始扫描
LPBYTE pColor = pBits + (bih.biHeight - 1) * m_dwAlignedWidthBytes;
DWORD dwLineBackLen = m_dwAlignedWidthBytes + bih.biWidth * Bpp; // 前一行偏移
DWORD dwRectsCount = bih.biHeight; // RECT数
INT i, j; // 在mask中的当前位置
INT first = 0; // 当前行的左边位置
bool wasfirst = false; // 标记当前行是否找到mask
bool ismask; // 标记当前色是mask色
RGNDATAHEADER* pRgnData =
(RGNDATAHEADER*)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
memset(pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT));
pRgnData->dwSize = RGNDATAHEADER_SIZE;
pRgnData->iType = RDH_RECTANGLES;
for (i = 0; i < bih.biHeight; i++)
{
for (j = 0; j < bih.biWidth; j++)
{
// 得到颜色
switch (bih.biBitCount)
{
case 8:
ismask = (clr_tbl[ *pColor ] != color);
break;
case 16:
ismask = (*(LPWORD)pColor != (WORD)color);
break;
case 24:
ismask = ((*(LPDWORD)pColor & 0x00ffffff) != color);
break;
case 32:
ismask = (*(LPDWORD)pColor != color);
}
// 下一个颜色
pColor += Bpp;
if (wasfirst)
{
if (!ismask)
{
// 保存当前RECT
RECT rect = {first, i, j, i + 1};
pRects[pRgnData->nCount++] = rect;
// 如果空间不够就分配新空间
if (pRgnData->nCount >= dwRectsCount)
{
dwRectsCount += ADD_RECTS_COUNT;
LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
delete pRgnData;
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
wasfirst = false;
}
}
else if (ismask)
{
first = j;
wasfirst = true;
}
}
if (wasfirst && ismask)
{
// 保存当前 RECT
RECT rect = {first, i, j, i + 1};
pRects[pRgnData->nCount++] = rect;
// 如果需要更多内存
if ( pRgnData->nCount >= dwRectsCount )
{
dwRectsCount += ADD_RECTS_COUNT;
// 分配新内存
LPBYTE pRgnDataNew = new BYTE[RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT)];
// 拷贝当前Region数据
memcpy(pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT));
// 删除旧的Region数据
delete pRgnData;
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
// 指向正确的RECT表
pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
}
wasfirst = false;
}
pColor -= dwLineBackLen;
}
delete pBits;
delete bi;
// 创建 Region
HRGN hRgn = ExtCreateRegion(NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData);
// 释放Region数据
delete pRgnData;
return hRgn;
}
BOOL _disibledevent=> IMAGE_NAME, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hBmp != NULL)
{
// 创建Region, 用红色作为透明色
HRGN hRgn = CreateRgnFromFile(hBmp, RGB(255, 0, 0));
// 创建背景DC
HDC dc = GetDC(hwnd);
g_dcBkGrnd = CreateCompatibleDC(dc);
ReleaseDC(hwnd, dc);
// 选入背景图片
SelectObject(g_dcBkGrnd, hBmp);
// 设置窗口大小与图片大小一置
SetWindowPos(hwnd, HWND_TOP, 0, 0, g_dwWidth, g_dwHeight, SWP_NOZORDER | SWP_NOMOVE);
// 设置Region到窗口
SetWindowRgn(hwnd, hRgn, FALSE);
}
return TRUE;
}
void _disibledevent=> HDC dc = BeginPaint(hwnd, &ps);
if (g_dcBkGrnd)
BitBlt(dc, 0, 0, g_dwWidth, g_dwHeight, g_dcBkGrnd, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
}
BOOL _disibledevent=> EndDialog(hwnd, 0);
}
void _disibledevent=> ReleaseCapture();
}
}
void _disibledevent=> g_ptMouseY = y;
g_dwFlags |= DRAGGING;
SetCapture(hwnd);
}
}
void _disibledevent=> rect.top += y - g_ptMouseY;
SetWindowPos(hwnd, NULL, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
}
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
HANDLE_MSG(hwndDlg, WM_INITDIALOG, _disibledevent=> DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
return 0;
}
Tags: 

延伸阅读

最新评论

发表评论