2014-09-18 3 views
0

Я хотел бы реализовать функцию в своем приложении, проблема в том, что я не знаю, где искать, потому что я не знаю имя/термин этой функции.Имя/срок неизвестной функции

В некоторых случаях, когда вы перемещаете форму возле границы/угла экрана, приложение автоматически самопридерживается к этой границе до тех пор, пока вы не перетащите форму до границы, чтобы не наследовать.

У меня нет приложения, чтобы показать эту функцию, извините за это.

Кто-нибудь может объяснить мне, что является именем/термином этой функции и где я могу найти источник для изучения методов, используемых для реализации этой функции (в WinForms) ?.

+0

ли вы имеете в виду, как Windows 7 делает? – OneFineDay

+0

Это иногда называют «магнитным», если вы имеете в виду окна приложения, привязывающиеся друг к другу. – CodeCaster

+0

@OneFineDay Спасибо, но я не уверен, о чем вы говорите, я не видел, как Windows 7 shell (explorer) делает это. – ElektroStudios

ответ

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

+1

Не ожидайте от меня поддержки, я просто сообщаю, что нашел. ;) Это дает вам представление о том, как это можно сделать, не стесняйтесь создавать исправления в CodeProject или редактировать этот пост. Я предполагаю, что, например, вам нужно сделать 'SystemInformation.FrameBorderSize.Width' и' Height' дважды вместо одного. Изменить: поцарапать это, это полностью неправильное свойство, которое он использует, поскольку оно _ «Получает толщину в пикселях ** границы изменения размера, которая нарисована вокруг периметра окна, которое подвергается перетаскиванию **« _. Это не размер окна хром, это серая граница, которую вы видите при изменении размера. Этот код нарушен. – CodeCaster

+1

Я только что заменил эту логику измерения границ (что не обязательно) с 'this.Width' и' this.Height', теперь он работает так, как ожидалось, спасибо за ваше время. – ElektroStudios

Смежные вопросы