【问题标题】:MessageBox.Show()消息框.Show()
【发布时间】:2010-12-10 09:29:54
【问题描述】:

我想在其父窗体的中心显示我的消息框。如果我移动表单并显示消息框,它总是显示在桌面的中心。我希望它与表格一起出现。 你能给我一些技巧和建议吗?

【问题讨论】:

标签: .net winforms


【解决方案1】:

最好的方法是使用 Window Hooks 并自行将消息框居中。有一篇完美的文章展示了这种用法。

您可以在这里找到它: http://www.codeproject.com/KB/dialog/CenterDialog.aspx

您也可以在您的应用程序中使用该类,而无需深入了解它的实际工作原理。

【讨论】:

  • 文章很棒。只需在将其应用于我的应用程序之前了解它。 tnx。有更简单的方法吗?呵呵..
  • 最简单的方法是自己制作一个新的 MessageBox 表单。这将根据您的口味,看起来就像您想要的那样。此外,您可以添加任何您喜欢的功能。
【解决方案2】:

我根据我在其他地方找到的 Windows 窗体类创建了这个类。

只需将该类添加到您的 WPF 项目中,并将“this”作为参数提供给辅助方法,如下所示:

  MessageBoxHelper.PrepToCenterMessageBoxOnForm(this)" 

然后显示消息框:

MessageBox.Show("Hello there!");


/// <summary>
/// This class makes it possible to center a MessageBox over the parent dialog.
/// Usage example:
///         MessageBoxHelper.PrepToCenterMessageBoxOnForm(this);
///         MessageBox.Show("Hello there!);
/// </summary>
public static class MessageBoxHelper
{
    public static void PrepToCenterMessageBoxOnForm(Window window)
    {
        MessageBoxCenterHelper helper = new MessageBoxCenterHelper();
        helper.Prep(window);
    }

    private class MessageBoxCenterHelper
    {
        private int messageHook;
        private IntPtr parentFormHandle;

        public void Prep(Window window)
        {
            NativeMethods.CenterMessageCallBackDelegate callBackDelegate = new NativeMethods.CenterMessageCallBackDelegate(CenterMessageCallBack);
            GCHandle.Alloc(callBackDelegate);
            parentFormHandle = new WindowInteropHelper(window).Handle;
            messageHook = NativeMethods.SetWindowsHookEx(5, callBackDelegate, new IntPtr(NativeMethods.GetWindowLong(parentFormHandle, -6)), NativeMethods.GetCurrentThreadId()).ToInt32();
        }

        private int CenterMessageCallBack(int message, int wParam, int lParam)
        {
            NativeMethods.RECT formRect;
            NativeMethods.RECT messageBoxRect;
            int xPos;
            int yPos;

            if (message == 5)
            {
                NativeMethods.GetWindowRect(parentFormHandle, out formRect);
                NativeMethods.GetWindowRect(new IntPtr(wParam), out messageBoxRect);

                xPos = (int)((formRect.Left + (formRect.Right - formRect.Left) / 2) - ((messageBoxRect.Right - messageBoxRect.Left) / 2));
                yPos = (int)((formRect.Top + (formRect.Bottom - formRect.Top) / 2) - ((messageBoxRect.Bottom - messageBoxRect.Top) / 2));

                NativeMethods.SetWindowPos(wParam, 0, xPos, yPos, 0, 0, 0x1 | 0x4 | 0x10);
                NativeMethods.UnhookWindowsHookEx(messageHook);
            }

            return 0;
        }
    }

    private static class NativeMethods
    {
        internal struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        internal delegate int CenterMessageCallBackDelegate(int message, int wParam, int lParam);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool UnhookWindowsHookEx(int hhk);

        [DllImport("user32.dll", SetLastError = true)]
        internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("kernel32.dll")]
        internal static extern int GetCurrentThreadId();

        [DllImport("user32.dll", SetLastError = true)]
        internal static extern IntPtr SetWindowsHookEx(int hook, CenterMessageCallBackDelegate callback, IntPtr hMod, int dwThreadId);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetWindowPos(int hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    }
}

【讨论】:

  • 你忘了说从哪里你偷了这个代码。归因在这里很重要。谷歌搜索出现了几个可能的来源:jasoncarr.com/technology/…code.google.com/p/lioneditor/source/browse/branches/…
  • 好主意。但请注意你的用词:“偷”是一种严厉的表达方式。我明确地说“在其他地方找到了”,但你对归因是绝对正确的。
  • 不,原始代码并非来自您添加的链接。它来自 Jason Carr:jasoncarr.com/technology/…。我刚刚修改它以在 WPF 中工作。谢谢杰森。
  • 上升。没看到你添加了那个链接:-)
  • 您应该创建一个变量来存储 GCHandle.Alloc 的结果并在 UnhookWindowsHookEx 之后在回调挂钩内调用 GCHandle.Free()
【解决方案3】:

将消息框窗口的所有者设置为您的窗口(使用.Show()的第一个参数),而不是不设置所有者。

参考here

【讨论】:

  • 你能给我举个例子吗?我试过这个:IWin32Window win = this; MessageBox.Show(win,"TESTING");虽然,同样的结果。桌面中间还是会弹出消息框
  • 我想这取决于this 是什么。恐怕我的经验仅限于原生 Win32 MessageBox() 函数,这有点不同,我回答到一半才意识到你在使用 WinForms。所以我修改了我的答案以适合我在参考中找到的内容,但我可能仍然缺少一些细节。 :)
  • 将窗口句柄传递给 MessageBox 不会在父项的中心显示消息框。它只是启用与父级的最小化/最大化,并且消息框窗口没有特定的任务图标。
  • 你能给我举个例子在父中心显示消息框吗?
  • @Yogesh:有趣,也许 WinForms MessageBox 没有使用 Win32 MessageBox 函数实现。
【解决方案4】:

我以前在 C# 中做过这个。这是我记得的。

定义一个类:

public class IWindowWrapper : System.Windows.Forms.IWin32Window
{
    public IWindowWrapper(IntPtr handle)
    {
        this.Handle= handle;
    }

    public IntPtr Handle
    {
        get; 
        set;
    }
}

基于 MessageBox 定义一个类。 基于 MessageBox 创建一个类,并创建一个新的 Show 方法:

public string Show(IWin32Window owner)
{
   if(owner == null)
   {
    this.ShowDialog();
   }
   else
   {
      //parentWindow.
      this.StartPosition = FormStartPosition.CenterParent;
      this.ShowDialog(owner);
   }

}

在您的调用代码中(这里假定它是一个 winform,msgBox 基于新的消息框类)调用新的 Show 方法并在 Show 上传递一个 IWindowWrapper 实例,例如

msgBox.Show(new IWindowWrapper(this.Handle))

【讨论】:

  • 当您说“基于”时,您的意思是继承吗?我在 C# 中有点新。 :)
  • 是的,例如public class MyMessageBox : MessageBox ...等
  • 您不必使用 C# 来执行此操作,但这就是我使用的。那是您正在使用的编程语言吗?
  • 第二个密码。我要继承一个消息框吗?或者只是创建一个与 Messagebox 样式相同的表单?如果我继承消息框,this.ShowDialog() 不可用
  • @ChrisBD:您打算如何继承 MessageBox?你能举个例子吗?
【解决方案5】:

这是一个非常易于使用的解决方案,而且效果很好:

步骤:

  1. 将该类复制并粘贴到您的项目中。我未经任何修改就使用了它。
  2. 要使用修改后的 MessageBox,请在您的项目中使用这行代码:

(在 UserControlForm 内)

MessageBoxEx.Show(this, "Please fix the validation errors before saving.", "Validation Errors");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多