14.4.10 非矩形的位图图像
(1)“掩码”位图——单色位图,要显示的像素对应的掩码置1,不显示置0
(2)光栅操作(点这里,见此文分析)
(3)MaskBlt函数
①MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc,hbmMask, xMask, yMask, dwRop);
②前景和背景:在由hbmMask指定的掩码中,数值1表示在那个位置应使用dwRop指定的前景光栅操作码。数值0表示应使用dwRop指定的背景光栅操作码。
③用MAKEROP4(fore,back)组合光栅操作码
【BitMask程序】
效果图
/*------------------------------------------------------------ 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; WNDCLASSEX wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); //为了更好的效果,不用白色画刷 wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("Bitmap Masking Demo"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters 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) { PAINTSTRUCT ps; static int cxBitmap, cyBitmap, cxClient, cyClient; static HINSTANCE hInstance; static HBITMAP hBitmapImag, hBitmapMask; HDC hdc, hdcMemImag, hdcMemMask; BITMAP bitmap; int x, y; 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; //将原始图像选入内存DC hdcMemImag = CreateCompatibleDC(NULL); //这里用NULL没关系,只要是借个DC来修改原始图像 SelectObject(hdcMemImag, hBitmapImag); //创建单色掩码位图和内存DC hBitmapMask = CreateBitmap(cxBitmap, cyBitmap, 1, 1, NULL); //单色cxBitmap*cybitmap像素位图 hdcMemMask = CreateCompatibleDC(NULL); //这里用NULL没关系,只要是借个DC来修改掩码位图 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); //遮罩原始图像,只显示椭圆内的图像 BitBlt(hdcMemImag, 0, 0, cxBitmap, cyBitmap, hdcMemMask, 0, 0, SRCAND); //这里用“与”操作,只显示掩码为1的,但周围是黑色的。 DeleteDC(hdcMemImag); //可以删除,因为图像操作结果己保存在hBitmapImag中了。 DeleteDC(hdcMemMask); //可以删除,因为图像操作结果己保存在hBitmapMask中了。 return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); // hdcMemImag = CreateCompatibleDC(hdc); //这里要显示在客户区了,不用要NULL SelectObject(hdcMemImag, hBitmapImag); hdcMemMask = CreateCompatibleDC(hdc); SelectObject(hdcMemMask, hBitmapMask); x = (cxClient - cxBitmap) / 2; y = (cyClient - cyBitmap) / 2; ////掩码位图,至此是一个外部黑色的,里面为白色的椭圆 //0x220326=D&(~S),让椭圆内部为黑,外部白色,再&D,此时屏幕上为一个黑色椭圆。 //BitBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemMask, 0, 0, 0x220326); //源和目标进行逻辑或运算,或的结果就是黑色,区域将源和目标重叠部分(椭圆区域)显示出来。 //BitBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, SRCPAINT); //以上两句也可以用MaskBlt代替:MAKEROP4(fore,back),掩码为1为前景,掩码为0的地方为背景。 //因掩码图椭圆外为黑色,内部白色。因此前景的地方直接拷贝照片相应的地方(SRCCOPY), //背景的地方用画刷去刷(SRCPAINT) MaskBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, hBitmapMask, 0, 0, MAKEROP4(SRCCOPY, SRCPAINT)); DeleteDC(hdcMemImag); DeleteDC(hdcMemMask); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 BitMask.rc 使用 // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//BitMask.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h " END 2 TEXTINCLUDE BEGIN "#include ""winres.h"" " "