我正在使用WPF的OpenFileDialog,我正在尋找一種方法來確保它在顯示時在父窗口居中。它似乎缺少可能啓用此功能的StartupPosition等明顯屬性。如何將OpenFileDialog居中放置在WPF的父窗口中?
有人知道祕密嗎?
更新:看來,我第一次打開它,它確實出現在父母的中心,但如果我移動它,它會記住它的位置,並且不會在隨後的事件中集中打開。
我正在使用WPF的OpenFileDialog,我正在尋找一種方法來確保它在顯示時在父窗口居中。它似乎缺少可能啓用此功能的StartupPosition等明顯屬性。如何將OpenFileDialog居中放置在WPF的父窗口中?
有人知道祕密嗎?
更新:看來,我第一次打開它,它確實出現在父母的中心,但如果我移動它,它會記住它的位置,並且不會在隨後的事件中集中打開。
WPF中的CommonDialog不從窗口類繼承,所以它沒有StartupPosition屬性。
查看此博客文章的一個解決方案:OpenFileDialog in .NET on Vista
總之,它將對話框包裝在一個窗口中,然後顯示它。
謝謝你。你鏈接到的解決方案是有效地使用WinForms OpenFileDialog,我希望避免。 – 2011-03-16 10:18:31
這裏是一個泛型類的代碼,允許與「次對話」像這樣打一處來:
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);
}
我可能在這裏錯過了一些東西,但你似乎正在改變父窗口而不是用OpenFileDialog做任何事情? – 2011-03-16 10:54:50
@Samuel - WM_ENTERIDLE被髮送到一個對話框(這裏是OpenFileDialog)的所有者,並且lParam arg包含對話框的句柄。你有沒有嘗試過的代碼? – 2011-03-16 11:35:20
還沒有嘗試過代碼 - 只是試圖首先理解它。現在你已經解釋了WM_ENTERIDLE的意義,這一切都是有道理的。謝謝。 – 2011-03-16 11:41:22
這似乎是我進行快速測試時的默認行爲。你能更詳細地描述你的情況嗎? – 2011-03-16 09:27:11
@Fredrik - 我在問題 – 2011-03-16 09:51:41
中添加了另一個細節我第一次看到一個OP不被接受的問題,它不僅有50分,而且還有如此巨大的差距17.2k,對你很恥辱。 :) – 2015-07-06 14:47:46