如何在 WPF 中将 OpenFileDialog 置于其父窗口的中心?

发布于 2024-10-22 11:34:01 字数 313 浏览 3 评论 0原文

我正在使用 WPF 的 OpenFileDialog,并且我寻找一种方法来确保它在显示时位于父窗口的中心。它似乎缺少像 StartupPosition 这样可能启用此功能的明显属性。

有人知道其中的秘密吗?

更新:似乎我第一次打开它时,它确实出现在父级的中心,但是如果我移动它,它就会记住它的位置,并且不会在后续情况下以中心方式打开。

I'm using WPF's OpenFileDialog, and I'm looking for a way to make sure it is centered in the parent window when shown. It seems to be missing obvious properties like StartupPosition that might enable this.

Does anybody know the secret?

Update: It seems that the first time I open it, it does appear in the center of the parent, but if I move it, it then remembers its position, and doesn't open centered on subsequent occassions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

有木有妳兜一样 2024-10-29 11:34:01

下面是一个通用类的代码,它允许使用像这样的“子对话框”:

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);
}

here is the code of a generic class that allows to play with "sub dialogs" like this one:

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;
    }
}

And this is how you would use it in a standard WPF app. Here I just copy the parent window size, but I'll let you do the center math :-)

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);
}
国粹 2024-10-29 11:34:01

WPF 中的 CommonDialog 不是从窗口类继承的,因此它没有 StartupPosition 属性。

查看此博客文章以获取一种解决方案:OpenFileDialog in .NET on远景
简而言之,它将对话框包装在窗口中然后显示它。

CommonDialog in WPF does not inherit from window class, so it does not have StartupPosition property.

Check this blog post for one solution: OpenFileDialog in .NET on Vista
In short, it wraps dialog in a window and then shows it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文