簡體   English   中英

模擬拖動窗口標題欄的控件

[英]Control that simulates dragging of the window title bar

我已經構建了一個自定義控件,我想讓人們點擊並拖動我的控件,就像他們在窗口標題欄上拖動一樣。 做這個的最好方式是什么?

到目前為止,當窗口需要移動時,我沒有成功地利用鼠標按下,向上和移動事件來解密。

除了我的其他答案,您可以在控件中手動執行此操作,如下所示:

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
}

但是,如果此時有控件,我認為不會發送消息。

如果你想讓表單的一部分表現得像標題,那么SLaks提供的WM_NCHITTEST技巧就是你要走的路。 但是,如果你想讓一個子窗口能夠拖動窗體,還有另一種方法。

基本上,如果使用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.
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM