2014-09-18 57 views
0

我想在我的應用程序中實現一個功能,問題是我不知道在哪裏搜索,因爲我不知道此功能的名稱/術語。未知功能的名稱/期限

在某些應用程序中,當您將窗體移動到屏幕的邊界/角落附近時,應用程序會自動自動粘貼到該邊框,直到您將窗體拖到邊界以外爲止。

我沒有任何應用程序示例顯示使用此功能,對此感到抱歉。

有人可以解釋我是哪個名稱/這個特性的術語,在哪裏我可以找到一個來源來檢查用於實現此功能的技術(在WinForms中)?

+0

你的意思是像Windows 7呢? – OneFineDay 2014-09-18 20:30:48

+0

如果您的意思是應用程序的窗口彼此咬合,那麼有時稱爲「磁性」。 – CodeCaster 2014-09-18 20:32:30

+0

@OneFineDay謝謝,但我不確定你在說什麼,我沒有看到Windows 7 shell(瀏覽器)這樣做。 – ElektroStudios 2014-09-18 20:37:10

回答

1

該功能有時被稱爲「貼緊」,「粘滯」或「磁性」窗口,就像在WinAmp中使用的一樣。一個示例實現可以在CodeProject: A .NET Snap To Screen Form找到。

C#版本歸結爲:

[StructLayout(LayoutKind.Sequential)] 
public struct WINDOWPOS 
{ 
    public IntPtr hwnd; 
    public IntPtr hwndInsertAfter; 
    public int x; 
    public int y; 
    public int cx; 
    public int cy; 
    public int flags; 
} 

public partial class Form1 : Form 
{ 

    private const int SnapOffset = 35; 
    private const int WM_WINDOWPOSCHANGING = 70; 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == WM_WINDOWPOSCHANGING) 
     { 
      SnapToDesktopBorder(this, m.LParam, 0); 
     } 

     base.WndProc(ref m); 
    } 

    private void SnapToDesktopBorder(Form clientForm, IntPtr intPtr, int widthAdjustment) 
    { 
     var newPosition = new WINDOWPOS(); 
     newPosition = (WINDOWPOS)System.Runtime.InteropServices.Marshal.PtrToStructure(intPtr, typeof(WINDOWPOS)); 

     if (newPosition.y == 0 || newPosition.x == 0) 
     { 
      return; 
      // Nothing to do! 
     } 

     // Adjust the client size for borders and caption bar 
     Rectangle ClientRect = clientForm.RectangleToScreen(clientForm.ClientRectangle); 
     ClientRect.Width += (SystemInformation.FrameBorderSize.Width * 2) - widthAdjustment; 
     ClientRect.Height += (SystemInformation.FrameBorderSize.Height * 2) + SystemInformation.CaptionHeight; 

     // Now get the screen working area (without taskbar) 
     Rectangle WorkingRect = Screen.FromControl(clientForm).WorkingArea; 

     // Left border 
     if (newPosition.x >= WorkingRect.X - SnapOffset && newPosition.x <= WorkingRect.X + SnapOffset) 
     { 
      newPosition.x = WorkingRect.X; 
     } 

     // Get screen bounds and taskbar height 
     // (when taskbar is horizontal) 
     Rectangle ScreenRect = Screen.FromControl(clientForm).Bounds; 
     int TaskbarHeight = ScreenRect.Height - WorkingRect.Height; 

     // Top border (check if taskbar is on top 
     // or bottom via WorkingRect.Y) 
     if (newPosition.y >= -SnapOffset && (WorkingRect.Y > 0 && newPosition.y <= (TaskbarHeight + SnapOffset)) || (WorkingRect.Y <= 0 && newPosition.y <= (SnapOffset))) 
     { 
      if (TaskbarHeight > 0) 
      { 
       newPosition.y = WorkingRect.Y; 
       // Horizontal Taskbar 
      } 
      else 
      { 
       newPosition.y = 0; 
       // Vertical Taskbar 
      } 
     } 

     // Right border 
     if (newPosition.x + ClientRect.Width <= WorkingRect.Right + SnapOffset && newPosition.x + ClientRect.Width >= WorkingRect.Right - SnapOffset) 
     { 
      newPosition.x = WorkingRect.Right - (ClientRect.Width + SystemInformation.FrameBorderSize.Width); 
     } 

     // Bottom border 
     if (newPosition.y + ClientRect.Height <= WorkingRect.Bottom + SnapOffset && newPosition.y + ClientRect.Height >= WorkingRect.Bottom - SnapOffset) 
     { 
      newPosition.y = WorkingRect.Bottom - (ClientRect.Height + SystemInformation.FrameBorderSize.Height); 
     } 

     // Marshal it back 
     System.Runtime.InteropServices.Marshal.StructureToPtr(newPosition, intPtr, true); 
    } 
} 

但代碼看起來有點臃腫,我認爲它可以大大簡化。它也只適用於桌面邊界,而不適用於其他窗口。

又見Anyone familiar with a good 「sticky windows」 library for Winforms?,兩個答案鏈接到其他CodeProject上的解決方案:SnapFormExtender - a magnet for your MDI child forms(2004年)和Sticky Windows - How to make your (top-level) forms to stick one to the other or to the screen,也從2004年

+0

我注意到,當它在屏幕的右側/底部(任務欄)邊緣上貼着時,它會吃掉應用程序的右側/底部邊界(非客戶端區域)。 – ElektroStudios 2014-09-18 20:51:25

+1

不要指望我支持它,我只是報告我發現的內容。 ;)它給你一個如何完成的想法,隨時爲CodeProject提供修復或編輯這篇文章。我想,例如你需要做'SystemInformation.FrameBorderSize.Width'和'Height'兩次而不是一次。編輯:從頭開始,這完全是他正在使用的錯誤屬性,因爲它_「獲取圍繞正在拖動調整大小的窗口周圍繪製的調整邊框的大小(以像素爲單位)**」_。這不是窗口鉻大小,它是調整大小時看到的灰色邊框。此代碼已損壞。 – CodeCaster 2014-09-18 20:53:32

+1

我用'this.Width'和'this.Height'替換了邊界測量邏輯(似乎不需要),現在它按預期工作,謝謝你的時間。 – ElektroStudios 2014-09-18 21:04:37