c# - WPF 窗口应该是 native 所有者窗口的模式,但不是

标签 c# wpf window native owner

我在 WPF 项目中有以下 C# 代码:

private static void RunConfig(string owner)  
{  
    long ownerHandle;  
    var settingsWindow = new SettingsWindow();  
    if (long.TryParse(owner, out ownerHandle))  
    {  
        WindowInteropHelper helper = new WindowInteropHelper(settingsWindow);  
        helper.Owner = new IntPtr(ownerHandle);  
    }  
    settingsWindow.ShowDialog();  
}

SettingsWindow 不是所有者窗口的正确模态(即,当 SettingsWindow 仍然打开时,我可以专注于所有者窗口,与之交互,甚至关闭所有者窗口)。我做错了什么?

对于上下文,此代码是屏幕保护程序的一部分,所有者窗口是控制面板屏幕保护程序选择窗口(它通过命令行参数传入句柄以用作所有者)。我知道 IF 语句正在评估 true 并正确解析句柄。

我也尝试过使用 user32.dll 中的 SetWindowLongPtr 方法(针对 x64 进行编译,因此不使用 SetWindowLong),简要说明here并在使用中展示 here .此方法在 WinForms 中有效,但在 WPF 中似乎无效。帮助我 Obi-Wan Kenobi,你是我唯一的希望。

最佳答案

事实证明,使用 WindowInteropHelper 将 native 窗口设置为 WPF 窗口的所有者确实有效,但它无法完成全部工作。以这种方式设置时,WPF 窗口将在 native 窗口顶部保持可见,即使 native 窗口具有焦点也是如此。然而,这是唯一获得的效果。 WPF Window 不会阻​​止与 native Window 的交互, native 窗口甚至可以关闭,而 WPF Window 不会关闭或受到影响。

为了获得所需的其余行为,我们需要使用 EnableWindow user32.dll 中的函数在 WPF 窗口上调用 ShowDialog 之前禁用 native 窗口,并在 WPF 窗口关闭后再次重新启用它。

修改后的代码如下所示:

private static void RunConfig(string owner)
{
    long ownerHandle;
    var settingsForm = new SettingsWindow();
    if (long.TryParse(owner, out ownerHandle))
    {
        WindowInteropHelper helper = new WindowInteropHelper(settingsForm);
        helper.Owner = new IntPtr(ownerHandle);
        NativeMethods.EnableWindow(helper.Owner, false);
        settingsForm.ShowDialog();
        NativeMethods.EnableWindow(helper.Owner, true);
    }
    else
    {
        settingsForm.ShowDialog();
    }
}

(注意:上面的代码一般来说是正确的,但在屏幕保护程序的情况下不完整,这就是这段代码的实际用途。如果这段代码用于屏幕的配置窗口saver,为所有者句柄传入的字符串不是要用作所有者的控制面板窗口的句柄,而是控制面板窗口的子控件的句柄。在这种情况下的额外步骤是获取该控件的父控件的句柄。我们可以通过调用 GetParent 来完成此操作,也在 user32.dll 中,在传入的句柄上。这将返回我们想要使用的真实句柄用于所有者和 EnableWindow 调用。)

如果 Microsoft 的任何人发现此问题,可以考虑修改 WindowInteropHelper 以在分配 Owner 并使用 ShowDialog 时正确设置所有这些,因为这是模态窗口的正确完整行为。

关于c# - WPF 窗口应该是 native 所有者窗口的模式,但不是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14151038/

相关文章:

c# - .net core 6 api错误请求

javascript - 用 JavaScript 打开一个全新的窗口,而不替换前一个窗口的内容

Javascript,访问其他窗口的变量

c# - WpfToolkit AutoCompleteBox 上下文菜单不工作

javascript - 即使放在 $(window).load 内,我也会得到 $(image).width() == 0

c# - 使用 Ajax 加载用户控件

c# - 在 XSL 中使用特殊字符

c# - 将文本写入文件中间

.net - Silverlight 和 WPF 兼容性

wpf - 一般来说,什么是 WPF 面板和布局的好指南?