Winforms - 如何让MessageBox以MainForm为中心?

时间:2010-04-04 22:44:52

标签: winforms messagebox

Winforms - 如何使对话框显示在MainForm的中心?这与基于普通窗口默认值相反,后者将它们呈现在屏幕的中心。

在我的情况下,我有一个小的主要表单,例如可能位于一个角落,MessageBox弹出窗口显示似乎有一些方法。

5 个答案:

答案 0 :(得分:58)

可能有一些P / Invoke服务和Control.BeginInvoke()提供的魔力。在项目中添加一个新类并粘贴此代码:

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

class CenterWinDialog : IDisposable {
    private int mTries = 0;
    private Form mOwner;

    public CenterWinDialog(Form owner) {
        mOwner = owner;
        owner.BeginInvoke(new MethodInvoker(findDialog));
    }

    private void findDialog() {
        // Enumerate windows to find the message box
        if (mTries < 0) return;
        EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
        if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero)) {
            if (++mTries < 10) mOwner.BeginInvoke(new MethodInvoker(findDialog));
        }
    }
    private bool checkWindow(IntPtr hWnd, IntPtr lp) {
        // Checks if <hWnd> is a dialog
        StringBuilder sb = new StringBuilder(260);
        GetClassName(hWnd, sb, sb.Capacity);
        if (sb.ToString() != "#32770") return true;
        // Got it
        Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size);
        RECT dlgRect;
        GetWindowRect(hWnd, out dlgRect);
        MoveWindow(hWnd,
            frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) / 2,
            frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) / 2,
            dlgRect.Right - dlgRect.Left,
            dlgRect.Bottom - dlgRect.Top, true);
        return false;
    }
    public void Dispose() {
        mTries = -1;
    }

    // P/Invoke declarations
    private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
    [DllImport("user32.dll")]
    private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
    [DllImport("kernel32.dll")]
    private static extern int GetCurrentThreadId();
    [DllImport("user32.dll")]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
    [DllImport("user32.dll")]
    private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
    private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}

样本用法:

    private void button1_Click(object sender, EventArgs e) {
        using (new CenterWinDialog(this)) {
            MessageBox.Show("Nobugz waz here");
        }
    }

请注意,此代码适用于任何Windows对话框。 MessageBox,OpenFormDialog,FolderBrowserDialog,PrintDialog,ColorDialog,FontDialog,PageSetupDialog,SaveFileDialog。

答案 1 :(得分:2)

这是针对Win32 API,用C语言编写的。根据需要翻译它......

case WM_NOTIFY:{
  HWND X=FindWindow("#32770",NULL);
  if(GetParent(X)==H_frame){int Px,Py,Sx,Sy; RECT R1,R2;
    GetWindowRect(hwnd,&R1); GetWindowRect(X,&R2);
    Sx=R2.right-R2.left,Px=R1.left+(R1.right-R1.left)/2-Sx/2;
    Sy=R2.bottom-R2.top,Py=R1.top+(R1.bottom-R1.top)/2-Sy/2;
    MoveWindow(X,Px,Py,Sx,Sy,1);
  }
} break;

将其添加到WndProc代码中...您可以根据需要设置位置,在这种情况下,它只是在主程序窗口的中心。它将对任何消息框或文件打开/保存对话框以及可能的其他一些本机控件执行此操作。我不确定,但我认为您可能需要包含COMMCTRL或COMMDLG来使用它,至少,如果您想要打开/保存对话框,您将会这样做。

我尝试查看NMHDR的通知代码和hwndFrom,然后决定它同样有效,而且更容易,而不是。如果你真的想要非常具体,请告诉FindWindow寻找你想要它找到的窗口的唯一标题(标题)。

在屏幕上绘制消息框之前会触发此消息,因此如果您设置一个全局标记以指示代码执行操作的时间,并查找唯一标题,则可以确保您执行的操作只会发生一次(将会可能是多个通知者)。我没有详细探讨过这个问题,但我设法让CreateWindow在一个消息框对话框上放置一个编辑框/它看起来像一只老鼠的耳朵嫁接到一只克隆猪的脊柱上,但是它有效。以这种方式做事可能比滚动自己要容易得多。

乌鸦。

编辑:小校正以确保处理正确的窗口。确保父句柄始终一致,这应该可以正常工作。它对我来说,即使有两个相同程序的实例......

答案 2 :(得分:1)

编写自己的消息框。表格和标签应该这样做。或者你还需要全球化吗?

答案 3 :(得分:1)

该课程证明适用于其他两种情况。我有一个我想要更大的FolderBrowserDialog,我想让它靠近父对话框的左上角(靠近我点击按钮打开它)。

我复制了CenterWinDialog类并创建了两个新类。一个类更改对话框大小,另一个类将其位置更改为父表单的特定偏移量。这是用法:

class OffsetWinDialog : IDisposable
{
    private int mTries = 0;
    private Form mOwner;

    public OffsetWinDialog(Form owner)
    {
        mOwner = owner;
        owner.BeginInvoke(new MethodInvoker(findDialog));
    }

    public Point PreferredOffset { get; set; }

    private void findDialog()
    {
        // Enumerate windows to find the message box
        if (mTries < 0) 
            return;
        EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
        if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero))
        {
            if (++mTries < 10)
                mOwner.BeginInvoke(new MethodInvoker(findDialog));
        }
    }
    private bool checkWindow(IntPtr hWnd, IntPtr lp)
    {
        // Checks if <hWnd> is a dialog
        StringBuilder sb = new StringBuilder(260);
        GetClassName(hWnd, sb, sb.Capacity);
        if (sb.ToString() != "#32770") return true;
        // Got it
        Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size);
        RECT dlgRect;
        GetWindowRect(hWnd, out dlgRect);
        MoveWindow(hWnd,
            frmRect.Left   + PreferredOffset.X,
            frmRect.Top    + PreferredOffset.Y,
            dlgRect.Right  - dlgRect.Left,
            dlgRect.Bottom - dlgRect.Top, 
            true);
        return false;
    }
    public void Dispose()
    {
        mTries = -1;
    }

    // P/Invoke declarations
    private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
    [DllImport("user32.dll")]
    private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
    [DllImport("kernel32.dll")]
    private static extern int GetCurrentThreadId();
    [DllImport("user32.dll")]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
    [DllImport("user32.dll")]
    private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
    private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}

这些是基于原始类的两个类。

class SizeWinDialog : IDisposable
{
    private int mTries = 0;
    private Form mOwner;

    public SizeWinDialog(Form owner)
    {
        mOwner = owner;
        mOwner.BeginInvoke(new Action(findDialog));
    }

    public Size PreferredSize { get; set; }

    private void findDialog()
    {
        // Enumerate windows to find the message box
        if (mTries < 0) 
            return;
        EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
        if (EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero))
        {
            if (++mTries < 10) 
                mOwner.BeginInvoke(new MethodInvoker(findDialog));
        }
    }
    private bool checkWindow(IntPtr hWnd, IntPtr lp)
    {
        // Checks if <hWnd> is a dialog
        StringBuilder sb = new StringBuilder(260);
        GetClassName(hWnd, sb, sb.Capacity);
        if (sb.ToString() != "#32770") 
            return true;
        // Got it
        Rectangle frmRect = new Rectangle(mOwner.Location, mOwner.Size);
        RECT dlgRect;
        GetWindowRect(hWnd, out dlgRect);
        SetWindowPos(new HandleRef(this, hWnd), new HandleRef(), dlgRect.Left, dlgRect.Top, PreferredSize.Width, PreferredSize.Height, 20 | 2);
        return false;
    }
    public void Dispose()
    {
        mTries = -1;
    }

    // P/Invoke declarations
    private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
    [DllImport("user32.dll")]
    private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
    [DllImport("kernel32.dll")]
    private static extern int GetCurrentThreadId();
    [DllImport("user32.dll")]
    private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc);
    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy,
        int flags);

    private struct RECT { public int Left; public int Top; public int Right; public int Bottom; }
}

 <img ng-src="{"original": "https://xxx-export.s3.amazonaws.com/images/products/2016/12/product_1003_2.jpg"}">

答案 4 :(得分:0)

创建自己的..

 public partial class __MessageBox : Form
   {
      public MMMessageBox(string title, string message)
      {
         InitializeComponent();
         this.Text = title;
         this.labelString.Text = message;
      }
   }