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

  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。

  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. HRGN rgn = CreatePolygonRgn(pts, 5, WINDING);
  25. SetWindowRgn(hwnd, rgn, FALSE);
  26. //DeleteObject(rgn);
  27. ShowWindow(hwnd,nShow);
  28. //UpdateWindow(hwnd);

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

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

  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;

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

下面是完整的代码清单。

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

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

跟我一起玩Win32开发(7):多边形窗口的更多相关文章

  1. 跟我一起玩Win32开发(转自CSDN-东邪独孤)

    跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...

  2. 跟我一起玩Win32开发(17):启动和结束进程

    这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...

  3. 跟我一起玩Win32开发(18):使用对话框的两个技巧

    相信大家知道对话框怎么用了,就是先用“资源编辑器”设计一个对话框,然后在代码中加载处理.今天,我向大家分享两个使用对话框的技巧,还是比较实用的.不用担心,先喝杯茶,很简单的,一点也不复杂,总之,看俺写 ...

  4. 跟我一起玩Win32开发(19):浏览和打开文件

    在应用程序中,我们很经常要实现的功能,是Open文件或保存文件对话框,让用户来选择一个或N个文件.本文我将介绍两种思路,第一种方法较为复杂,第二种方法较为简单. 方法一:老规矩 这是一种传统方法,使用 ...

  5. 跟我一起玩Win32开发(12):使用控件——单选按钮

    今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少. 哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问 ...

  6. 跟我一起玩Win32开发(21):复制&粘贴&剪贴板操作

    我要提醒一下大家,看了我的博文学到的知识,千万不要用于实际开发,不然你会被你的上司骂:“妈的,这些东西哪来的,从来没有人这样做过.”不信你试试,脑细胞被冻结的经理或者技术总监们肯定会这样说的. 如果是 ...

  7. 跟我一起玩Win32开发(4):创建菜单

    也不知道发生什么事情,CSDN把我的文章弄到首页,结果有不少说我在误人子弟,是啊,我去年就说过了,如果你要成为砖家级人物,请远离我的博客,我这个人没什么特长,唯一厉害的一点就是不相信权威,鄙视砖家,所 ...

  8. 跟我一起玩Win32开发(2):完整的开发流程

    上一篇中我给各位说了一般人认为C++中较为难的东西——指针.其实对于C++,难点当然不局限在指针这玩意儿上,还有一些有趣的概念,如模板类.虚基类.纯虚函数等,这些都是概念性的东西,几乎每一本C++书上 ...

  9. 跟我一起玩Win32开发(25):监视剪贴板

    自从郭大侠和蓉儿离开桃花岛后,最近岛比较寂静,有一种“门前冷落鞍马稀”的感觉.于是,老邪就拿出<九阴真经>认真阅读,同时用迅雷下载经典大剧<汉武大帝>晚上睡觉前看上几集,老邪一 ...

随机推荐

  1. Django-配置celery

    首先需要安装的包 pip install cellerypip install django-cellery pip install django-cellery-results pip instal ...

  2. Java Unit Testing - JUnit & TestNG

    转自https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaUnitTesting.html yet another insignifican ...

  3. 【献给CWNU的师弟】Web篇

    2014年10月8日 献给CWNU的师弟

  4. Spring中的事务管理(学习笔记)

    什么是事物? 事物是指逻辑上的一组操作,这组操作要么全部成功,要么全部失败. 事物的特性: 原子性.一致性.隔离性.持久性 Spring事务管理的高级接口: PlatformTransactionMa ...

  5. 答案{{index==0 ? '一' : (index==1 ? '二':'三' )}}

    答案{{index==0 ? '一' : (index==1 ? '二':'三' )}}    

  6. spark通信原理

    https://github.com/apache/spark/tree/master/core/src/main/scala/org/apache/spark/network https://git ...

  7. Deep Learning 31: 不同版本的keras,对同样的代码,得到不同结果的原因总结

    一.疑问 这几天一直纠结于一个问题: 同样的代码,为什么在keras的0.3.3版本中,拟合得比较好,也没有过拟合,验证集准确率一直高于训练准确率. 但是在换到keras的1.2.0版本中的时候,就过 ...

  8. php网站前台utf-8格式有时会出现莫名其妙的空白行,重新保存下编码格式就可以了

    php网站前台utf-8格式有时会出现莫名其妙的空白行,重新保存下编码格式就可以了.

  9. Hadoop MapReduce输入输出类型

    一.输入格式 1.输入分片split 一个分片对应一个map任务: 一个分片包含一个表(整个文件)上的若干行,而一条记录(单行)对应一行: 分片包含一个以字节为单位的长度 和 一组存储位置,分片不包含 ...

  10. asp.net下的cookieName

    https://stackoverflow.com/questions/1017144/rename-asp-net-sessionid Add to your web.config:- <sy ...