名称/未知功能的术语

时间:2014-09-18 20:25:18

标签: c# .net vb.net winforms forms

我想在我的应用程序中实现一项功能,问题是我不知道在哪里搜索,因为我不知道此功能的名称/术语。

在某些应用程序中,当您将窗体移动到屏幕的边框/角落附近时,应用程序会自动自我粘贴到该边框,直到您将窗体拖到边框处为un-adherit。

我没有任何应用示例来展示使用此功能,对不起。

有人可以解释一下这个功能的名称/术语,我可以找到一个来源来检查用于实现此功能的技术(在WinForms中)吗?

1 个答案:

答案 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年。