需求:时候在制作一些特殊的界面时可能要用到异形窗口。
解决方案:制一张位图,在位图中指定一个透明色,这个透明色大多作为背景,也就是窗口中要切除的部分,即在一张位图中提取一个区域窗口是一个再方便不过的事情了,实现原理实际上是读取位图中的每个像素和指定的透明色进行对比,如果是相同的颜色就排除,否则就合并起来。
//////////////////////////////////////////////////////////
//
// Funcution: CreateBitmapRgn
//
// Description:
// Create region window from block of bitmap specifies
//
// Parameters:
// nXDest x-coordinate of upper-left corner
// nYDest y-coordinate of upper-left corner
// nWidth x-coordinate of lower-right corner
// nHeight y-coordinate of lower-right corner
// nXSrc x-coordinate of start position
// nYSrc y-coordinate of start posttion
// clrTrans Specify the transparent color
//
// 2007-11-05 LiJun created
//
//////////////////////////////////////////////////////////
HRGN CreateBitmapRgn(
HBITMAP hBitmap,
int nXDest,
int nYDest,
int nWidth,
int nHeight,
int nXSrc,
int nYSrc,
COLORREF clrTrans
)
{
if( hBitmap == NULL )
return NULL;
HDC hMemDC;
HRGN hRgn, hPix;
HBITMAP OldBitmap;
hMemDC = CreateCompatibleDC(NULL);
hOldBitmap = SelectObject(hMemDC, hBitmap);
hRgn = CreateRectRgn(nXDest, nYDest, nXDest + nWidth, nYDest + nHeight);
for(int i=nXDest, x=nXSrc; i < nXDest+nWidth; i++, x++)
{
for(int j=nYDest, y=nYSrc; j < nYDest+nHeight; j++, y++)
{
if(GetPixel(hMemDC, x, y) == clrTrans)
{
hPix = CreateRectRgn(i, j, i+1, j+1);
CombineRgn(hRgn, hRgn, hPix, RGN_XOR);
DeleteObject(hPix);
}
}
}
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
return hRgn;
}
//
// Funcution: CreateBitmapRgn
//
// Description:
// Create region window from block of bitmap specifies
//
// Parameters:
// nXDest x-coordinate of upper-left corner
// nYDest y-coordinate of upper-left corner
// nWidth x-coordinate of lower-right corner
// nHeight y-coordinate of lower-right corner
// nXSrc x-coordinate of start position
// nYSrc y-coordinate of start posttion
// clrTrans Specify the transparent color
//
// 2007-11-05 LiJun created
//
//////////////////////////////////////////////////////////
HRGN CreateBitmapRgn(
HBITMAP hBitmap,
int nXDest,
int nYDest,
int nWidth,
int nHeight,
int nXSrc,
int nYSrc,
COLORREF clrTrans
)
{
if( hBitmap == NULL )
return NULL;
HDC hMemDC;
HRGN hRgn, hPix;
HBITMAP OldBitmap;
hMemDC = CreateCompatibleDC(NULL);
hOldBitmap = SelectObject(hMemDC, hBitmap);
hRgn = CreateRectRgn(nXDest, nYDest, nXDest + nWidth, nYDest + nHeight);
for(int i=nXDest, x=nXSrc; i < nXDest+nWidth; i++, x++)
{
for(int j=nYDest, y=nYSrc; j < nYDest+nHeight; j++, y++)
{
if(GetPixel(hMemDC, x, y) == clrTrans)
{
hPix = CreateRectRgn(i, j, i+1, j+1);
CombineRgn(hRgn, hRgn, hPix, RGN_XOR);
DeleteObject(hPix);
}
}
}
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
return hRgn;
}
从一段位图数据转换到DIB位图句柄
需求:有时要显示的一幅位图数据并不存储一个工程资源里或不是一个独立的文件,它可能是存储在数据库或一个结构存储对象里,所以就必需将读出的数据转换成一个DIB位图句柄
解决方案:Windows提供有一个API CreateDIBitmap函数它可以轻松的实现将一个DDB数据转换成DIB句柄(为了示例如何进行转换,下面例子从一个文件中读取DDB数据然后用CreateDIBitmap函数进行转换)
HBITMAP LoadBitmapEx(LPCTSTR lpszFile)
{
if(lpszFile == NULL)
return NULL;
HBITMAP hBitmap;
HANDLE hf;
BITMAPFILEHEADER* pbmfh;
DWORD dwBytesRead, dwFileSize, dwFileSizeHigh;
BOOL bSuccess;
// 打开一个bmp文件
hf = CreateFile(lpszFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if( hf == INVALID_HANDLE_VALUE)
{
TRACE("Open file filed with error %d ", GetLastError());
return NULL;
}
// 得到这个文件大小
dwFileSize = GetFileSize(hf, &dwFileSizeHigh);
if( dwFileSizeHigh )
{
CloseHandle(hf);
return NULL;
}
// 分配内存,大小为该文件的大小
pbmfh = (BITMAPFILEHEADER*)malloc(dwFileSize);
if( !pbmfh )
{
CloseHandle(hf);
return NULL;
}
// 读取数据
bSuccess = ReadFile(hf, pbmfh, dwFileSize, &dwBytesRead, NULL);
CloseHandle(hf);
// 效验文件大小和文件格式
if( !bSuccess || dwFileSize != dwBytesRead
|| pbmfh->bfType != 0x4D42 || pbmfh->bfSize != dwFileSize)
{
free((void*)pbmfh);
return NULL;
}
// 进行DIB转换
hBitmap = CreateDIBitmap(
GetWindowDC(NULL),
(BITMAPINFOHEADER*)(pbmfh + 1),
CBM_INIT,
(BYTE*)pbmfh + pbmfh->bfOffBits,
(BITMAPINFO*)(pbmfh + 1),
DIB_RGB_COLORS);
free((void*)pbmfh);
return hBitmap;
}
{
if(lpszFile == NULL)
return NULL;
HBITMAP hBitmap;
HANDLE hf;
BITMAPFILEHEADER* pbmfh;
DWORD dwBytesRead, dwFileSize, dwFileSizeHigh;
BOOL bSuccess;
// 打开一个bmp文件
hf = CreateFile(lpszFile, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if( hf == INVALID_HANDLE_VALUE)
{
TRACE("Open file filed with error %d ", GetLastError());
return NULL;
}
// 得到这个文件大小
dwFileSize = GetFileSize(hf, &dwFileSizeHigh);
if( dwFileSizeHigh )
{
CloseHandle(hf);
return NULL;
}
// 分配内存,大小为该文件的大小
pbmfh = (BITMAPFILEHEADER*)malloc(dwFileSize);
if( !pbmfh )
{
CloseHandle(hf);
return NULL;
}
// 读取数据
bSuccess = ReadFile(hf, pbmfh, dwFileSize, &dwBytesRead, NULL);
CloseHandle(hf);
// 效验文件大小和文件格式
if( !bSuccess || dwFileSize != dwBytesRead
|| pbmfh->bfType != 0x4D42 || pbmfh->bfSize != dwFileSize)
{
free((void*)pbmfh);
return NULL;
}
// 进行DIB转换
hBitmap = CreateDIBitmap(
GetWindowDC(NULL),
(BITMAPINFOHEADER*)(pbmfh + 1),
CBM_INIT,
(BYTE*)pbmfh + pbmfh->bfOffBits,
(BITMAPINFO*)(pbmfh + 1),
DIB_RGB_COLORS);
free((void*)pbmfh);
return hBitmap;
}