当前位置: 首页 > 知识库问答 >
问题:

C#WPF和WinForms interop-centerowner无效

贲俊才
2023-03-14

我正在开发一个使用WPF和WinForms作为UI的遗留应用程序。WPF弥补了绝大多数,但是应用程序的主对话框仍然在WinForms中。

到目前为止,我已经能够让它们很好地协同工作(多亏了System.windows.forms.integration.elementhost),但我无法让WPF窗口以它们的WinForms父窗口为中心。

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    var dialog = new SubWindow();
    WindowOwnershipHelper.SetOwner(dialog, this);
    dialog.ShowDialog();
}

OwnershipHelper(摘自https://stackoverflow.com/a/36606974/13567181)

这个类建立“父-子”关系,这样嵌套的对话框就可以在同一屏幕上打开,并与其父对话框一起最小化。

public static class WindowOwnershipHelper
{
    public static void SetOwner(Window window, Visual parent)
    {
        var source = (HwndSource) PresentationSource.FromVisual(parent);

        if (source == null)
        {
            throw new InvalidOperationException("Could not determine parent from visual.");
        }

        new WindowInteropHelper(window).Owner = source.Handle;
    }
}

我面临的问题是,当dialog.showDialog()执行时,新打开的窗口根本不围绕其所有者。它在屏幕上的某个地方,但我不太明白它是如何确定它的位置的。

编辑:我刚在MSDN上找到这个--它有点相似,但我不确定。https://social.msdn.microsoft.com/forums/vstudio/en-us/05768951-73cf-4daf-b369-0905ca7e5222/centering-wpf-window-on-winforms-owner-window?forum=wpf

向诺伯特问好

共有1个答案

江承嗣
2023-03-14

使用application.run(new MyForm2());,然后单击该按钮创建一个以主窗体为中心的WPF窗口

public class MyForm2 : Form {

    public MyForm2() {
        this.Size = new Size(600,600);
        this.StartPosition = FormStartPosition.CenterScreen;
        Button btn = new Button { Text = "New Window", AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink };
        btn.Click += btn_Click;
        Controls.Add(btn);
    }

    void btn_Click(object sender, EventArgs e) {
        var w = new System.Windows.Window();
        w.SourceInitialized += w_SourceInitialized;
        w.Width = 400.0; // number of actual pixels might be different
        w.Height = 400.0; // depending on DPI. My laptop is 120 dpi, so 400.0 -> 400 * 120 / 96 = 500 pixels.
        w.Title = "WPF Window";
        w.ShowDialog();
    }

    void w_SourceInitialized(object sender, EventArgs e) {
        var w = (System.Windows.Window) sender;
        WindowInteropHelper helper = new WindowInteropHelper(w);
        //w.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner; does nothing
        int GWL_HWNDPARENT = -8;
        SetWindowLongInternal(helper.Handle, GWL_HWNDPARENT, this.Handle);

        Rectangle r = this.Bounds;
        RECT r2 = new RECT();
        GetWindowRect(helper.Handle, out r2);
        int w2 = r2.Right - r2.Left;
        int h2 = r2.Bottom - r2.Top;

        int x2 = r.X + (r.Width - w2) / 2;
        int y2 = r.Y + (r.Height - h2) / 2;

        uint SWP_NOSIZE        = 0x0001;
        uint SWP_NOZORDER      = 0x0004;
        uint SWP_NOREDRAW      = 0x0008;
        uint SWP_NOACTIVATE    = 0x0010;
        uint SWP_NOCOPYBITS    = 0x0100;
        uint SWP_NOOWNERZORDER = 0x0200;
        uint flags = SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER;

        SetWindowPos(helper.Handle, IntPtr.Zero, x2, y2, 0, 0, flags);
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

    [DllImport("user32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int w, int h, uint uFlags);

    [DllImport("user32.dll", SetLastError=true)]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    [DllImport("user32.dll", SetLastError=true)]
    private static extern int SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

    private static int SetWindowLongInternal(IntPtr hWnd, int nIndex, IntPtr dwNewLong) {
        if (IntPtr.Size == 4)
            return SetWindowLong(hWnd, nIndex, dwNewLong);

        return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
    }
}
 类似资料:
  • 我有一个组合框,它在下拉列表中显示listview,我遵循MVVM模式,我也在我的Viewmodel中设置了公共属性,当我将其分配给标签时,它工作正常,但对于组合框,它似乎不依赖于我的绑定。我尝试了很多方法,但都找不到问题所在。 XAML: 当我使用公共属性并访问它的元素时,这对我来说很好,我还尝试设置text={绑定选择MU.MU_Identifier}和选择值,但它不起作用。

  • WPF

    WPF(Windows Presentation Foundation) 是微软推出的用于构建桌面客户端应用程序的 UI 框架,具有应用程序模型、控件、图形、布局、数据绑定和安全性等功能,属于 .NET Framework 3.0 的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。 WPF 的核心是一个利用现代图形硬

  • 我正在使用HierarchycalDataTemplate来形成树。我正在做以下事情:1。选择一个文件夹并单击“添加文件夹”按钮。2.应显示选定文件夹下的新文件夹。ViewModel已正确更新,以便在选定的Folder元素下有一个文件夹,并在TreeView中更新该文件夹。 我关心的是如何获取添加文件夹的TreeView项。我有对新添加文件夹的引用,但不知道如何获取同一文件夹的TreeViewIt

  • 日安, 我希望我的组合框选择其中的第一个项目。我正在使用C#和WPF。我从DataSet读取数据。要填充组合框: 组合框XAML代码: 如果我尝试: 它不起作用。

  • 本文向大家介绍C# WPF 自定义按钮的方法,包括了C# WPF 自定义按钮的方法的使用技巧和注意事项,需要的朋友参考一下 本文介绍WPF一种自定义按钮的方法。 实现效果 使用图片做按钮背景; 自定义鼠标进入时效果; 自定义按压效果; 自定义禁用效果 实现效果如下图所示: 实现步骤 创建CustomButton.cs,继承自Button; 创建一个资源文件ButtonStyles.xaml; 在资

  • 本文向大家介绍C# WPF ListView控件的实例详解,包括了C# WPF ListView控件的实例详解的使用技巧和注意事项,需要的朋友参考一下 C# WPF ListView控件的实例详解 C#的WPF作为现在微软主流的桌面程序开发平台,相比过去的MFC时代,有了非常多的不同。本人刚从MFC平台转过来,以为可以轻松上手,哪知碰到了很多问题,十分不解。不得不乖乖回去看了本书,再继续回到边左边