/*-------------------------------------------
BITMASK.C -- Bitmap Masking Demonstration
(c) Charles Petzold, 1998
-------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName [] = TEXT ("BitMask") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Bitmap Masking Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hBitmapImag, hBitmapMask ;
static HINSTANCE hInstance ;
static int cxClient, cyClient, cxBitmap, cyBitmap ;
BITMAP bitmap ;
HDC hdc, hdcMemImag, hdcMemMask ;
int x, y ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_CREATE:
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
// 载入位图资源,获取位图信息
hBitmapImag = LoadBitmap (hInstance, TEXT ("Matthew")) ;
GetObject (hBitmapImag, sizeof (BITMAP), &bitmap) ;
cxBitmap = bitmap.bmWidth ;
cyBitmap = bitmap.bmHeight ;
// 创建兼容内存环境,并载入位图
hdcMemImag = CreateCompatibleDC (NULL) ;
SelectObject (hdcMemImag, hBitmapImag) ;
// 创建与资源位图同样大小的单色蒙板位图,并载入另一个兼容内存环境中
hBitmapMask = CreateBitmap (cxBitmap, cyBitmap, 1, 1, NULL) ;
hdcMemMask = CreateCompatibleDC (NULL) ;
SelectObject (hdcMemMask, hBitmapMask) ;
// 为蒙板内存环境载入黑色画刷,并用该画刷填充整个区域
SelectObject (hdcMemMask, GetStockObject (BLACK_BRUSH)) ;
Rectangle (hdcMemMask, 0, 0, cxBitmap, cyBitmap) ;
// 画一个白色的椭圆形,在蒙板内存环境中间
SelectObject (hdcMemMask, GetStockObject (WHITE_BRUSH)) ;
Ellipse (hdcMemMask, 0, 0, cxBitmap, cyBitmap) ;
// Mask the original image
// 使用AND(与)操作符来将蒙板传送到原始位图上
// 由于蒙板位图是单色的,所以白色为1,黑色为0。通过AND操作,删除了源位图中椭圆以外的图素
BitBlt (hdcMemImag, 0, 0, cxBitmap, cyBitmap,
hdcMemMask, 0, 0, SRCAND) ;
// 删除内存环境,得到了黑色包围的椭圆区域位图hdcMemImag
DeleteDC (hdcMemImag) ;
DeleteDC (hdcMemMask) ;
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
// 用于传送最终位图的内存环境
hdcMemImag = CreateCompatibleDC (hdc) ;
SelectObject (hdcMemImag, hBitmapImag) ;
// 用于设置背景色的内存环境
hdcMemMask = CreateCompatibleDC (hdc) ;
SelectObject (hdcMemMask, hBitmapMask) ;
// 窗口大小 减去 位图大小 除以2 得到除开位图的平均中心区域,用于中心显示位图
x = (cxClient - cxBitmap) / 2 ;
y = (cyClient - cyBitmap) / 2 ;
// 0x220326 所执行的操作为 D & !S (先将蒙板图素取反,再与程序窗体色进行位AND运算后合并)
// 该操作先将原来黑色包围白色椭圆的位图,变为白色包围黑色椭圆的位图
// 最后通过AND合并,黑色为0。所以得到一个程序窗口中心为黑色椭圆的窗口画面
BitBlt (hdc, x, y, cxBitmap, cyBitmap, hdcMemMask, 0, 0, 0x220326) ;
// SRCPAINT 在来源和目的之间进行位OR操作
// 由于该位图在椭圆以外为黑色0,OR保持了程序窗口原始色彩不变
// 最终将这个修改过的椭圆位图,显示到了窗口中心区域
BitBlt (hdc, x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, SRCPAINT) ;
DeleteDC (hdcMemImag) ;
DeleteDC (hdcMemMask) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
DeleteObject (hBitmapImag) ;
DeleteObject (hBitmapMask) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}