2016-07-14 46 views
1

我有一個Windows窗體,我的任務是向窗體添加拖動功能。 「VendorMasterList」是一個標籤。我添加了鼠標移動,鼠標移動和鼠標移動到該標籤的事件。窗體的拖動將窗體向下移動

enter image description here

如果我試圖拖動,形式向下移動,然後只能拖我想要的方式。我的問題是爲什麼它會下降?這是我的代碼

private Point startPoint = new Point(0, 0); 
    private bool isDragging = false; 

    private void lblHeader_MouseDown(object sender, MouseEventArgs e) 
    { 
     isDragging = true; // _dragging is your variable flag 
     startPoint = new Point(e.X, e.Y); 
    } 
    private void lblHeader_MouseUp(object sender, MouseEventArgs e) 
    { 
     isDragging = false; 
    } 
    private void lblHeader_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (isDragging) 
      { 
       Point p = PointToScreen(e.Location); 
       this.Location = new Point(p.X - this.startPoint.X, p.Y - this.startPoint.Y); 
      } 
    } 

有什麼辦法解決這個問題嗎?

新增圖像

enter image description here

+0

是你要移動頭部或形式..爲「this.location」移動形式...... – BugFinder

+0

你真的認爲這樣使用自定義鑲邊是個好主意?將窗口保持原樣並讓*用戶選擇它將如何顯示會出現什麼問題?如果你堅持,看看非客戶區在Windows中是如何工作的 - 很容易以任何你想要的方式重新繪製非客戶區,擴展它,或者甚至假裝窗口客戶區的一部分實際上是一個與客戶端對應的非客戶端區域(並讓Windows爲您做出拖動)。 – Luaan

+0

如果鼠標移過標籤並點擊。表單的位置發生了變化。 – user2115618

回答

0

我的天堂」想你的代碼,但我所看到的只是部分正確:-)

您保存初始座標,這是相對於點擊左上角的控件,但您需要保存屏幕座標

然後,鼠標移動,並再次得到相對於該角落的一個點。你錯過了一些相關的事情:

  1. 你需要計算基礎上,屏幕座標的兩個點之間的增量,下方的光標爲您提供了錯誤的值,否則移動窗口。
  2. 您需要此增量添加到窗體的當前位置
  3. 您需要保存新的鼠標位置來計算正確

基於屏幕座標當前鼠標的位置可以得到下一個增量通過Cursor.Position

所以,你的代碼應該閱讀:

private void lblHeader_MouseDown(object sender, MouseEventArgs e) 
{ 
    isDragging = true; // _dragging is your variable flag 
    startPoint = Cursor.Position; 
} 

private void lblHeader_MouseUp(object sender, MouseEventArgs e) 
{ 
    isDragging = false; 
} 

private void lblHeader_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (isDragging) 
    { 
     Point p = Cursor.Position; 
     int deltaX = p.X - startPoint.X; 
     int deltaY = p.Y - startPoint.Y; 
     startPoint = p; 

     this.Left += deltaX; 
     this.Top += deltaY; 
    } 
} 

我剛纔放置在窗體上面板和implented以上,其工作。當他說,這種做法其實是不太好,因爲它沒有考慮到的Windows實際上可以處理這一切都爲您


@IInspector是正確的。

的另一種方法(和最好的一個)我會帶是:

  1. 覆蓋所述WndProc方法如下所示
  2. 完成。沒有更多的鼠標處理

以下是你如何能重寫的WndProc做你所需要的一個例子:

protected override void WndProc(ref Message m) 
{ 
    const UInt32 WM_NCHITTEST = 0x0084; 
    const UInt32 HTCAPTION = 0x2; 

    bool handled = false; 
    if (m.Msg == WM_NCHITTEST) 
    { 
     if (<cursor is within the caption area>) 
     { 
      m.Result = (IntPtr)HTCAPTION; 
      handled = true; 
     } 
    } 

    if (!handled) 
     base.WndProc(ref m); 
} 

要限制該窗口可以移動到的區域,你可以使用以下內容。當然,@IInspectable會不同意,但你去這條道路:-)

private void lblHeader_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (isDragging) 
    { 
     Point p = Cursor.Position; 
     int deltaX = p.X - startPoint.X; 
     int deltaY = p.Y - startPoint.Y; 
     startPoint = p; 

     int fX = this.Left + deltaX; 
     int fY = this.Top + deltaY; 

     if (fX >= 0 && fX + this.Width < Area.Width) this.Left = fX; 
     if (fY >= 0 && f> + this.Height < Area.Height) this.Top = fY; 
    } 
} 
+1

請不要。它開始是錯誤的,我甚至在看到更新版本之前不得不downvote。 Windows已經爲你做了一切,除了正確處理[WM_NCHITTEST](https://msdn.microsoft.com/en-us/library/windows/desktop/ms645618.aspx)之外,你的程序確實沒有什麼需要做的,信息。只需返回相應區域的「HTCAPTION」,並完成它。其他一切都很簡單(包括移動表格)。 – IInspectable

+1

@IInspectable那麼,那不是我的錯。 OP已經有了這個代碼,OP想知道他的代碼爲什麼不起作用,我給出了一個正確的答案。你可能不會對此感到滿意,但這真的不是我的問題或我的答案的問題。當然,我知道WM_NCHITTEST,但那不是OP的方式。否則,我的答案是完全正確的,因爲它的工作原理與OP所要求的一致。你所說的都是正確的,但我沒有看到一個downvote的理由。隨意寫出你自己的答案,概述你的方法。 –

+0

@IInspectable我把你的方法作爲我的答案的替代方案。 –