0

ボタンのクリックから(タイトルバーを使用して)フォームを移動しようとしています。

SendMessage を使用すると、これは簡単だと思いました。

Const WM_LBUTTONDOWN As Integer = &H201

Button1.Capture = False
Cursor.Position = Me.Location + New Size(50, 8)

SendMessage(Me.Handle, WM_LBUTTONDOWN, CType(1, IntPtr), IntPtr.Zero)

ただし、カーソルがフォーム クライアント領域にある場合はメッセージが送信されますが、フォームのタイトルバーには送信されないようです (カーソルがクライアント領域ではなくタイトルバーにあるにもかかわらず、フォームは何らかの形でイベントをキャプチャします)。

ボタンのmousedownイベントとクリックイベントの両方で上記のコードを試し、カーソルを移動してからbutton1を押しました。

助言がありますか?

4

3 に答える 3

3

あなたが必要です(そしてとして渡します)。ただし、これがあなたがやろうとしていることを達成できるかどうかはまだ完全にはわかりません。WM_NCLBUTTONDOWNHTCAPTIONwParam

通常、タイトル バー以外の場所をクリックしたときにユーザーがフォームを移動できるようにする方法は、メッセージを処理し、カーソルが移動を開始する領域の上にあるときにWM_NCHITTEST戻ることです。HTCAPTIONただし、この領域が子コントロールで占有されている場合は、子コントロールWM_NCHITTESTからも処理して返す必要がありHTTRANSPARENTます。


ちなみに、これを達成するためのより簡単な方法は、Mehrdad Afshariが提案したように、フォームのLocationプロパティを設定することです。あなたは彼に「マウスの動きに合わせて移動する必要がある」とコメントしましたが、それはまさにあなたができることであり、すべきことです。

class MyForm : Form{
    Point downAt;

    MyForm(){
        Label lbl      = new Label();
        lbl.AutoSize   = true;
        lbl.BackColor  = Color.Blue;
        lbl.ForeColor  = Color.White;
        lbl.Location   = new Point(50, 50);
        lbl.Text       = "Drag me to move this form.";
        lbl.Parent     = this;
        lbl.MouseDown += (s, e)=>downAt = e.Location;
        lbl.MouseMove += (s, e)=>{if(lbl.Capture) Location += (Size)e.Location - (Size)downAt;};
    }
}

このアプローチの問題は、最上位ウィンドウを移動するための Windows のコードをバイパスすることです。つまり、ユーザーが [画面のプロパティ] ダイアログで [ドラッグ中にウィンドウの内容を表示する] オプションを選択していない場合、その設定は事実上無視されます (ドラッグ アウトラインは表示されません)。私が考えていない他の欠点があるかもしれません。

ただし、全体として、これはこれを達成するためのシンプルで簡単な方法であり、プラットフォームの呼び出しに依存しない完全な .NET ソリューションです (したがって、Unix 上の Mono に移植できるはずです)。


おっとっと。C# のサンプル コードを提供したことに気付きましたが、あなたのコードは VB.NET のようです。私はあなたが必要とするものは次のようになると思います:

Sub New()
    Dim lbl As New Label
    lbl.AutoSize  = True
    lbl.BackColor = Color.Blue
    lbl.ForeColor = Color.White
    lbl.Location  = New Point(50, 50)
    lbl.Text      = "Drag me to move this form."
    lbl.Parent    = Me
    AddHandler lbl.MouseDown, Function(ByVal s As Object, ByVal e As MouseEventArgs)
        Me.downAt = e.Location
    End Function
    AddHandler lbl.MouseMove, Function(ByVal s As Object, ByVal e As MouseEventArgs)
        If lbl.Capture Then
            Me.Location = Me.Location + DirectCast(e.Location, Size) - DirectCast(Me.downAt, Size)
        End If
    End Function
End Sub

これは、VB.NET でこれを表現する最も簡潔な方法ではない場合があります。Reflectorを使用して翻訳しました。

于 2009-01-11T19:56:38.360 に答える
2

Mehrdadは正しいです、これをする必要はありません。マウスがキャプチャされるので、あまり速く動かすことはできません。サンプルコード:

Point mLastPos;
private void button1_MouseMove(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    this.Location = new Point(this.Location.X + e.X - mLastPos.X,
      this.Location.Y + e.Y - mLastPos.Y);
  }
  // NOTE: else is intentional!
  else mLastPos = e.Location;
}
于 2009-01-11T20:13:30.637 に答える
2

メッセージのLParam値は、クライアント座標wm_LButtonDownでのマウス位置を受け取ります。タイトル バーは非クライアント領域にあるため、メッセージを使用します。以前にこの質問に対する回答としてメッセージが表示されたのを見たことがありますが、動作すると予想されるより直接的なルートがあります。ウィンドウにメッセージを送信し、フラグを指定します。wm_NCLButtonDownwm_SysCommandsc_Move

于 2009-01-11T20:01:52.860 に答える