BitMask分析

  • Post author:
  • Post category:其他


//头文件

#include <Windows.h>

#include “resource.h”

//预处理

#ifdef


UNICODE

#define CF_TCHAR


CF_UNICODETEXT

#else

#define CF_TCHAR


CF_TEXT

#endif

//全局变量

HINSTANCE


hInst;

TCHAR


szAppName[] = TEXT(“BitMask”);

//自定义函数

//1.功能:弹出对应数值的对话框

void MB_Value(int i)

{



TCHAR szBuffer[100];



wsprintf(szBuffer, TEXT(“%d”), i);



MessageBox(0, szBuffer, szBuffer, 0);

}

//主窗口消息过程

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{



HDC


hdc, hdcMemImag, hdcMemMask;



PAINTSTRUCT


ps;



static int


cxClient, cyClient, cxBitmap, cyBitmap;



static HBITMAP


hBitmapImag, hBitmapMask;



int


x, y;



BITMAP


bitmap;



switch (message)



{



case WM_CREATE:



//初始化2个位图, cxBitmap, cyBitmap



hBitmapImag = LoadBitmap(hInst, TEXT(“MATTHEW”));



GetObject(hBitmapImag, sizeof(BITMAP), &bitmap);



cxBitmap = bitmap.bmWidth;



cyBitmap = bitmap.bmHeight;



hBitmapMask = CreateBitmap(cxBitmap, cyBitmap, 1, 1, 0);



//初始化2个Memory DC



hdcMemImag = CreateCompatibleDC(0);



hdcMemMask = CreateCompatibleDC(0);



//将位图载入DC



SelectObject(hdcMemImag, hBitmapImag);



SelectObject(hdcMemMask, hBitmapMask);



//绘制hBitmapMask位图



SelectObject(hdcMemMask, GetStockObject(BLACK_BRUSH));



Rectangle(hdcMemMask, 0, 0, cxBitmap, cyBitmap);


//黑色矩形



SelectObject(hdcMemMask, GetStockObject(WHITE_BRUSH));



Ellipse(hdcMemMask, 0, 0, cxBitmap, cyBitmap);


//白色椭圆



//对第一个位图进行位运算



// 使用AND(与)操作符来将模板传送到原始位图上



// 由于模板位图是单色的,所以白色为1,黑色为0。通过AND操作,删除了源位图中椭圆以外的图素



BitBlt(hdcMemImag, 0, 0, cxBitmap, cyBitmap, hdcMemMask, 0, 0, SRCAND);





//左边是现在的hBitmapImag


//右边是hBiutmapMask



// 删除内存环境,得到了黑色包围的椭圆区域位图hdcMemImag



DeleteObject(hdcMemImag);



DeleteObject(hdcMemMask);



return 0;



case WM_SIZE:



//窗口大小发生变化时



cxClient = LOWORD(lParam);



cyClient = HIWORD(lParam);



return 0;



case WM_PAINT:



//窗口重新绘制时



hdc = BeginPaint(hwnd, &ps);



//Select bitmaps in to memory DCs



// 用于传送最终位图的内存环境



hdcMemImag = CreateCompatibleDC(hdc);



SelectObject(hdcMemImag, hBitmapImag);



// 用于设置背景色的内存环境



hdcMemMask = CreateCompatibleDC(hdc);



SelectObject(hdcMemMask, hBitmapMask);



//Center image



// 窗口大小 减去 位图大小 除以2 得到除开位图的平均中心区域,用于中心显示位图



x = (cxClient – cxBitmap) / 2;



y = (cyClient – cyBitmap) / 2;



//do the bit



// 0x220326 所执行的操作为 D & !S


(先将模板图素(hdcBitmapMask)取反 ,再与程序窗体色进行位AND运算后合并)



// 该操作先将原来黑色包围白色椭圆的位图,变为白色包围黑色椭圆的位图



// 最后通过AND合并,黑色为0。所以得到一个程序窗口中心为黑色椭圆的窗口画面


//左边是现在的hBitmapImag


//右边是hBitmapMask




BitBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemMask, 0, 0, 0x220326);



取反

//


BitBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemMask, 0, 0, SRCCOPY);

//


BitBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, SRCCOPY);



// SRCPAINT 在来源和目的之间进行位OR操作



// 由于该位图在椭圆以外为黑色0,OR保持了程序窗口原始色彩不变



// 最终将这个修改过的椭圆位图,显示到了窗口中心区域



BitBlt(hdc, x, y, cxBitmap, cyBitmap, hdcMemImag, 0, 0, SRCPAINT);



O

R

最后的结果就为



DeleteDC(hdcMemImag);



DeleteDC(hdcMemMask);



EndPaint(hwnd, &ps);



return 0;



case WM_DESTROY:



//退出清除



DeleteObject(hBitmapImag);



DeleteObject(hBitmapMask);



PostQuitMessage(0);



return 0;



default:



break;



}



return DefWindowProc(hwnd, message, wParam, lParam);

}

//程序入口

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLines, int iCmdShow)

{



hInst = hInstance;



HWND


hwnd;



MSG


msg;



WNDCLASS


wndclass;



wndclass.style = CS_HREDRAW | CS_VREDRAW;



wndclass.cbClsExtra = 0;



wndclass.cbWndExtra = 0;



wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);



wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);



wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);



wndclass.hInstance = hInstance;



wndclass.lpfnWndProc = WndProc;



wndclass.lpszClassName = szAppName;



wndclass.lpszMenuName = NULL;



if (!RegisterClass(&wndclass))



{



MessageBox(NULL, TEXT(“The program requires Window 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;

}