有的时候,我们需要自绘窗口的标题,或者隐藏了窗口标题,那么问题来了,这就是怎么拖动无标题的窗口?
这个问题的本质便是怎么在窗口的客户区上,拖动鼠标,并且移动窗口。
通常状态下,一个窗口只有在标题栏的区域,才会响应鼠标拖动的消息。而在窗口的客户区并不会响应。
这样便有了一个方法,就是我们可以欺骗windows,让它误认为鼠标点击窗口客户区时是点击在了标题栏上。
有这么个消息,就是WM_NCHITTEST。
MSDN对它的解释是:
The WM_NCHITTEST message is sent to a window when the cursor moves, or when a mouse button is pressed or released. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.
这个消息是当鼠标移动或者有鼠标键按下时候发出的。
如果WM_NCHITTEST的消息响应函数的返回值是HTCLIENT,表示鼠标点击的是客户区,则Windows会向窗口发送WM_LBUTTONDOWN消息;如果WM_NCHITTEST的消息响应函数的返回值不是HTCLIENT(可能是HTCAPTION、HTCLOSE、HTMAXBUTTON等),即鼠标点击的是非客户区,Windows就会向窗口发送WM_NCLBUTTONDOWN消息。
这个介绍对这个没有什么大关系,但是可以帮助你理解。
接下来便是实现的具体方法,这个方法分为两步:
1.在MESSAGE_MAP中添加ON_WM_NCHITTEST()
2.手动添加响应函数UINT OnNcHitTest(CPoint point)
其中应这么处理:
UINT CYourClass::OnNcHitTest(CPoint point)
{
UINT nh=CDialog::OnNcHitTest(point);
return ((nh==HTCLIENT)?HTCAPTION:nh);
}
第二个办法很简单了,就是处理鼠标左击消息:
首先添加鼠标左键单击消息,用自动添加便可。
void CYourClass::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SendMessage(WM_SYSCOMMAND,0xF012,0);
CDialog::OnLButtonDown(nFlags, point);
}
需要注意的是SendMessage(WM_SYSCOMMAND,0xF012,0);
这跟第一个方法的效果相差不大,发送的消息说明的是发送SC_MOVE + HTCAPTION,所以这里简写成为0xF012。
第二个方法要比第一种更加简单,容易使用。