2009-01-11 61 views
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。

有什麼建議嗎?

回答

3

您需要WM_NCLBUTTONDOWN(並通過HTCAPTION作爲wParam)。不過,我仍然不完全確定這會實現你想要做的事情。

通常,當單擊標題欄以外的其他位置時,允許用戶移動表單的方法是在光標位於要啓動移動的區域上時處理WM_NCHITTEST消息並返回HTCAPTION。但是,如果此區域被兒童控制器佔用,則您還必須從子控制器處理WM_NCHITTEST,並返回HTTRANSPARENT


順便說一句,一個更簡單,如果略少正確的路來完成,這是做的邁赫達德Afshari suggested,只是設置窗體的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來幫我翻譯它。

+0

不要擔心,我把這個問題標記爲c#和vb.net,因爲我不介意答案:) – Pondidum 2009-01-11 20:44:07

2

LParam值爲wm_LButtonDown消息接收鼠標位置客戶端座標。標題欄位於非客戶區域,因此請使用wm_NCLButtonDown message。我已經看到過這個信息,作爲這個問題的答案,但是我有一條更直接的路線,我希望能夠發揮作用:發送一個wm_SysCommand message到窗口,並指定sc_Move標誌。

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; 
} 
相關問題