调用`Show()`时,错误的窗口出现在任务栏上

时间:2013-05-30 11:53:25

标签: wpf winapi window user32

这让我感到困惑,我开始相信这是核心winapi或WPF中的错误。如果此处没有人知道问题的可能原因,我将在Microsoft Connect上提交错误报告。

问题在我调用Window.Show()后出现,但根本原因可能在于其他地方,包括之前调用user32.dll。一旦我在窗口上调用Show(),我的窗口就会显示,但任务栏上会弹出另一个窗口,但不会显示。此外,单击它不会使该窗口可见。

我试图显示的窗口设置了以下属性,这似乎是导致这种奇怪行为所必需的。改变其中任何一个'修复'这个问题。

WindowStyle="None"
WindowState="Maximized"
ShowInTaskbar="False"

我正在创建虚拟桌面管理器(VDM),因此我通过user32.dll隐藏/显示窗口。如果我在显示我想要的窗口之前没有隐藏任何窗口,问题也不会出现。 VDM is available on github的完整代码。特定的user32调用发生在包装器which can also be found on github中。

// Hide windows.
var hideWindows = _windows
    .Select( w => new RepositionWindowInfo( w.Info ) { Visible = false } );
WindowManager.RepositionWindows( hideWindows.ToList() );

此处发布RepositionWindows方法有点长,但您可以看到它in its entirety on github。它使用BeginDeferWindowPosDeferWindowPosEndDeferWindowPos

最后,当我使用Visibility属性显示/隐藏我的窗口而不是使用Show()Hide()时,在某些情况下不会出现所描述的行为(稍后会详细介绍)无论是。但是,according to the documentation on msdn

  

调用Show可以获得与设置Visibility相同的最终结果   Window对象的属性为Visible。但是,有一个   从时间角度看两者之间的差异。呼叫秀是   仅在Loaded事件开启后返回的同步操作   子窗口已被提升[...]

这似乎与正在执行同步或异步的操作有很大关系。在某些情况下,我使用user32的ShowWindow隐藏了一个特定的窗口。如果我在显示窗口后立即(使用快捷键),无论是使用Visibility还是Show()来显示窗口,问题都会再次出现。但是,如果我使用ShowWindowAsync()隐藏窗口,则一切都很好。

最后......(很多,如果是......我知道,很抱歉)当我在显示窗口之前点击任何窗口(选择它)时,问题也不会发生。如果我不使用快捷键来显示窗口,我将永远不会发现这个。

这个问题的根本原因是什么?

1 个答案:

答案 0 :(得分:0)

我想我已经确定了造成这个问题的核心问题。隐藏窗口时,另一个窗口处于活动状态。但是,似乎只有任务栏上的窗口才会处于活动状态。当我隐藏所有窗口然后调用GetActiveWindow时,它表示没有窗口处于活动状态(返回值为null)。

随后显示一个窗口,该窗口不应显示在任务栏上(无论是使用Show()还是Visibility),隐藏窗口都会显示在任务栏上。

解决此问题的解决方法是在延迟窗口定位操作之后检查是否有任何窗口处于活动状态。如果没有,我现在把焦点放在任务栏上。下次显示非任务栏窗口时,不会发生错误!

succeeded = User32.EndDeferWindowPos( windowsPositionInfo );
if ( succeeded && User32.GetActiveWindow() == IntPtr.Zero )
{
    WindowInfo startBar = GetWindows()
        .Where( w => w.GetClassName() == "Shell_TrayWnd" ).FirstOrDefault();
    if ( startBar != null )
    {
        User32.SwitchToThisWindow( startBar.Handle, false );
    }
}