【问题标题】:Why does TopMost=True not always work?为什么 TopMost=True 并不总是有效?
【发布时间】:2011-02-21 14:12:16
【问题描述】:

我有一个简单的应用程序,它很小,应该漂浮在我所有其他窗口的顶部。几个小时后,我会注意到它不再位于我所有其他窗口的顶部,我想知道是否有人知道为什么会发生这种情况。

在此期间,我打开了新的应用程序(主要是 MS 2010 产品),几次锁定/解锁了我的电脑,点击了桌面快捷方式,并在屏幕上移动了应用程序(有时在屏幕之间移动,因为我有两台显示器) .

我无法按需复制该行为,但它每天至少发生一次。当它停止停留在顶部时,它会在我点击桌面快捷方式时隐藏起来,所以我认为 TopMost 属性以某种方式设置为 false。

<Window AllowsTransparency="True" 
        WindowStyle="None"
        Topmost="True"
        SizeToContent="WidthAndHeight"
        MouseDown="Window_MouseDown"
        ShowInTaskbar="False"
        Background="Transparent" 
        SnapsToDevicePixels="True">

该应用程序非常简单......它就像一个虚拟国际象棋时钟一样工作,让我可以跟踪处理帮助台电话与实际开发所花费的时间。 MouseDown 事件只是触发应用程序的拖放行为,因为 WindowStyle 设置为 None。

我正在运行 WindowsXP,并且该应用程序是在 .Net 4.0 中构建的。

【问题讨论】:

  • 运气好了吗?我也遇到了同样的问题,还没有找到可靠的解决方案。
  • @joeg 很遗憾,没有。我的窗口仍然间歇性地消失
  • 在我的应用程序中,我一直在重现 Topmost 的损失。首先,我有一个最顶层的 WindowA。在另一个窗口 WindowB 中,我执行以下操作:(1) 设置 WindowB.Topmost = true,然后 (2) 调用 MessageBox.Show,然后 (3) 再次设置 WindowB.Topmost = false。在此之后,WindowA 将失去最顶层的状态。这很令人沮丧。

标签: wpf topmost


【解决方案1】:

也许您可以捕获Deactivated 事件,并再次强制窗口回到顶部?

只是一个猜测,但如果在正确的时间设置Topmost = False 然后Topmost = True 可以解决它,那么值得研究。

【讨论】:

  • 谢谢,我正在试一试,但在它不再停留在其他窗口之上之前,我不确定它是否有效。现在我添加了一个 MessageBox 警报并在窗口被停用并且 Topmost=False 时重置 Topmost=True
  • 仍然无法重现该问题...不知道为什么,因为在我发布此消息之前它每天都在发生。你的想法是个好主意,我接受它作为答案
  • 不幸的是,这不起作用...我正在观看Deactivated 事件并在TopMost = false 时抛出一个弹出窗口并且它永远不会触发。
【解决方案2】:

替代解决方案

在您的 WPF 主窗口中

namespace YourNameSpace
{  
     public partial class MainWindow : Window
     {
    public MainWindow()
    {
        InitializeComponent();
    }

    private delegate void MessageBoxDelegate(DelegatePara para);

    public void ShowAwMessageBox(DelegatePara para)
    {            
        this.Dispatcher.BeginInvoke(new MessageBoxDelegate(ShowMessageBox), para);
    }

    private void ShowMessageBox(DelegatePara para)
    {
        this.Topmost = true;
        int typ = para.count;
        string msg = para.Msg;
        switch (typ)
        {
            case 0:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Information);
                break;
            case 1:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Error);
                break;
            case 2:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Question);
                break;
            default:
                MessageBox.Show(this, msg, "Auswertung", MessageBoxButton.OK, MessageBoxImage.Information);
                break;
        }
    }
}

 public class DelegatePara
 {
    public int count {get;set; }
    public string Msg {get;set; }
 }
}

然后你可以在任何你想要的地方用MainWind句柄调用它,即使是在一个线程中

this.MyWind.ShowRlvAwMessageBox(new DelegatePara() { count = 0, Msg = "Hallo World!" });

【讨论】:

    【解决方案3】:

    这个问题已经很老了,但我还没有找到任何真正的解决方案,所以这是我对遇到这个问题的其他人的想法:

    试试 Tom 的建议,但不要仅仅检查 TopMost 是否变为使用 ShowWindowAsync 来强制它再次显示。

    唯一可能成为问题的是它可以将焦点从活动应用程序中移开,但我知道如果您可以选择的话,有一种方法可以使其成为“无焦点”表单。

    即将亲自尝试,所以如果它适用于详细信息,我将更新此答案。

    【讨论】:

    • “我要亲自尝试一下,所以如果它适用于细节,我会更新这个答案。” - 所以它不起作用?
    • @dontbyteme 哦,天哪...对不起,我忘了回来更新这个。我不能说我现在肯定记得,但我不认为这最终成为我的最终解决方案。我想我必须在这个问题上加入答案:stackoverflow.com/questions/156046/…
    • @dontbyteme 虽然现在我又在看,但也许你没有把它变成一个无焦点的窗口,所以这个答案可能无济于事。如果一切都失败了,只需设置一个计时器将其放回顶部。当然,您要确保当您这样做时,它不会窃取您正在处理的任何事情的焦点(或快速返回),因此这本身可能是另一个挑战。希望我说的对您有所帮助,祝您好运!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2019-08-02
    • 2016-11-11
    相关资源
    最近更新 更多