通常情況下,窗口都是一個矩形,不過,調用下面這個函數,可以自定義窗口的形狀。
~~~
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函數。
- 前言
- (1):關于C++的幾個要點
- (2):完整的開發流程
- (3):窗口的重繪
- (4):創建菜單
- (5):具有單選標記的菜單
- (6):創建右鍵菜單
- (7):多邊形窗口
- (8):繪圖(A)
- (9):繪圖(B)
- (10):繪圖(C)
- (11):使用控件——先來耍一下按鈕
- (12):使用控件——單選按鈕
- (13):握手對話框
- (14):用對話框作為主窗口
- (15):ListView控件
- (16):ListView的多個視圖
- (17):啟動和結束進程
- (18):使用對話框的兩個技巧
- (19):瀏覽和打開文件
- (20):瀏覽文件夾
- (21):復制&amp;粘貼&amp;剪貼板操作
- (22):抓取屏幕
- (23):漸變顏色填充
- (24):計時器
- (25):監視剪貼板