见过搜狗拼音的奥运主题,鸟巢和水立方作背景,而且整个界面是不规则的,看着很有意思,于是想自己用图片做一个。现在所实现的仅是单色背景的图片。
创建不规则使用下面这个API函数
int SetWindowRgn( HWND hWnd, // handle to window HRGN hRgn, // handle to region BOOL bRedraw // window redraw option );
需要做是把非背景色的像素绘制出来即可:可以逐行进行扫描,遇到不为背景色的像素则创建绘制区域。将得到的区域和创建好的空区域作或,合并在一起,然后向下逐行进行扫描,重复即可得到整个图片除背景色外的像素区域。
- #include "windows.h"
- #include "resource.h"
- /************************************************************/
- #define ButtonID 1000
- #define PictureW 480 //图片的宽
- #define PictureH 410 //高
- HWND g_hwndButton; //保存按钮句柄
- HWND g_hWnd; //保存窗体句柄
- HBITMAP g_hBitMap; //保存位图句柄
- HDC g_hDC; //保存设备DC句柄
- HRGN wndRgn; //保存RGN数据句柄
- HINSTANCE g_hInstance;
- char ClassName[] = "cws_class";
- char DisplayName[] = "custom windows shape";
- char ButtonClassName[] = "button";
- char ButtonText[] = "Click Me!";
- char Text[] = "Good bye...";
- void SetupRegion(HDC hDC, HBITMAP &cBitmap, COLORREF TransColor)
- {
- //创建与传入DC兼容的临时DC
- HDC memDC= ::CreateCompatibleDC(hDC);
- HBITMAP hOldMemBmp(0);
- //将位图选入临时DC
- hOldMemBmp = (HBITMAP)::SelectObject(memDC,cBitmap);
- //创建总的窗体区域,初始region为0
- wndRgn = ::CreateRectRgn(0,0,0,0);
- BITMAP bit;
- //取得位图参数,这里要用到位图的长和宽
- GetObject(cBitmap,sizeof(BITMAP),&bit);
- int y;
- for(y=0;y<=bit.bmHeight ;y++)
- {
- HRGN rgnTemp; //保存临时region
- int iX = 0;
- do
- {
- //跳过透明色找到下一个非透明色的点.
- while (iX <= bit.bmWidth &&
- GetPixel(memDC,iX, y) == TransColor)
- iX++;
- //记住这个起始点
- int iLeftX = iX;
- //寻找下个透明色的点
- while (iX <= bit.bmWidth &&
- GetPixel(memDC,iX, y) != TransColor)
- ++iX;
- //创建一个包含起点与终点间高为1像素的临时“region”
- rgnTemp = CreateRectRgn(iLeftX, y, iX, y+1);
- //合并到主"region".
- CombineRgn(wndRgn,wndRgn,rgnTemp, RGN_OR);
- //删除临时"region",否则下次创建时和出错
- DeleteObject(rgnTemp);
- }while(iX <bit.bmWidth );
- iX = 0;
- }
- if(hOldMemBmp)
- SelectObject(memDC,hOldMemBmp);
- HWND hWnd = WindowFromDC(hDC);
- SetWindowRgn(hWnd,wndRgn,TRUE);
- SetForegroundWindow(hWnd);
- }
- /************************************************************/
- LRESULT CALLBACK WindowProc( HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- switch(uMsg)
- {
- case WM_CREATE:
- g_hBitMap = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); //加载背景位图
- g_hDC = BeginPaint(g_hWnd,NULL);
- SetupRegion(g_hDC,g_hBitMap,RGB(255,0,0));
- SetWindowRgn(hwnd,wndRgn,TRUE);//设定RGN数据
- g_hwndButton = CreateWindowEx(NULL,ButtonClassName,ButtonText,
- WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
- 320,270,120,30,hwnd,(HMENU)ButtonID,g_hInstance,NULL);
- break;
- case WM_COMMAND:
- if(LOWORD(wParam) == ButtonID)
- {
- MessageBox(hwnd,Text,DisplayName,MB_OK);
- SendMessage(hwnd,WM_DESTROY,NULL,NULL);
- }
- break;
- case WM_LBUTTONDOWN:
- SendMessage(hwnd,WM_NCLBUTTONDOWN,HTCAPTION,lParam);
- break;
- case WM_DESTROY:
- PostQuitMessage(NULL);
- break;
- default:
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
- }
- return 0;
- }
- int APIENTRY WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- WNDCLASSEX wc;
- MSG msg;
- g_hInstance = hInstance;
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_HREDRAW | CS_VREDRAW |CS_BYTEALIGNWINDOW;
- wc.lpfnWndProc = WindowProc;
- wc.cbClsExtra = NULL;
- wc.cbWndExtra = NULL;
- wc.hInstance = hInstance;
- wc.hbrBackground = CreatePatternBrush(LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP1)));
- wc.lpszMenuName = NULL;
- wc.lpszClassName = ClassName;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor(NULL,IDC_CROSS);
- wc.hIconSm = NULL;
- RegisterClassEx(&wc);
- g_hWnd = CreateWindowEx(WS_EX_LEFT,
- ClassName,
- DisplayName,
- WS_POPUP,
- (GetSystemMetrics(SM_CXSCREEN) - PictureW)/2,
- (GetSystemMetrics(SM_CYSCREEN) - PictureH)/2,
- PictureW,
- PictureH,
- NULL,
- NULL,
- hInstance,
- NULL
- );
- ShowWindow(g_hWnd,SW_SHOWNORMAL);
- UpdateWindow(g_hWnd);
- while(GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return msg.wParam;
- }
资源文件只包含了位图的定义。
这样就可以看到我传的图片的效果了。不是太好,但是一种思路,以前怎么也想不到这种效果,总以为窗口是矩形的,中间如果有空着的区域的话,点住空白区域拖动窗体是随鼠标一起动的,但创建不规则窗口则可以实现“镂空”效果。不信可以试试呵呵。