WM_NCCALCSIZE消息处理详解
【前言】
指定应用程序的标题高度和边框的宽度的方法有很多种。其中最普遍的方法有下面的两种:
第一种:创建没有标题栏应用程序,在客户区让出一部分空间用一幅图片画一个标题栏,让人“误认为”是标题栏。
第二种:处理应用程序接收到的WM_NCCALCSIZE消息,改变客户区在窗口中的位置,从而得到合适标题栏高度。
不能说哪一种方法好,哪一种方法不好,其实第一种做法简单易行,而且也能做得很漂亮,但不爽的一点是就是每一次画客户区的时候总是计算坐标的起始位置;第二种方法有点麻烦(其实也不麻烦),但有一点很好,客户区不用负责标题栏重绘工作,响应WM_PAINT消息时候不用计算位置。
【第二种】
要想得到最准确最全面的信息得去MS的老巢去找EN文版的(GOOGLE什么的最讨厌了),别怕一句一句看(俺的英语水平(360) << CET-4(425),我都能看懂,肯定没有人看不懂的了)。
wParam:
If wParam is TRUE, it specifies that the application should indicate which part of the client area contains valid information. The system copies the valid information to the specified area within the new client area.
If wParam is FALSE, the application does not need to indicate the valid part of the client area.
lParam:
If wParam is TRUE, lParam points to an NCCALCSIZE_PARAMS structure that contains information an application can use to calculate the new size and position of the client rectangle.
If wParam is FALSE, lParam points to a RECT structure. On entry, the structure contains the proposed window rectangle for the window. On exit, the structure should contain the screen coordinates of the corresponding window client area.
这是MSND上一段话:意思是如wParam为TRUE,需要在新矩形中指定可用的客户区;如果wParam为FALSE应用程序不用在新矩形中指定客户区。
我这样的理解的:当窗口创建时候的wParam为FALSE,其它情况为TRUE。
【TRUE情况】
假想:窗口一开始在A位置,突然移动到B位置。
如图:
这时候Windows将会给窗口发送一个WM_NCCALCSIZE消息,通知应用程序窗口的位置或者大小变了,应用程序应当指定新的非客户区和客户区的位置。消息具体内容的是:
message:WM_NCCALCSIZE
wParam: TRUE
lParam: 一个指向三个矩形的指针(NCCALCSIZE_PARAMS *)。下面是NCCALCSIZE_PARAMS结构:
typedef struct tagNCCALCSIZE_PARAMS {
RECT rgrc[3];
PWINDOWPOS lppos;
} NCCALCSIZE_PARAMS, *LPNCCALCSIZE_PARAMS;
下面是MSDN的一段说明:
rgrc
RECT
An array of rectangles. The meaning of the array of rectangles changes during the processing of the WM_NCCALCSIZE message.
When the window procedure receives the WM_NCCALCSIZE message, the first rectangle contains the new coordinates of a window that has been moved or resized, that is, it is the proposed new window coordinates. The second contains the coordinates of the window before it was moved or resized. The third contains the coordinates of the window's client area before the window was moved or resized. If the window is a child window, the coordinates are relative to the client area of the parent window. If the window is a top-level window, the coordinates are relative to the screen origin.
When the window procedure returns, the first rectangle contains the coordinates of the new client rectangle resulting from the move or resize. The second rectangle contains the valid destination rectangle, and the third rectangle contains the valid source rectangle. The last two rectangles are used
简易翻译一下(凑合看):
当窗口处理收到的WM_NCCALCSIZE消息是,第一个矩形包含了移动后或者改变大小后的新坐标(也就是B的坐标),它是建议的坐标。第二个矩形包含了移动或改变大小前的坐标(也就是A坐标),第三个矩形包含了客户区的移动前的坐标(也就是A坐标中的客户区坐标)。
处理这个消息返回之前(也就是WM_NCCALCSIZE处理完成后),第一个矩形应当包含新客户区的坐标(也就是B坐标中的客户区坐标),第二个矩形包含了可用的目标矩形(B坐标),第三个坐标包含了源矩形(A坐标)。后面的两个矩形也会被用到。简而言之:
我们在处理前的是:第一个矩形是B,第二个矩形是A,第三个矩形是AC,
我们在处理后的是:第一个矩形是BC,第二个矩形是B,第三个是矩形A。
于是我写下了下写的C处理代码:
int xFrame = 2; /*左右边框的厚度*/
int yFrame = 2; /*下边框的厚度*/
int nTHight = 40; /*标题栏的高度*/
NCCALCSIZE_PARAMS * p; /*TRUE是的指针*/
RECT * rc; /*FALSE是的指针*/
RECT aRect;
RECT bRect;
RECT bcRect;
if(wParam == TRUE)
{
p = (NCCALCSIZE_PARAMS *)lParam;
/*复制A B矩形位置*/
CopyRect(&aRect,&p->rgrc[1]);
CopyRect(&bRect,&p->rgrc[0]);
/*指定BC的矩形的位置*/
bcRect.left = bRect.left + xFrame;
bcRect.top = bRect.top + nTHight;
bcRect.right = bRect.right - xFrame;
bcRect.bottom = bRect.bottom - yFrame;
/*各个矩形归位成BC B A*/
CopyRect(&p->rgrc[0],&bcRect);
CopyRect(&p->rgrc[1],&bRect);
CopyRect(&p->rgrc[2],&aRect);
}
上面是处理了wParam为TRUE的情况,再回头来看FALSE的情况,就是初始化的时候,我们知道刚刚初始化的时候不是A->B而是从没有矩形到有矩形。
【FALSE情况】
这时候,lParam是指向一个矩形,这个矩形是窗口的现在位置X,我们要返回的是XC,也是就是返回X变成XC,下面给成C代码:
else
{
rc = (RECT *)lParam;
rc->left = rc->left + xFrame;
rc->top = rc->top + nTHight;
rc->right = rc->right - xFrame;
rc->bottom = rc->bottom - yFrame;
}
至此, WM_NCCALCSIZE讲解完毕。自定义高度的窗口式样(照着QQ风格画的):
nie@song.ah.cn
niesongsong
沈阳
敬上
整个函数写法:
case WM_NCCALCSIZE:
ProcNCCalcSize(hWnd,message,wParam,lParam);
int ProcNCCalcSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int xFrame = 2; /*左右边框的厚度*/
int yFrame = 2; /*下边框的厚度*/
int nTHight = 40; /*标题栏的高度*/
NCCALCSIZE_PARAMS * p;
RECT * rc;
RECT aRect;
RECT bRect;
RECT bcRect;
if(wParam == TRUE)
{
p = (NCCALCSIZE_PARAMS *)lParam; /*矩形是B A AC,目标是改成BC B A*/
CopyRect(&aRect,&p->rgrc[1]);
CopyRect(&bRect,&p->rgrc[0]);
/*指定BC的矩形的位置*/
bcRect.left = bRect.left + xFrame;
bcRect.top = bRect.top + nTHight;
bcRect.right = bRect.right - xFrame;
bcRect.bottom = bRect.bottom - yFrame;
/*各个矩形归位*/
CopyRect(&p->rgrc[0],&bcRect);
CopyRect(&p->rgrc[1],&bRect);
CopyRect(&p->rgrc[2],&aRect);
}
else
{
rc = (RECT *)lParam;
rc->left = rc->left + xFrame;
rc->top = rc->top + nTHight;
rc->right = rc->right - xFrame;
rc->bottom = rc->bottom - yFrame;
}
return GetLastError();
}
WM_NCCALCSIZE消息处理详解的更多相关文章
- Android多线程----异步消息处理机制之Handler详解
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- linux查看端口及端口详解
今天现场查看了TCP端口的占用情况,如下图 红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说E ...
- HTTP协议详解(转)
转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...
- HTTP协议详解
Author :Jeffrey 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...
- ASP.NET知识总结(3.HTTP协议详解)
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- 接口测试之HTTP协议详解
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- 【转】HTTP协议详解
原文地址:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436.html 一.概念 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则 ...
- HTTP协议详解(真的很经典)
HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展.目前在WWW中使用的是HTTP/1.0 ...
- HTTP协议详解--转载http://blog.csdn.net/gueter/article/details/1524447
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
随机推荐
- HDU 2050 折线分割平面 (递推)
题意:略. 析:多写几个就找到规律了,第1条是2,2条时是7个,3条时是16,4条时是29,.... 那么规律就出来了2 * n * n + 1 - n; 也可以递推,第n条折线的两条边都与前n-1条 ...
- C#学习笔记(十五):预处理指令
C#和C/C++一样,也支持预处理指令,下面我们来看看C#中的预处理指令. #region 代码折叠功能,配合#endregion使用,如下: 点击后如下: 条件预处理 条件预处理可以根据给出的条件决 ...
- 一个 C# 获取高精度时间类(调用API QueryP*)
如果你觉得用 DotNet 自带的 DateTime 获取的时间精度不够,解决的方法是通过调用 QueryPerformanceFrequency 和 QueryPerformanceCounter这 ...
- 怀念我的老师——丁伟岳院士 by 史宇光
在我的人生中,丁老师对我的帮助是莫大的. 我第一次见到丁老师是在91年8月份的一次南开非线性分析学术会议上(会议期间苏联发生了8.19事件),他当时报告的题目是关于二维调和映射热流短时间爆破的问 ...
- SASS优化响应式断点管理
前端开发whqet,csdn,王海庆,whqet,前端开发专家 原文:<Managing Responsive Breakpoints with Sass> 作者:Hugo Giraude ...
- 【转】larbin中的url去重算法
1.bloom filter算法 传说中,larbin使用bloom filter算法来进行url去重.那我们就先来了解下bloom filter算法好了. [以下转自:http://hi.baidu ...
- HDU 4343 D - Interval query 二分贪心
D - Interval queryTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest ...
- jsp forward 动作标签
forward 动作标签: <jsp:forward page="要转向的页面"> </jsp:forward> 或 <jsp:forward pag ...
- 图解JS原型链
一:任何一个对象都有一个prototype的属性,在js中可以把它记为:__proto__ 当初ECMAscript的发明者为了简化这门语言,同时又保持继承的属性,于是就设计了这个链表.. 在数据结构 ...
- Fedora 19安装Fcitx输入法并安装搜狗输入法资源包
系统自带的Ibus输入法非常的不好用.在Sublime Text下中文根本不能输入.于是想着换成Fcitx. 1.先卸载系统自带的Ibus输入法 sudo yum remove ibus gsetti ...