Winforms - 如何使对话框显示在MainForm的中心?这与基于普通窗口默认值相反,后者将它们呈现在屏幕的中心。
在我的情况下,我有一个小的主要表单,例如可能位于一个角落,MessageBox弹出窗口显示似乎有一些方法。
答案 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;
}
}