很多时候,为了界面的美观,我们会隐藏标题栏,而在客户区通过自绘模拟标题栏。但是这样处理,会导致窗体无法移动。下面提供几种移动方法:

    1、采用欺骗的方式。即当鼠标点击客户区的时候,我们欺骗windows,让windows认为我们点击在了标题栏,这样,拖动过程就通过windows进行处理了。因此可以大大减少我们的代码量。具体方法如下:

响应鼠标左键按下消息WM_LBUTTONDOWN,相应函数中,直接发送欺骗消息:

PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));

    WM_NCLBUTTONDOWN即左键在非客户区按下,HTCAPTION即标题栏,所以采用这种方式,就可以实现无标题栏对话框的移动问题了。

    那么问题来了。。。

    采用这种操作后,会导致我们的对话框无法响应WM_LBUTTONUP消息,同时在我编写程序过程中发现WM_NCLBUTTONUP也一般不能响应。当然,可以通过注册WM_MOUSEHOVER以及WM_MOUSELEAVE消息,响应这两个消息去处理相应的代码,或者采用下钩子的方法,在钩子中正确发送消息,不过不推荐这种方法,实现也比较麻烦。

    所以下面提供第二种方法。

    2、在WM_MOUSEMOVE消息中,自己处理窗口移动。具体就是先判断鼠标左键是否处于按下,如果是的话,就获取鼠标移动到的位置,然后将窗口进行移动就可以了。具体实现如下:

void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)  
{  
    static CPoint PrePoint = CPoint(0, 0);  
    if(MK_LBUTTON == nFlags)  
    {  
         if(point != PrePoint)  
         {  
              CPoint ptTemp = point - PrePoint;  
              CRect rcWindow;  
              GetWindowRect(&rcWindow);  
              rcWindow.OffsetRect(ptTemp.x, ptTemp.y);  
              MoveWindow(&rcWindow);  
              return ;  
         }  
     }  
    PrePoint = point;  
    CDialog::OnMouseMove(nFlags, point); 
}

    通过上面的消息,就能够进行窗口移动了。然而,如果仅仅响应上面的消息发现两个问题:第一,当鼠标按住左键快速移动的时候,鼠标会移出窗口,窗口不动了,拖动效果不好;第二,左键释放消息在上面这种情况下没有响应。解决方法如下:

    首先左键按下消息中设置鼠标捕获

SetCapture();

    在左键释放消息中释放鼠标捕获

RealeseCapture();

    通过上面的处理,就可以完美拖动,同时,左键抬起的消息也不会受影响。


    因此,第一种方法较为简洁,适合不需要响应鼠标其它消息的情况;第二种方法相对麻烦一些,不过实现效果也很好,并且不影响其他消息。