6

カスタム コントロールを作成しました。ウィンドウのタイトル バーをドラッグしているかのように、コントロールをクリックしてドラッグできるようにしたいと考えています。これを行う最善の方法は何ですか?

これまでのところ、マウスのダウン、アップ、および移動イベントを利用して、ウィンドウを移動する必要があるタイミングを解読することに成功していません。

4

3 に答える 3

11

私の他の答えに加えて、次のようにコントロールで手動でこれを行うことができます:

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;
    }
}

編集: テストおよび修正済み - これは実際に機能するようになりました。

于 2010-03-05T03:50:32.573 に答える
5

これを行う最も効果的な方法は、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
}

ただし、その時点でコントロールがあればメッセージは送信されないと思います。

于 2010-03-05T03:33:03.440 に答える
3

フォームの一部をキャプションのように動作させたい場合は、WM_NCHITTESTSLaks が提供したトリックが最適です。しかし、子ウィンドウでフォームをドラッグできるようにしたい場合は、別の方法があります。

基本的に、WM_SYSCOMMAND メッセージを MOUSE_MOVE コマンド ID で DefWindowProc に送信すると、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.
  }
于 2010-03-05T04:48:15.040 に答える