我已經構建了一個自定義控件,並且希望允許用戶單擊並拖動我的控件,就好像它們在窗口標題欄上拖動一樣。做這個的最好方式是什麼?模擬拖動窗口標題欄的控件
到目前爲止,我一直在利用鼠標按下,向上和移動事件來解密窗口需要移動時失敗。
我已經構建了一個自定義控件,並且希望允許用戶單擊並拖動我的控件,就好像它們在窗口標題欄上拖動一樣。做這個的最好方式是什麼?模擬拖動窗口標題欄的控件
到目前爲止,我一直在利用鼠標按下,向上和移動事件來解密窗口需要移動時失敗。
除了我其他的回答,您可以手動在這樣的控制做到這一點:
Point dragOffset;
protected override void OnMouseDown(MouseEventArgs e) {
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left) {
dragOffset = this.PointToScreen(e.Location);
var formLocation = FindForm().Location;
dragOffset.X -= formLocation.X;
dragOffset.Y -= formLocation.Y;
}
}
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left) {
Point newLocation = this.PointToScreen(e.Location);
newLocation.X -= dragOffset.X;
newLocation.Y -= dragOffset.Y;
FindForm().Location = newLocation;
}
}
編輯:測試和固定 - 這就是現在的實際工作。
最有效的方法是處理WM_NCHITTEST
通知。
覆蓋形式的WndProc
方法並添加以下代碼:
if (m.Msg == 0x0084) { //WM_NCHITTEST
var point = new Point((int)m.LParam);
if(someRect.Contains(PointToClient(point))
m.Result = new IntPtr(2); //HT_CAPTION
}
不過,我不認爲如果在該點的控制信息將被髮送。
我很好奇......你能詳細說明嗎?這究竟是怎麼做的? – echo 2010-03-05 03:35:33
@echo:它告訴Windows窗體的那一部分是標題欄,可以拖動它。請注意,這也將允許通過雙擊該部分來最大化表單。 – SLaks 2010-03-05 03:37:48
哈,整潔的把戲,我從來沒有見過這個。花了我一分鐘來弄清楚這裏發生了什麼事! – Aaronaught 2010-03-05 03:39:06
如果你想讓表格的一部分表現得像標題一樣,SLaks給出的訣竅就是要走的路。但是,如果你想讓孩子窗口能夠拖動窗體,並且有另一種方式。
基本上,如果您使用MOUSE_MOVE命令ID向DefWindowProc發送WM_SYSCOMMAND消息,則Windows將進入拖動模式。這基本上是如何標題做到這一點,但通過削減中間人,我們可以從一個子窗口啓動這個拖動,並且我們不會獲得所有其他標題行爲。
public class form1 : Form
{
...
[DllImport("user32.dll")]
static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool ReleaseCapture(IntPtr hwnd);
const uint WM_SYSCOMMAND = 0x112;
const uint MOUSE_MOVE = 0xF012;
public void DragMe()
{
DefWindowProc(this.Handle, WM_SYSCOMMAND, (UIntPtr)MOUSE_MOVE, IntPtr.Zero);
}
private void button1_MouseDown(object sender, MouseEventArgs e)
{
Control ctl = sender as Control;
// when we get a buttondown message from a button control
// the button has capture, we need to release capture so
// or DragMe() won't work.
ReleaseCapture(ctl.Handle);
this.DragMe(); // put the form into mousedrag mode.
}
這對我有效,但我必須更改ReleaseCapture以使其沒有參數。請參閱[ReleaseCapture](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646261(v = vs.85).aspx) – Erroneous 2016-07-08 19:13:26
感謝您的代碼! – 2012-04-01 20:56:15