我正在使用WPF的OpenFileDialog,我正在寻找一种方法来确保它在显示时在父窗口中居中。它似乎缺少像StartupPosition这样可能启用此功能的明显属性。
有人知道这个秘密吗?
更新:似乎第一次打开它时,它确实出现在父级的中心,但如果我移动它,则会记住它的位置,并且不会打开居中在随后的时间里。
答案 0 :(得分:5)
这里是一个泛型类的代码,它允许使用像这样的“子对话框”:
public class SubDialogManager : IDisposable
{
public SubDialogManager(Window window, Action<IntPtr> enterIdleAction)
:this(new WindowInteropHelper(window).Handle, enterIdleAction)
{
}
public SubDialogManager(IntPtr hwnd, Action<IntPtr> enterIdleAction)
{
if (enterIdleAction == null)
throw new ArgumentNullException("enterIdleAction");
EnterIdleAction = enterIdleAction;
Source = HwndSource.FromHwnd(hwnd);
Source.AddHook(WindowMessageHandler);
}
protected HwndSource Source { get; private set; }
protected Action<IntPtr> EnterIdleAction { get; private set; }
void IDisposable.Dispose()
{
if (Source != null)
{
Source.RemoveHook(WindowMessageHandler);
Source = null;
}
}
private const int WM_ENTERIDLE = 0x0121;
protected virtual IntPtr WindowMessageHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_ENTERIDLE)
{
EnterIdleAction(lParam);
}
return IntPtr.Zero;
}
}
这就是你在标准WPF应用程序中使用它的方法。这里我只是复制父窗口大小,但我会让你做中心数学: - )
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
bool computed = false; // do this only once
int x = (int)Left;
int y = (int)Top;
int w = (int)Width;
int h = (int)Height;
using (SubDialogManager center = new SubDialogManager(this, ptr => { if (!computed) { SetWindowPos(ptr, IntPtr.Zero, x, y, w, h, 0); computed= true; } }))
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.ShowDialog(this);
}
}
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int flags);
}
答案 1 :(得分:0)
WPF中的CommonDialog不从窗口类继承,因此它没有StartupPosition属性。
在此博客文章中查看一个解决方案:OpenFileDialog in .NET on Vista
简而言之,它在窗口中包装对话框然后显示它。