【问题标题】:How to keep the focus on a WPF desktop application?如何保持对 WPF 桌面应用程序的关注?
【发布时间】:2016-02-20 13:08:58
【问题描述】:

我想创建一个可供我女儿使用的 Windows 桌面应用程序。用例是我给她一个键盘,然后我启动这个应用程序,这样她就可以按她想要的任何键。该应用程序可以显示某些内容(例如,按下的大字母或图片等)并防止我女儿从/在我的计算机上删除/修改内容。

我在处理特殊键时遇到了一些困难。我可以使用以下技术禁用 ALT+F4,但无法控制 ALT+TAB 和 Win 键。

public MainWindow()
{
    InitializeComponent();
    this.KeyDown += new KeyEventHandler(OnButtonKeyDown);
}

protected override void OnPreviewKeyDown(KeyEventArgs e)
{
    if (Keyboard.Modifiers == ModifierKeys.Alt && e.SystemKey == Key.F4)
    {
        e.Handled = true;
    }
    else
    {
        base.OnPreviewKeyDown(e);
    }
}

我发现 an article 在应用程序处于活动状态时会禁用此类功能,但我认为它对于非预期的应用程序退出非常脆弱。

我最后做的是一个可行但感觉不太专业的解决方法。

public MainWindow()
{
    InitializeComponent();
    System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
    dispatcherTimer.Tick += OnTimerTick;
    dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 100);
    dispatcherTimer.Start();
}

private void OnTimerTick(object sender, EventArgs e)
{
    this.Activate();
    this.Focus();
}

如您所见,我创建了一个计时器,它会不时将焦点带回来。这样,如果您按 Win 键或 ALT+TAB 键,应用程序就会返回。

如何以更专业的方式专注于我的申请?我正在考虑一种解决方案,它可以检测应用程序何时失去焦点(出于任何原因)并重新设置焦点。

【问题讨论】:

  • 在我的脑海中,我认为您可以实现偶数OnFocusLost。不过,不确定它是否适用于所有 WIN 键和其他东西。
  • 为什么不创建另一个用户,它只有这个程序,而其他所有东西都被锁定了?然后您只需将用户切换到它,当您想要返回时,将用户切换回来(并输入您的密码)

标签: c# .net wpf


【解决方案1】:

使用Window.Deactivated事件并重新激活它来实现你想要的:

this.Deactivated += (s, e) => this.Activate();

您还希望让应用全屏显示并在应用内创建一个隐藏的快捷键。按下该按钮后,系统会提示您输入密码,然后您可以关闭应用程序。否则,你也为你关闭应用程序会很麻烦。

【讨论】:

  • 嗨@fᴀʀʜᴀɴ-aɴᴀᴍ!谢谢你的时间。我应该把这段代码放在哪里?我将它放入 MainWindow 构造函数中,但它无助于重置焦点。我可以通过这种方式轻松切换应用程序。对于您的其他建议:是的,我做到了。 :)
  • 此代码不起作用。当我们尝试在我们的应用程序中聚焦一个窗口时,它可能会起作用。但不在我们的应用程序之外。
【解决方案2】:

在我的 XAML 标记中,我添加了用于停用的事件侦听器。

<Window x:Class="Desktop.MainWindow"
        Deactivated="MainWindow_OnDeactivated">
...
</Window>

在后面的代码中,我添加了用于重新激活的事件处理程序。

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

    private void MainWindow_OnDeactivated(object sender, EventArgs eventArgs)
    {
      Activate();
    }
  }
}

【讨论】:

  • 嗨@konrad-viltersten!你试过了吗?我问是因为我添加到 my current version (locally) 并且它对我不起作用。我使用 VS 2015 社区版、Windows 10,并尝试了 Visual Studio 中的 VS 调试版本。如果它对您有用,那也很有帮助,因为这意味着问题出在我的设置中。
  • @GaborMeszaros 我试过了,是的。首先,我尝试了焦点事件,但这并没有将窗口拉回视图。但是这个做到了。我在Win 8上,如果有什么不同的话。当你说它不起作用时,你到底是什么意思?发生什么了?您是否在处理程序中遇到断点?然后……?
  • 我将两个视频上传到 YouTube Timer solutionDeactivated solution。在第二种情况下,当您按下 Win 键时,它会停留在那里。在 Timer 解决方案的情况下,它会将应用程序带回顶部并将焦点返回给它。
  • @GaborMeszaros 我可能还没有用 Win 测试过它。我可能只是点击离开窗口,然后它自己又回到了视图中。您可以重新映射键,但这更像是一种丑陋的解决方法,而不是一种解决方案。我现在没有别的了。您的问题很困难,因为从技术上讲,您正试图消除多窗口 GUI 中的其他窗口...您见过 this(完全未经测试)吗?
【解决方案3】:

使用以下窗口 XAML:

<Window x:Class="WpfStackOverflowTempProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="450" Width="525"
    DataContext="{RelativeSource Mode=PreviousData}"
    xmlns:local="clr-namespace:WpfStackOverflowTempProject" 
    WindowState="Maximized"   ResizeMode="NoResize"  
    Topmost="True"        
    >

Topmost="True" 应该从功能的角度来看技巧。 WindowState="Maximized" & ResizeMode="NoResize" 限制 与其他窗口的交互。

【讨论】:

  • 嗨@kylo-ren!它对我不起作用。我倾向于相信该问题与 Windows 10 有关。我将使用此信息更新原始帖子。我在@konrad-viltersten 的回答中添加了两个视频。你的解决方案给了我与他的解决方案完全相同的结果。
  • @GaborMeszaros 我不认为我们的解决方案可以产生相同的结果。从理论上讲,如果一个窗口被激活并不一定意味着它将是最顶层的窗口或者它将是焦点窗口。发布的其他解决方案的问题是他们没有在用户停用和代码激活之间使用任何延迟。因此激活将在 alt+tab 结果结果呈现之前发生。并且 alt+tab 结果最终将在屏幕上可见。我已经在窗口 10 中测试了我的代码并且它正在工作。不知道为什么它不适合你。
  • @GaborMeszaros 我认为 DispatcherTimer 解决方案也不完整。试试 win + m 键。或者用户可以最小化窗口。
猜你喜欢
  • 2015-03-17
  • 2016-11-23
  • 1970-01-01
  • 2012-02-01
  • 2017-04-11
  • 2010-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多