我想在我的应用程序中实现一项功能,问题是我不知道在哪里搜索,因为我不知道此功能的名称/术语。
在某些应用程序中,当您将窗体移动到屏幕的边框/角落附近时,应用程序会自动自我粘贴到该边框,直到您将窗体拖到边框处为un-adherit。
我没有任何应用示例来展示使用此功能,对不起。
有人可以解释一下这个功能的名称/术语,我可以找到一个来源来检查用于实现此功能的技术(在WinForms中)吗?
答案 0 :(得分: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年。