通常情況下,窗口都是一個矩形,不過,調用下面這個函數,可以自定義窗口的形狀。
int SetWindowRgn( __in HWND hWnd, __in HRGN hRgn, __in BOOL bRedraw );
第一個參數是窗口的句柄,第二個參數也是一個句柄——HRGN,一個多邊形的區域,可 以用CreatePolygonRgn函數來創建。第三個參數指定函數調用成功後是否重畫窗口,如果窗口還沒有顯 示,就不必了,如果窗口已經顯示,可以考慮設為TRUE。
我們創建用於顯示窗口形狀的區域句 柄HRGN可以不顯示用DeleteObject函數刪除,因為MSDN上面有這麼一句話:In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.
OK,理論知識准備好了,下面就趁溫暖打鐵,實戰一下吧。
接下來我們要做出 這個模樣的窗口。
由於這個形狀是固定的,只需要設置一次即可,所以,我不打算在處理WM_PAINT消息的時候來設 置多邊形區域,改為在CreateWindow成功後就設置,設置之後再ShowWindow。
WNDCLASS wc = {}; wc.lpszClassName = L"MyApp"; wc.hbrBackground = CreateSolidBrush(RGB(254, 239, 180)); wc.lpfnWndProc = WindowProc; wc.hInstance = hThisApp; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hCursor = LoadCursor(hThisApp, IDC_ARROW); RegisterClass(&wc); HWND hwnd = CreateWindow(L"MyApp", L"我的應用", WS_POPUP, 300,140,400,400, NULL,NULL,hThisApp,NULL); if(hwnd == NULL) return -1; POINT pts[5] = { { 200, 0}, { 0, 160 }, { 120, 400 }, { 285, 400 }, { 400, 160 } }; HRGN rgn = CreatePolygonRgn(pts, 5, WINDING); SetWindowRgn(hwnd, rgn, FALSE); //DeleteObject(rgn); ShowWindow(hwnd,nShow); //UpdateWindow(hwnd);
為了去掉標題欄和邊框,我在CreateWindow的時候,使用 WS_POPUP。
不過,這窗口好像有點單調,於是,我想著能畫些什麼東西在上面,故也處理了 WM_PAINT消息。
case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); //創建紅色的pen HPEN pen= CreatePen(PS_DASHDOTDOT, 1, RGB(255,0,0)); //把pen選擇到設備上下文 auto orgObj = SelectObject(ps.hdc, pen); //第一部分 POINT lnpts1[5] = { {200,50}, {180,360}, {220, 360}, {60,120}, {340,120} }; BYTE bts1[5] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_MOVETO, PT_LINETO }; PolyDraw(ps.hdc,lnpts1,bts1,5); // 第二部分 POINT lnpts2[2] = { {200,50}, {220,360} }; BYTE bts2[2] = { PT_MOVETO, PT_LINETO}; PolyDraw(ps.hdc, lnpts2, bts2, 2); // 第三部分 POINT lnpts3[2] = {{180,360}, {60,120}}; BYTE bts3[2] = {PT_MOVETO, PT_LINETO}; PolyDraw(ps.hdc, lnpts3, bts3, 2); // 第四部分 POINT lnpts4[2] = {{220,360}, {340,120}}; BYTE bts4[2] = {PT_MOVETO, PT_LINETO}; PolyDraw(ps.hdc, lnpts4, bts4, 2); SelectObject(ps.hdc, orgObj); // 刪除HPEN DeleteObject(pen); EndPaint(hwnd, &ps); } return 0;
畫些線條上面,讓窗口可視區域看上去不那麼單調。
下面是完整的代 碼清單。
#include <Windows.h> LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR cmdlint, int nShow) { WNDCLASS wc = {}; wc.lpszClassName = L"MyApp"; wc.hbrBackground = CreateSolidBrush(RGB(254, 239, 180)); wc.lpfnWndProc = WindowProc; wc.hInstance = hThisApp; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hCursor = LoadCursor(hThisApp, IDC_ARROW); RegisterClass(&wc); HWND hwnd = CreateWindow(L"MyApp", L"我的應用", WS_POPUP, 300,140,400,400, NULL,NULL,hThisApp,NULL); if(hwnd == NULL) return -1; POINT pts[5] = { { 200, 0}, { 0, 160 }, { 120, 400 }, { 285, 400 }, { 400, 160 } }; HRGN rgn = CreatePolygonRgn(pts, 5, WINDING); SetWindowRgn(hwnd, rgn, FALSE); //DeleteObject(rgn); ShowWindow(hwnd,nShow); //UpdateWindow(hwnd); // 消息循環 MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); //創建紅色的pen HPEN pen= CreatePen(PS_DASHDOTDOT, 1, RGB(255,0,0)); //把pen選擇到設備上下文 auto orgObj = SelectObject(ps.hdc, pen); //第一部分 POINT lnpts1[5] = { {200,50}, {180,360}, {220, 360}, {60,120}, {340,120} }; BYTE bts1[5] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_MOVETO, PT_LINETO }; PolyDraw(ps.hdc,lnpts1,bts1,5); // 第二部分 POINT lnpts2[2] = { {200,50}, {220,360} }; BYTE bts2[2] = { PT_MOVETO, PT_LINETO}; PolyDraw(ps.hdc, lnpts2, bts2, 2); // 第三部分 POINT lnpts3[2] = {{180,360}, {60,120}}; BYTE bts3[2] = {PT_MOVETO, PT_LINETO}; PolyDraw(ps.hdc, lnpts3, bts3, 2); // 第四部分 POINT lnpts4[2] = {{220,360}, {340,120}}; BYTE bts4[2] = {PT_MOVETO, PT_LINETO}; PolyDraw(ps.hdc, lnpts4, bts4, 2); SelectObject(ps.hdc, orgObj); // 刪除HPEN DeleteObject(pen); EndPaint(hwnd, &ps); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); }
關於繪圖方面的東東,後面會專門介紹,這裡重點是說一下SetWindowRgn函數。