【问题标题】:C# Form Control MoveC# 窗体控件移动
【发布时间】:2009-06-28 14:08:09
【问题描述】:

是否可以控制表单的移动位置?

所以如果我移动一个表单,它只能在垂直轴上移动,当我尝试水平移动它时,什么也没有发生。

我不想要一个错误的实现,比如 locationchanged 或 move 事件并将其弹出回内联。我没有办法使用 WndProc 覆盖之类的东西,但搜索了一段时间后,我找不到任何东西。请帮忙

【问题讨论】:

    标签: c# user-interface move wndproc


    【解决方案1】:

    例如:

    using System.Runtime.InteropServices;
    
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x216)  // WM_MOVING = 0x216
        {
            Rectangle rect = 
               (Rectangle) Marshal.PtrToStructure(m.LParam, typeof (Rectangle));
            if (rect.Left < 100)
            {
                // compensates for right side drift
                rect.Width = rect.Width + (100 - rect.Left);
                // force left side to 100
                rect.X = 100;
                Marshal.StructureToPtr(rect, m.LParam, true);
            }
        }
        base.WndProc(ref m);
    }
    

    上面的代码设置了最小左手位置 100。

    无需像 driis 那样重新创建 RECT 结构,.NET 原生 Rectangle 可以正常工作。但是,您必须通过 X 属性设置位置,因为 Left 是一个仅限获取的属性。

    【讨论】:

    • 您还必须处理其他消息,因为第一次创建窗口时不会调用 WM_MOVING。您需要在创建时明确设置窗口位置,或者您需要确保在创建时它在您想要的范围内。
    【解决方案2】:

    您很可能希望覆盖 WndProc 并处理 WM_MOVING 消息。 According to MSDN:

    WM_MOVING 消息被发送到 用户正在移动的窗口。经过 处理此消息,一个 应用程序可以监控位置 拖动矩形,如果需要, 改变它的位置。

    这是一种方法,但是,您显然需要根据需要调整它:

    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace VerticalMovingForm
    {
        public partial class Form1 : Form
        {
            private const int WM_MOVING = 0x0216;
            private readonly int positionX;
            private readonly int positionR;
    
            public Form1()
            {
                Left = 400;
                Width = 500;                            
                positionX = Left;
                positionR = Left + Width;
            }
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_MOVING)
                {
                    var r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
                    r.Left = positionX;
                    r.Right = positionR;
                    Marshal.StructureToPtr(r, m.LParam, false);
                }
                base.WndProc(ref m);                
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      VB.NET 版本:

      Protected Overloads Overrides Sub WndProc(ByRef m As Message)
          If m.Msg = &H216 Then
              ' WM_MOVING = 0x216
              Dim rect As Rectangle = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(Rectangle)), Rectangle)
              If rect.Left < 100 Then
                  ' compensates for right side drift
                  rect.Width = rect.Width + (100 - rect.Left)
                  ' force left side to 100
                  rect.X = 100
                  Marshal.StructureToPtr(rect, m.LParam, True)
              End If
          End If
          MyBase.WndProc(m)
      End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-02
        • 2017-03-13
        • 2013-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多