当前位置:  开发笔记 > 编程语言 > 正文

如何使我的Windows窗体应用程序捕捉到屏幕边缘?

如何解决《如何使我的Windows窗体应用程序捕捉到屏幕边缘?》经验,为你挑选了2个好方法。

那里的任何人都知道如何使你的.net窗口形成应用程序像Winamp一样粘性/敏捷,所以它会捕捉到屏幕的边缘?

目标框架是使用VS08用C#编写的.NET 2.0 Windows Form.我希望将此功能添加到自定义用户控件,但我想更多的人将从为应用程序及其主要表单描述它将受益.

谢谢.



1> Hans Passant..:

这工作得很好,适用于多个监视器,观察任务栏:

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }
    private const int SnapDist = 100;
    private bool DoSnap(int pos, int edge) {
      int delta = pos - edge;
      return delta > 0 && delta <= SnapDist;
    }
    protected override void  OnResizeEnd(EventArgs e) {
      base.OnResizeEnd(e);
      Screen scn = Screen.FromPoint(this.Location);
      if (DoSnap(this.Left, scn.WorkingArea.Left)) this.Left= scn.WorkingArea.Left;
      if (DoSnap(this.Top, scn.WorkingArea.Top)) this.Top = scn.WorkingArea.Top;
      if (DoSnap(scn.WorkingArea.Right, this.Right)) this.Left = scn.WorkingArea.Right - this.Width;
      if (DoSnap(scn.WorkingArea.Bottom, this.Bottom)) this.Top = scn.WorkingArea.Bottom - this.Height;
    }
  }


这是否也会改变屏幕工作区域,从而减少桌面上的最大可用空间(即最大化的窗口不会在顶部)?

2> Andrew Sun..:

接受的答案仅在完成拖动后捕捉窗口,而我希望表单在拖动时连续捕捉到屏幕边缘.这是我的解决方案,松散地基于Paint.NET源代码:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Whatever
{
    /// 
    /// Managed equivalent of the Win32 RECT structure.
    /// 
    [StructLayout(LayoutKind.Sequential)]
    public struct LtrbRectangle
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public LtrbRectangle(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }

        public Rectangle ToRectangle()
        {
            return Rectangle.FromLTRB(Left, Top, Right, Bottom);
        }

        public static LtrbRectangle FromRectangle(Rectangle rect)
        {
            return new LtrbRectangle(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
        }

        public override string ToString()
        {
            return "{Left=" + Left + ",Top=" + Top + ",Right=" + Right + ",Bottom=" + Bottom + "}";
        }
    }

    /// 
    /// A form that "snaps" to screen edges when moving.
    /// 
    public class AnchoredForm : Form
    {
        private const int WmEnterSizeMove = 0x0231;
        private const int WmMoving = 0x0216;
        private const int WmSize = 0x0005;

        private SnapLocation _snapAnchor;
        private int _dragOffsetX;
        private int _dragOffsetY;

        /// 
        /// Flags specifying which edges to anchor the form at.
        /// 
        [Flags]
        public enum SnapLocation
        {
            None = 0,
            Left = 1 << 0,
            Top = 1 << 1,
            Right = 1 << 2,
            Bottom = 1 << 3,
            All = Left | Top | Right | Bottom
        }

        /// 
        /// How far from the screen edge to anchor the form.
        /// 
        [Browsable(true)]
        [DefaultValue(10)]
        [Description("The distance from the screen edge to anchor the form.")]
        public virtual int AnchorDistance { get; set; } = 10;

        /// 
        /// Gets or sets how close the form must be to the
        /// anchor point to snap to it. A higher value gives
        /// a more noticable "snap" effect.
        /// 
        [Browsable(true)]
        [DefaultValue(20)]
        [Description("The maximum form snapping distance.")]
        public virtual int SnapDistance { get; set; } = 20;

        /// 
        /// Re-snaps the control to its current anchor points.
        /// This can be useful for re-positioning the form after
        /// the screen resolution changes.
        /// 
        public void ReSnap()
        {
            SnapTo(_snapAnchor);
        }

        /// 
        /// Forces the control to snap to the specified edges.
        /// 
        /// The screen edges to snap to.
        public void SnapTo(SnapLocation anchor)
        {
            Screen currentScreen = Screen.FromPoint(Location);
            Rectangle workingArea = currentScreen.WorkingArea;
            if ((anchor & SnapLocation.Left) != 0)
            {
                Left = workingArea.Left + AnchorDistance;
            }
            else if ((anchor & SnapLocation.Right) != 0)
            {
                Left = workingArea.Right - AnchorDistance - Width;
            }
            if ((anchor & SnapLocation.Top) != 0)
            {
                Top = workingArea.Top + AnchorDistance;
            }
            else if ((anchor & SnapLocation.Bottom) != 0)
            {
                Top = workingArea.Bottom - AnchorDistance - Height;
            }
            _snapAnchor = anchor;
        }

        private bool InSnapRange(int a, int b)
        {
            return Math.Abs(a - b) < SnapDistance;
        }

        private SnapLocation FindSnap(ref Rectangle effectiveBounds)
        {
            Screen currentScreen = Screen.FromPoint(effectiveBounds.Location);
            Rectangle workingArea = currentScreen.WorkingArea;
            SnapLocation anchor = SnapLocation.None;
            if (InSnapRange(effectiveBounds.Left, workingArea.Left + AnchorDistance))
            {
                effectiveBounds.X = workingArea.Left + AnchorDistance;
                anchor |= SnapLocation.Left;
            }
            else if (InSnapRange(effectiveBounds.Right, workingArea.Right - AnchorDistance))
            {
                effectiveBounds.X = workingArea.Right - AnchorDistance - effectiveBounds.Width;
                anchor |= SnapLocation.Right;
            }
            if (InSnapRange(effectiveBounds.Top, workingArea.Top + AnchorDistance))
            {
                effectiveBounds.Y = workingArea.Top + AnchorDistance;
                anchor |= SnapLocation.Top;
            }
            else if (InSnapRange(effectiveBounds.Bottom, workingArea.Bottom - AnchorDistance))
            {
                effectiveBounds.Y = workingArea.Bottom - AnchorDistance - effectiveBounds.Height;
                anchor |= SnapLocation.Bottom;
            }
            return anchor;
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WmEnterSizeMove:
                case WmSize:
                    // Need to handle window size changed as well when
                    // un-maximizing the form by dragging the title bar.
                    _dragOffsetX = Cursor.Position.X - Left;
                    _dragOffsetY = Cursor.Position.Y - Top;
                    break;
                case WmMoving:
                    LtrbRectangle boundsLtrb = Marshal.PtrToStructure(m.LParam);
                    Rectangle bounds = boundsLtrb.ToRectangle();
                    // This is where the window _would_ be located if snapping
                    // had not occurred. This prevents the cursor from sliding
                    // off the title bar if the snap distance is too large.
                    Rectangle effectiveBounds = new Rectangle(
                        Cursor.Position.X - _dragOffsetX,
                        Cursor.Position.Y - _dragOffsetY,
                        bounds.Width,
                        bounds.Height);
                    _snapAnchor = FindSnap(ref effectiveBounds);
                    LtrbRectangle newLtrb = LtrbRectangle.FromRectangle(effectiveBounds);
                    Marshal.StructureToPtr(newLtrb, m.LParam, false);
                    m.Result = new IntPtr(1);
                    break;
            }
            base.WndProc(ref m);
        }
    }
}

这是它的样子:

截图

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有