【发布时间】:2011-01-03 13:51:31
【问题描述】:
如何使用 WinForms 中的 ActiveForm 属性在 C# 中引用 WPF 应用程序的活动窗口?
【问题讨论】:
如何使用 WinForms 中的 ActiveForm 属性在 C# 中引用 WPF 应用程序的活动窗口?
【问题讨论】:
一种可能的方法是扫描应用程序中打开的窗口列表并检查其中哪个窗口具有IsActive = true:
Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
不确定是否可能有多个活动窗口,例如,如果有一个模态对话框显示,在这种情况下,对话框的所有者和对话框本身可能是活动的。
【讨论】:
OfType<Window>() 运算符而不是Cast<Window>() 运算符...
FirstOrDefault 而不是SingleOrDefault,如果有多个匹配项,则会引发异常。另外,它应该更快一点,因为它接受第一个结果并且不需要检查它是否是唯一的。
FirstOrDefault 和SingleOrDefault 都返回null,这意味着没有将 IsActive 设置为 true 的窗口。这怎么可能?
使用 PInvoke 有更好的方法来做到这一点。 Aviads 的答案并非一直有效(有一些带有对话框的极端情况)。
IntPtr active = GetActiveWindow();
ActiveWindow = Application.Current.Windows.OfType<Window>()
.SingleOrDefault(window => new WindowInteropHelper(window).Handle == active);
必须首先包含以下导入:
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
【讨论】:
IsActive。使用另一种解决方案引发异常(SingleOrDefault 抛出,如果有多个匹配谓词)或者在使用 FirstOrDefault 时没有给我实际的活动窗口
我知道这是一个有点老的问题,但我认为我的回答可以帮助某人。
我的问题是:我有一个 WPF MVVM 应用程序,我需要在第二个视图(即第二个视图模型)中获取我的 MainWindow 实例,以便将标题栏按钮的可见性设置为 visible。
这是我的解决方案:
MainWindow window = (MyApp.MainWindow)App.Current.MainWindow;
window.btnSearch.Visibility = System.Windows.Visibility.Visible;
希望这会对某人有所帮助。
【讨论】:
我对这种方式有问题 "Application.Current.Windows.OfType().SingleOrDefault(x => x.IsActive);"特别是因为我正在使用主窗口构建应用程序,然后在选择主窗口时遇到问题。我解决它创建这个:
在某些基类或 App.xaml.cs 中创建:
public static Window ActivatedWindow {get;set;}
然后将派生窗口的基类或所有窗口的激活事件放入:
第一个选项 - 个人窗口基类:
public class MetroToolWindowBase
{
public MetroToolWindowBase()
{
Activated += new EventHandler(MakeActive);
}
private void MakeActive(object sender, EventArgs e)
{
App.ActivatedWindow= this;
}
}
第二个选项-在 Windows 的激活事件中:
private void XWindow_Activated(object sender,EventArgs e)
{
App.ActivatedWindow= this;
}
【讨论】:
另一种方法是使用 user32.dll 中的原生 GetActiveWindow 函数。
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetActiveWindow();
要将其转换为实际的 WPF 窗口:
IntPtr handle = GetActiveWindow();
HwndSource hwndSource = HwndSource.FromHwnd(handle);
var window = hwndSource?.RootVisual as Window;
如果在 WinForms 应用程序中托管 WPF 窗口,则应使用 WindowInteropHelper。例如,这使得 Window 所有者可以正常工作:
var wih = new WindowInteropHelper(window)
{
Owner = GetActiveWindow()
};
我编辑了旧答案,因为我遇到的边缘情况在 Visual Studio 更新后消失了,但可以从答案历史记录中检查。我遇到了一个问题,即在调试时在某些情况下活动窗口为空。
【讨论】: