using (new OffsetWinDialog(this) { PreferredOffset = new Point(75, 75 )})
using (new SizeWinDialog(this) { PreferredSize = new Size(400, 600)})
{
DialogResult result = dlgFolderBrowser.ShowDialog();
if (result == DialogResult.Cancel)
return;
}
这两个类是基于原始类的。
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; }
}
6条答案
按热度按时间pcrecxhr1#
使用一些P/Invoke服务和Control.BeginInvoke()提供的魔力是可能的。将新类添加到项目中并粘贴以下代码:
样品使用:
请注意,此代码适用于任何Windows对话框。MessageBox、OpenFormDialog、FolderBrowserDialog、PrintDialog、ColorDialog、FontDialog、PageSetupDialog、SaveFileDialog。
kx5bkwkv2#
这是Win32 API,用C写的。你需要的话就翻译吧。。
将其添加到WndProc代码中…您可以根据需要设置位置,在这种情况下,它只是在主程序窗口的中心。它将为任何消息框或文件打开/保存对话框以及其他一些本机控件执行此操作。我不确定,但我认为你可能需要包括COMMCTRL或COMMDLG来使用它,至少,如果你想要打开/保存对话框,你会这样做。
我尝试查看NMHDR的通知代码和hwndFrom,然后决定它同样有效,而且更容易,不要。如果你真的想非常具体,告诉FindWindow寻找一个唯一的标题(标题),你给予你想找到的窗口。
这会在屏幕上绘制消息框之前触发,因此如果您设置了一个全局标志来指示代码执行操作的时间,并查找唯一的标题,则可以确保您执行的操作只发生一次(可能会有多个通知程序)。我还没有详细探讨过这个问题,但我设法让CreateWindow在消息框对话框上放了一个编辑框/它看起来就像把老鼠的耳朵移植到克隆Pig的脊柱上一样不合时宜,但它确实有效。这样做可能比你自己做要容易得多。
乌鸦
编辑:小的修正,以确保正确的窗口处理。确保父句柄始终一致,这样应该可以正常工作。对我来说,即使是同一个程序的两个示例...
l5tcr1uw3#
这个类被证明适用于另外两种情况。我有一个FolderBrowserDialog,我希望它更大,我希望它出现在父对话框的左上角附近(靠近我单击打开它的按钮)。
我复制了CenterWinDialog类并创建了两个新类。一个类更改对话框的大小,另一个类将其位置更改为相对于父窗体的特定偏移量。这就是用法:
这两个类是基于原始类的。
和/或
nfeuvbwi4#
写你自己的消息框。一个表单和一个标签就可以了。或者你也需要全球化吗?
l2osamch5#
无需自制messagebox或GetForegroundWindow、EnumWindows、AutomationElement、RootElement、FindAll、SetWindowsHookEx等。
WM_ACTIVATE消息在消息框打开或关闭时发送到窗体。然后您可以获取消息框的窗口句柄(LParam)。
GetWindowProcessId是GetWindowThreadProcessId的 Package 。根据需要添加其他Pinvoke方法。如果你想尽可能地减少P/Invoke,用UIAutomation替换它们。
7fhtutme6#
创建您自己的..