【问题标题】:How to prevent a dialog from leaving parent bounds?如何防止对话框离开父边界?
【发布时间】:2014-10-15 04:32:55
【问题描述】:

我有一个显示可拖动对话框的窗口,但我不希望对话框离开父窗口的边界。

using (var dialog = new MyDialog())
{
    if (dialog.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
    {
        // do something
    }
}

我怎样才能做到这一点?

【问题讨论】:

  • 不要。让用户为所欲为。
  • @TaW 是对的。你说的是“父窗口”,但你的代码没有显示育儿:dialog.MDIParent = this,或类似的东西。
  • @DonBoitnott 抱歉,我还在学习 WinForms,在使用它时感觉自己像个真正的新手。我已经在ShowDialog(this) 方法中传入this 以识别当前表单是父表单,我正在寻找是否有一种简单的方法可以将对话框限制在父表单的范围内。
  • 我的评论试图非法回应你是否想要一个奇怪的手铐,但不是那么分开的形式,或者你是否真的想要一个真正的 MDI 亲子关系。这将具有一种形式在另一种形式中的特征。
  • @DonBoitnott 我一直在寻找更像 MDI 父子关系的东西。这是为了一些小东西,所以我希望我可以做一些 hack-ish 来让它工作而不会弄乱 MDI 框架。

标签: c# .net winforms .net-3.5


【解决方案1】:

您可以尝试覆盖对话框表单的WndProc 方法并监视WM_WINDOWPOSCHANGING 系统消息的新位置和大小:

public class DialogForm : Form
{
    private struct WindowPos
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public uint flags;
    }

    public DialogForm()
    {
    }

    protected override void WndProc(ref Message m)
    {
        const int WM_WINDOWPOSCHANGING = 0x0046;
        if (m.Msg == WM_WINDOWPOSCHANGING)
        {
            WindowPos mwp = (WindowPos)Marshal.PtrToStructure(m.LParam, typeof(WindowPos));
            if (mwp.hwnd == Handle)
            {
                const int SWP_NOMOVE = 0x0002;
                const int SWP_NOSIZE = 0x0001;
                int x = mwp.x;
                int y = mwp.y;
                if (x < Owner.Left || y < Owner.Top || x + mwp.cx > Owner.Right || y + mwp.cy > Owner.Bottom)
                {
                    m.Result = IntPtr.Zero;
                    mwp.flags |= SWP_NOMOVE | SWP_NOSIZE;
                    Marshal.StructureToPtr(mwp, m.LParam, true);
                }
            }
        }
        base.WndProc(ref m);
    }
}

编辑。要更平滑,请使用此方法:

protected override void WndProc(ref Message m)
{
    const int WM_WINDOWPOSCHANGING = 0x0046;
    if (m.Msg == WM_WINDOWPOSCHANGING)
    {
        WindowPos mwp = (WindowPos)Marshal.PtrToStructure(m.LParam, typeof (WindowPos));
        if (mwp.hwnd == Handle)
        {
            int x = mwp.x;
            int y = mwp.y;
            if (x < Owner.Left || y < Owner.Top || x + mwp.cx > Owner.Right || y + mwp.cy > Owner.Bottom)
            {
                bool resizing = mwp.cx != Width || mwp.cy != Height;
                if (resizing)
                {
                    if (x < Owner.Left)
                    {
                        mwp.x = x = Owner.Left;
                        mwp.cx = Width;
                    }
                    if (y < Owner.Top)
                    {
                        mwp.y = y = Owner.Top;
                        mwp.cy = Height;
                    }

                    if (mwp.cx > Owner.Right - x)
                        mwp.cx = Owner.Right - x;
                    if (mwp.cy > Owner.Bottom - y)
                        mwp.cy = Owner.Bottom - y;
                }
                else
                {
                    if (x < Owner.Left)
                        mwp.x = Owner.Left;
                    else if (x > Owner.Right - mwp.cx)
                        mwp.x = Owner.Right - mwp.cx;

                    if (y < Owner.Top)
                        mwp.y = Owner.Top;
                    else if (y > Owner.Bottom - mwp.cy)
                        mwp.y = Owner.Bottom - mwp.cy;
                }
                m.Result = IntPtr.Zero;
                Marshal.StructureToPtr(mwp, m.LParam, true);
            }
        }
    }
    base.WndProc(ref m);
}

【讨论】:

  • 它不是很流畅,但它确实有效。我会看看我能做些什么来修改代码,让它运行得更流畅一些,否则我会尝试另一种方法来完成这项任务。谢谢。
  • 如果我正确理解在这种情况下什么是平滑度,则添加了一种更平滑的方法。
  • 谢谢 Dmitry :) 我今天在远程工作,显然远程连接处理窗口拖动的方式有所不同,我下周全部休息,但我回来后会试一试。根据我目前看到的情况,我看不出它有什么不起作用的原因。
猜你喜欢
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
  • 2012-06-08
  • 2018-10-26
相关资源
最近更新 更多