窗口分成两大部分:客户区和非客户区。非客户区再次细分:标题栏,如图片中顶部深蓝色;左边框,如图片中红色部分;上边框,如图片中绿色部分;右边框,如图片中右侧天蓝色部分;底边框,如图片中下面棕色部分。

之所以要有这样的区分,是因为,我在用函数SystemParametersInfo得到窗口的非客户区参数时,标题栏高度确实是上面深蓝色部分,不能达到客户区,在标题栏和客户区之间还有一个白色区域,我想这可能就是上边框吧。

需要用到的几个函数:

PatBlt:作用是在指定的矩形区域用指定的Brush画刷来填充这个区域。

SystemParametersInfo:得到系统的一些参数,比如标题栏的高度,边框宽度等。

GetSystemMetrics:有点和上面函数相同,但是感觉没有上面的SystemParametersInfo函数精确。

思路:在消息WM_NCPAINT,WM_NCACTIVATE,WM_MOVE响应时得到非客户区的DC(区别于客户区的DC),再得到矩形区域,用函数来填充颜色。拦截系统对这几个消息的处理。

注意:使用的DC一定要是非客户区的DC,用GetWindowDC来得到句柄,不能用GetDC,因为GetDC得到的是客户区的DC,这个DC只能用来涂鸦客户区。得到边框的宽度时,比如顶部边框,绿色部分,要在得到的基础上+4,否则的话不能完全填充为指定的绿色,也是个疑问。

 case WM_NOTIFY:case WM_MOVE:case WM_NCACTIVATE:case WM_NCPAINT:{//得到系统标题栏的信息:宽度、高度、矩形区域int tbheight,tbwidth;RECT wndrect,clientrect;GetWindowRect(hwnd,&wndrect);GetClientRect(hwnd,&clientrect);tbheight= GetSystemMetrics(SM_CYSIZE);//标题栏宽度//end 得到系统标题栏的信息//填充标题栏RECT rcWindow ;GetWindowRect(hwnd,&rcWindow);HDC hDc =  GetWindowDC(hwnd);HBRUSH hBrush = CreateSolidBrush(RGB(25,0,255));HBRUSH hOldbrush =(HBRUSH) SelectObject(hDc,(HGDIOBJ)hBrush);PatBlt(hDc,0,0,wndrect.right-wndrect.left,tbheight,PATCOPY);//end 填充标题栏//填充边框NONCLIENTMETRICS  nonmet;nonmet.cbSize=sizeof(NONCLIENTMETRICS);SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&nonmet,0);RECT borderleft,borderright,bordertop,borderbottom;borderleft.left = 0;borderleft.right = wndrect.left+7;borderleft.top=tbheight;borderleft.bottom=wndrect.bottom;hBrush = CreateSolidBrush(RGB(200,0,0));SelectObject(hDc,(HGDIOBJ)hBrush);PatBlt(hDc,borderleft.left,borderleft.top,nonmet.iPaddedBorderWidth+4,borderleft.bottom-borderleft.top,PATCOPY);SelectObject(hDc,(HGDIOBJ)hOldbrush);bordertop.left=0;bordertop.bottom=wndrect.top+nonmet.iCaptionHeight+nonmet.iPaddedBorderWidth+4;bordertop.right = wndrect.right;bordertop.top=nonmet.iCaptionHeight;hBrush = CreateSolidBrush(RGB(0,200,0));SelectObject(hDc,(HGDIOBJ)hBrush);PatBlt(hDc,bordertop.left,bordertop.top,bordertop.right-bordertop.left,nonmet.iPaddedBorderWidth+5,PATCOPY);SelectObject(hDc,(HGDIOBJ)hOldbrush);borderright.left=wndrect.right-wndrect.left-nonmet.iPaddedBorderWidth-4;borderright.top=nonmet.iCaptionHeight;borderright.bottom=wndrect.bottom;borderright.right = wndrect.right-wndrect.left;hBrush = CreateSolidBrush(RGB(0,100,200));SelectObject(hDc,(HGDIOBJ)hBrush);PatBlt(hDc,borderright.left,borderright.top,nonmet.iPaddedBorderWidth+4,borderright.bottom-borderright.top,PATCOPY);borderbottom.bottom = wndrect.bottom;borderbottom.left=nonmet.iPaddedBorderWidth+4;borderbottom.right = wndrect.right-wndrect.left-nonmet.iPaddedBorderWidth-4;borderbottom.top = wndrect.bottom-wndrect.top-nonmet.iPaddedBorderWidth-4;hBrush = CreateSolidBrush(RGB(100,80,80));SelectObject(hDc,(HGDIOBJ)hBrush);PatBlt(hDc,borderbottom.left,borderbottom.top,borderbottom.right-borderbottom.left,nonmet.iPaddedBorderWidth+4,PATCOPY);//end 填充边框SelectObject(hDc,(HGDIOBJ)hOldbrush);ReleaseDC(hwnd,hDc);
//DefWindowProc(hwnd,uMsg,wParam,lParam);
return 0;//拦截系统的处理
break;
}对DC的解释参考文章:
http://www.codeproject.com/Articles/89996/Drawing-in-Windows-101

对标题栏的理解:

在Win7下,设置主题为Basic类型的,得到一个界面如下:

外圈棕色部分就是边框,和上面说的上边框的位置不同,在对QQ窗口进行最大化也会看到红色的部分,这个部分是标题栏的位置。

几点注意:

1、三个系统按钮是为标题按钮,标题按钮和标题栏的宽度是一样大小的。

2、当最大化时,边框会消失。标准大小时,恢复状态。

调整后上边框为上绿色,结果如下:

而三个系统按钮就在最左边的位置 如图。

像Aero主题 和QQ 、迅雷等的按钮会发生变化,是因为是对这三个按钮处理的结果,上面的程序也有一个问题:当在单击到三个按钮的位置时会出现这三个按钮。如下:

就这个问题。

调整后的结果,:

对标题栏的理解:

在Win7下,设置主题为Basic类型的,得到一个界面如下:

外圈棕色部分就是边框,和上面说的上边框的位置不同,在对QQ窗口进行最大化也会看到红色的部分,这个部分是标题栏的位置。

而三个系统按钮就在最左边的位置 如图。

像Aero主题 和QQ 、迅雷等的按钮会发生变化,是因为是对这三个按钮处理的结果,上面的程序也有一个问题:当在单击到三个按钮的位置时会出现这三个按钮。如下:

就这个问题。

用位图来填充矩形:

目标是把三个按钮给覆盖:

         //处理三个按钮//第一步:定位位置--在右边框的左边,右侧贴右边框,左侧可通过SystemParametersInfo得到按钮宽度iCaptionHeight,再*3;上下边框在标题栏内。//第二步:用图片或者颜色给盖上,拦截NCLBUTTONDOWN消息。在单击位置在按钮区域时,分别发送3个消息,RECT btnrect;btnrect.bottom=nonmet.iCaptionHeight+nonmet.iBorderWidth;btnrect.left=wndrect.right-wndrect.left-nonmet.iCaptionHeight*3-nonmet.iBorderWidth;btnrect.right=btnrect.left+nonmet.iCaptionHeight*3;btnrect.top=nonmet.iBorderWidth;HDC hcomdc = CreateCompatibleDC(hDc);HBITMAP hbmp = LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_BITMAP4));HBITMAP holdbmp=(HBITMAP)SelectObject(hcomdc,(HGDIOBJ)hbmp);StretchBlt(hDc,btnrect.left-nonmet.iPaddedBorderWidth-14,btnrect.top+nonmet.iPaddedBorderWidth+4,nonmet.iCaptionHeight*3+12,nonmet.iCaptionHeight,hcomdc,0,0,60,20,SRCCOPY);//end处理三个按钮

结果如图:

拦截消息如下:

        GetWindowRect(hwnd,&wndrect);POINT *lpoint=(POINT *)lParam;int xPos = GET_X_LPARAM(lParam); int yPos = GET_Y_LPARAM(lParam);if(xPos>wndrect.left+btnrect.left-10&&xPos<wndrect.left+btnrect.right-10&&yPos>wndrect.top+btnrect.top+8&&yPos<wndrect.top+btnrect.bottom)return 0;break;

把窗口进行圆角操作:

需要在窗口大小变化后进行圆角操作。捕捉大小变化的消息是WM_SIZE, 这是窗口变化后的消息。代码如下:

    case WM_SIZE:{RECT wndRect;GetWindowRect(hWnd,&wndRect);HRGN hRgn=CreateRoundRectRgn(0,0,wndRect.right-wndRect.left,wndRect.bottom-wndRect.top,50,50);SetWindowRgn(hWnd,hRgn,true);if(hRgn)DeleteObject((HGDIOBJ)hRgn);break;}

转载于:https://www.cnblogs.com/ddx-deng/p/3755833.html

VC----SDK下对窗口非客户区的操作相关推荐

  1. 窗口非客户区绘制位图与设计

    原文:http://www.haogongju.net/art/1891934 首先介绍在指定区域绘制位图 为了能够在指定的区域中输出位图,需要使用设备上下文CDC类的StretchBlt方法.由于我 ...

  2. 客户区和非客户区指的什么?窗口客户区和视图客户区的区别

    客户区和非客户区指的什么?窗口客户区和视图客户区的区别! 1,什么是客户区/非客户区? 2, 窗口(框架/frame)的客户区和视图(view)的客户区的区别? 这些都是初学者很容易迷惑的地方,我也是 ...

  3. 客户区和非客户区指的什么?窗口客户区和视图客户区的区别(小问题大思想)

    1,什么是客户区/非客户区? 2, 窗口(框架/frame)的客户区和视图(view)的客户区的区别? 这些都是初学者很容易迷惑的地方,我也是很迷惑,不过经过一番折腾终于弄明白这些问题了.对于这些问题 ...

  4. Windows的三种坐标系:屏幕坐标系,非客户区坐标系,客户区坐标系

    1. 屏幕坐标系:以屏幕的左上角为原点,如图所示 GetWindowRect() 函数获得的 RECT 就是以屏幕坐标系算的. 2. 非客户区坐标系(窗口坐标系) 包括标题栏的部分.GetWindow ...

  5. Win32 鼠标消息 - 客户区鼠标消息、非客户区鼠标消息、击中测试、鼠标滚轮

    注:以下内容为学习笔记,多数是从书本.资料中得来,只为加深印象,及日后参考.然而本人表达能力较差,写的不好.因非翻译.非转载,只好选原创,但多数乃摘抄,实为惭愧.但若能帮助一二访客,幸甚! 注:以下内 ...

  6. vc++ mfc 非客户区 描绘线_决战客户端技术

    原文链接-决战客户端技术 最近经常有小伙伴问我要做一个客户端, 该怎么弄. 这个问题问得很粗犷, 但是实际上客户端的选型是一个很细的问题. 从大学到现在, 也弄了不少的客户端, 从公司主营炒股专业客户 ...

  7. 老话题:自己编写只截窗口客户区的截屏软件(VB2010)

    现在能实现截屏的软件很多,就不一一列举了,连WIN7都自带截屏软件,甚至OFFICE2010开始都有截屏的功能. 截屏软件虽多,无外乎三种截屏方式:全屏截图.窗口截图.自定义矩形截图. 其中,窗口截图 ...

  8. 窗口置顶(置于桌面所有程序之上)VC/MFC 怎么将窗口置顶

    软件界面全屏显示后,需要把窗体置于其他桌面程序之上,但总是置于其他弹出框之下,会造成用户忽略了导致用户不明什么原因. 百度查了好多方法总是失败. 后来查到了CSND的一个帖子http://bbs.cs ...

  9. 7.2 客户区鼠标消息

    摘录于<Windows程序(第5版,珍藏版).CHarles.Petzold 著>P223 第 6 章已经讲到,Windows 只把键盘消息发送到当前具有输入焦点的窗口.鼠标消息则不同:当 ...

最新文章

  1. QT的Q3DScatter类的使用
  2. Vim杂记:Sublime的配色方案
  3. python爬虫的一些技巧
  4. Java String类型变量的比较问题
  5. 修改MYSQL最大连接数的3种方法
  6. 信息学奥赛一本通(1060:均值)
  7. 在 Java 虚拟机上班是一种怎样的体验?
  8. 20200612每日一句
  9. 最新聚合支付四方系统完整源码+修复大量BUG/新UI
  10. Java 删除文件夹
  11. Python 3.7 pygame 下载方法
  12. 利用R语言如何计算出回归分析中的t值和P值
  13. php集成paypal付款流程,PHP整合PayPal支付_PHP教程
  14. 国庆节未休假的你,领到了三倍的工资吗?
  15. 【方向盘】2021年JVM生态报告:Java 11使用率超Java 8
  16. 生活随记 - 开门放水
  17. OpenGL深入探索——阴影贴图(二)
  18. 大华摄像头网页端控制+web串口(适用任何浏览器,不能用来打我)通讯合集
  19. winrar命令行打自解压安装包不生效问题
  20. git 在往云端push代码时候报错detached head

热门文章

  1. Kafka监控:Kafka-Manager
  2. Python基础-使用paramiko
  3. WiFi(网络)调试Android手机
  4. Codeforces Round #387 (Div. 2) 747F(数位DP)
  5. [工具资源] 《HelloGitHub》第 08 期
  6. PostgreSQL 9.6 IO Hang问题浅析与优化
  7. 电信网络拓扑图自动布局
  8. 简明批处理教程(2)
  9. mysql 随机槽_mysql怎样高效率随机获取n条数据
  10. freeswitch 用户配置详解_FreeSwitch安装配置记录-阿里云开发者社区