跟我一起玩Win32开发(7):多边形窗口

通常情况下,窗口都是一个矩形,不过,调用下面这个函数,可以自定义窗口的形状。

[cpp] view plain copy
 
  1. int SetWindowRgn(  
  2.     __in  HWND hWnd,  
  3.     __in  HRGN hRgn,  
  4.     __in  BOOL bRedraw  
  5.   );  


第一个参数是窗口的句柄,第二个参数也是一个句柄——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。

[cpp] view plain copy
 
  1. WNDCLASS wc = {};  
  2. wc.lpszClassName = L"MyApp";  
  3. wc.hbrBackground = CreateSolidBrush(RGB(254, 239, 180));  
  4. wc.lpfnWndProc = WindowProc;  
  5. wc.hInstance = hThisApp;  
  6. wc.style = CS_HREDRAW | CS_VREDRAW;  
  7. wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);  
  8. RegisterClass(&wc);  
  9. HWND hwnd = CreateWindow(L"MyApp",  
  10.     L"我的应用",  
  11.     WS_POPUP,  
  12.     300,140,400,400,  
  13.     NULL,NULL,hThisApp,NULL);  
  14. if(hwnd == NULL)  
  15.     return -1;  
  16. POINT pts[5] =   
  17. {  
  18.     { 200, 0},   
  19.     { 0, 160 },  
  20.     { 120, 400 },  
  21.     { 285, 400 },  
  22.     { 400, 160 }  
  23. };  
  24.   
  25. HRGN rgn = CreatePolygonRgn(pts, 5, WINDING);  
  26. SetWindowRgn(hwnd, rgn, FALSE);  
  27. //DeleteObject(rgn);  
  28. ShowWindow(hwnd,nShow);  
  29.    //UpdateWindow(hwnd);  


为了去掉标题栏和边框,我在CreateWindow的时候,使用WS_POPUP。

不过,这窗口好像有点单调,于是,我想着能画些什么东西在上面,故也处理了WM_PAINT消息。

[cpp] view plain copy
 
  1. case WM_PAINT:  
  2.     {  
  3.         PAINTSTRUCT ps;  
  4.         BeginPaint(hwnd, &ps);  
  5.         //创建红色的pen  
  6.         HPEN pen= CreatePen(PS_DASHDOTDOT, 1, RGB(255,0,0));  
  7.         //把pen选择到设备上下文  
  8.         auto orgObj = SelectObject(ps.hdc, pen);  
  9.         //第一部分  
  10.         POINT lnpts1[5] =   
  11.         {  
  12.             {200,50}, {180,360}, {220, 360}, {60,120}, {340,120}  
  13.         };  
  14.         BYTE bts1[5] =  {PT_MOVETO, PT_LINETO, PT_LINETO,  PT_MOVETO, PT_LINETO };  
  15.         PolyDraw(ps.hdc,lnpts1,bts1,5);  
  16.         // 第二部分  
  17.         POINT lnpts2[2] = { {200,50}, {220,360} };  
  18.         BYTE bts2[2] = { PT_MOVETO, PT_LINETO};  
  19.         PolyDraw(ps.hdc, lnpts2, bts2, 2);  
  20.         // 第三部分  
  21.         POINT lnpts3[2] = {{180,360}, {60,120}};  
  22.         BYTE bts3[2] = {PT_MOVETO, PT_LINETO};  
  23.         PolyDraw(ps.hdc, lnpts3, bts3, 2);  
  24.         // 第四部分  
  25.         POINT lnpts4[2] = {{220,360}, {340,120}};  
  26.         BYTE bts4[2] = {PT_MOVETO, PT_LINETO};  
  27.         PolyDraw(ps.hdc, lnpts4, bts4, 2);  
  28.         SelectObject(ps.hdc, orgObj);  
  29.         // 删除HPEN  
  30.         DeleteObject(pen);  
  31.         EndPaint(hwnd, &ps);  
  32.     }  
  33.     return 0;  


画些线条上面,让窗口可视区域看上去不那么单调。

下面是完整的代码清单。

[cpp] view plain copy
 
  1. #include <Windows.h>  
  2.   
  3. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);  
  4.   
  5. int WINAPI WinMain(HINSTANCE hThisApp,  
  6.                     HINSTANCE hPrevApp,  
  7.                     LPSTR cmdlint,  
  8.                     int nShow)  
  9. {  
  10.     WNDCLASS wc = {};  
  11.     wc.lpszClassName = L"MyApp";  
  12.     wc.hbrBackground = CreateSolidBrush(RGB(254, 239, 180));  
  13.     wc.lpfnWndProc = WindowProc;  
  14.     wc.hInstance = hThisApp;  
  15.     wc.style = CS_HREDRAW | CS_VREDRAW;  
  16.     wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);  
  17.     RegisterClass(&wc);  
  18.     HWND hwnd = CreateWindow(L"MyApp",  
  19.         L"我的应用",  
  20.         WS_POPUP,  
  21.         300,140,400,400,  
  22.         NULL,NULL,hThisApp,NULL);  
  23.     if(hwnd == NULL)  
  24.         return -1;  
  25.     POINT pts[5] =   
  26.     {  
  27.         { 200, 0},   
  28.         { 0, 160 },  
  29.         { 120, 400 },  
  30.         { 285, 400 },  
  31.         { 400, 160 }  
  32.     };  
  33.   
  34.     HRGN rgn = CreatePolygonRgn(pts, 5, WINDING);  
  35.     SetWindowRgn(hwnd, rgn, FALSE);  
  36.     //DeleteObject(rgn);  
  37.     ShowWindow(hwnd,nShow);  
  38.     //UpdateWindow(hwnd);  
  39.   
  40.     // 消息循环  
  41.     MSG msg;  
  42.     while(GetMessage(&msg, NULL, 0, 0))  
  43.     {  
  44.         TranslateMessage(&msg);  
  45.         DispatchMessage(&msg);  
  46.     }  
  47.   
  48.     return 0;  
  49. }  
  50.   
  51. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  
  52. {  
  53.     switch(msg)  
  54.     {  
  55.     case WM_PAINT:  
  56.         {  
  57.             PAINTSTRUCT ps;  
  58.             BeginPaint(hwnd, &ps);  
  59.             //创建红色的pen  
  60.             HPEN pen= CreatePen(PS_DASHDOTDOT, 1, RGB(255,0,0));  
  61.             //把pen选择到设备上下文  
  62.             auto orgObj = SelectObject(ps.hdc, pen);  
  63.             //第一部分  
  64.             POINT lnpts1[5] =   
  65.             {  
  66.                 {200,50}, {180,360}, {220, 360}, {60,120}, {340,120}  
  67.             };  
  68.             BYTE bts1[5] =  {PT_MOVETO, PT_LINETO, PT_LINETO,  PT_MOVETO, PT_LINETO };  
  69.             PolyDraw(ps.hdc,lnpts1,bts1,5);  
  70.             // 第二部分  
  71.             POINT lnpts2[2] = { {200,50}, {220,360} };  
  72.             BYTE bts2[2] = { PT_MOVETO, PT_LINETO};  
  73.             PolyDraw(ps.hdc, lnpts2, bts2, 2);  
  74.             // 第三部分  
  75.             POINT lnpts3[2] = {{180,360}, {60,120}};  
  76.             BYTE bts3[2] = {PT_MOVETO, PT_LINETO};  
  77.             PolyDraw(ps.hdc, lnpts3, bts3, 2);  
  78.             // 第四部分  
  79.             POINT lnpts4[2] = {{220,360}, {340,120}};  
  80.             BYTE bts4[2] = {PT_MOVETO, PT_LINETO};  
  81.             PolyDraw(ps.hdc, lnpts4, bts4, 2);  
  82.             SelectObject(ps.hdc, orgObj);  
  83.             // 删除HPEN  
  84.             DeleteObject(pen);  
  85.             EndPaint(hwnd, &ps);  
  86.         }  
  87.         return 0;  
  88.     case WM_DESTROY:  
  89.         PostQuitMessage(0);  
  90.         return 0;  
  91.     }  
  92.     return DefWindowProc(hwnd, msg, wParam, lParam);  
  93. }  

关于绘图方面的东东,后面会专门介绍,这里重点是说一下SetWindowRgn函数。

原文地址:https://www.cnblogs.com/weekbo/p/8681901.html