Post

将拖拽进行到底 终结篇 WindowsMessage

将拖拽进行到底 这篇文中的第四种方法,发一个消息告诉系统鼠标在 CaptionTitle(每个窗口自己 TitleBar)上,这样窗口的拖拽就可以由系统托管了。现在实现了在窗口中任意位置单击鼠标拖拽窗体。这两天,我又发现了一个东东,几乎可以完美的实现这个思想,用 SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y)) 或者用 UINT CMFCDragDlg::OnNcHitTest(CPoint point) 直接返回 HTCAPTIONSendMessage 的思想是窗口拖拽就直接由系统托管,不管鼠标点击到那里,都告诉系统,鼠标在窗体的 CaptionBar 上―发伪装的消息。用UINT CMFCDragDlg::OnNcHitTest(CPoint point) 的含义是,直接处理系统的 Message,不让系统托管了。在MFC中这两种方法的处理和实现有很多文章在介绍了,这里就不写了。这里就在C#下用类似的方法,来实现SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y))UINT CMFCDragDlg::OnNcHitTest(CPoint point)

方案 1. SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y)) Override WndProc 方法当有 WM_LBUTTONDOWN 消息时处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected override void WndProc(ref Message m)  
{  
    Point screenPoint= Control.MousePosition; 
    Point clientPoint = this.PointToClient(screenPoint); 
    if (m.Msg == UnmanagedMethods.WM_LBUTTONDOWN)  
    {  

        if(rectangleMin.Contains(clientPoint))  
        {  
            this.WindowState = FormWindowState.Minimized; 
            return;  
        }  
        if(rectangleClose.Contains(clientPoint))  
        {  
            this.Close(); 
            return;  
        }
        UnmanagedMethods.SendMessage(this.Handle, UnmanagedMethods.WM_NCLBUTTONDOWN, UnmanagedMethods.HTCAPTION, 0); 
        UnmanagedMethods.MakeLParam(screenPoint.X,clientPoint.Y); 
        return;  
    }  
    base.WndProc (ref m); 
}

UnmanagedMethods.SendMessage(this.Handle, UnmanagedMethods.WM_NCLBUTTONDOWN, UnmanagedMethods.HTCAPTION, 0); UnmanagedMethods.MakeLParam(screenPoint.X,clientPoint.Y); return; 发消息告诉系统自己在CaptionBar上。

方案 2. UINT CMFCDragDlg::OnNcHitTest(CPoint point) 自己处理消息,自己修改截获的消息,然后还给系统,告诉系统自己在CaptionBar上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected override void WndProc(ref Message m)  
{  
    Point screenPoint= Control.MousePosition; 
    Point clientPoint = this.PointToClient(screenPoint); 
    if (m.Msg == UnmanagedMethods.WM_LBUTTONDOWN)  
    {  

        if(rectangleMin.Contains(clientPoint))  
        {  
            this.WindowState = FormWindowState.Minimized; 
            return;  
        }  
        if(rectangleClose.Contains(clientPoint))  
        {  
            this.Close(); 
            return;  
        }  
        m.WParam = new IntPtr(UnmanagedMethods.HTCAPTION); 
        m.Msg = UnmanagedMethods.WM_NCLBUTTONDOWN; 
        m.LParam = UnmanagedMethods.MakeLParam(screenPoint.X,clientPoint.Y); 
    }  
    base.WndProc (ref m); 
}  

源代码(Windows 2003 Serve + VS 2003编译通过)

This post is licensed under CC BY 4.0 by the author.