WPF 始终位于顶部

问题描述 投票:0回答:8

即使其他应用程序在全屏上运行,是否可以使窗口始终保持在顶部?我现在正在使用

TopMost = true
,但是当其他应用程序在全屏上运行时,我的应用程序变得不可见。顺便说一句,这是
WindowStyle = None
窗口。

编辑:当然不要让其他窗口最小化

c# wpf topmost
8个回答
64
投票

这不会100%有效,但会在一定程度上改善情况。您可以在

Topmost = true
 事件的处理程序中设置 
Window.Deactivated

private void Window_Deactivated(object sender, EventArgs e)
{
    Window window = (Window)sender;
    window.Topmost = true;
}

只要您的应用程序失去焦点(通常是当另一个应用程序请求

Deactivated
时),就会调用
Topmost
事件,因此此后这会将您的应用程序重置为顶部。


17
投票

尝试 MSDN 中的这个解决方案,它应该适合您。 在

Window Activated Event
中添加以下代码:

this.Width   = System.Windows.SystemParameters.PrimaryScreenWidth;
this.Height  = System.Windows.SystemParameters.PrimaryScreenHeight;
this.Topmost = true;
this.Top  = 0;
this.Left = 0;

DeActivated Event
中添加以下代码

this.Topmost = true;
this.Activate();

原帖来自MSDN


16
投票

上述解决方案对我来说都不起作用,所以这就是我最终所做的。它对我来说非常有效。

基本上,要使其保持在顶部,您只需设置失去焦点事件即可使其返回顶部。

XAML:

PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus"
    

背后代码:

private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
      var window = (Window)sender;
      window.Topmost = true;
}

3
投票

如果您希望应用程序掌控一切(包括 Windows 8 中的启动界面,以前称为“Metro”),那么您可以在清单文件中指定 UiAccess="True"。这通常由辅助应用程序(例如屏幕键盘)使用。

根据记忆,你需要做 3 件事;

  1. 请求 UiAccess="True"
  2. 使用公认的证书对应用程序的 exe 文件进行签名。我从 Certum 获得了免费的代码签名证书,因为我的项目是开源的。
  3. 将您的应用程序安装到“受信任的位置”,在我的例子中是程序文件目录。我找不到“受信任位置”的官方定义。

3
投票

所以我最近遇到了同样的需求。似乎评分最高的答案以及第二个答案对我来说都不起作用。我找到了一个似乎完美运行的解决方案,并且在某种程度上遵循了使用 MVVM 的最佳实践。

使用下面的方法可以将窗口强制移到顶部,并且不会像其他解决方案那样在更改时失效。

第 1 步:我为主客户端窗口创建了一个简单的状态管理器类。当使用直接绑定到我的窗口时,我使用 INotifyPropertyChanged 来保持属性同步。 (非常重要)

public class ClientStateManager : INotifyPropertyChanged
{
    #region Private Variables
    private bool isForceToTop;
    private bool isClientEnabled;
    #endregion

    #region Public Properties
    public bool IsForceToTop
    {
        get { return isForceToTop; }
        set
        {
            isForceToTop = value;
            NotifyPropertyChanged();
        }
    }
    public bool IsClientEnabled
    {
        get { return isClientEnabled; }
        set
        {
            isClientEnabled = value;
            NotifyPropertyChanged();
        }
    }       
    #endregion

    #region Private Methods
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    #region Public Methods
    public void Lock() => this.IsClientEnabled = false;
    public void UnLock() => this.IsClientEnabled = true;
    public void SetTop() => this.IsForceToTop = true;
    public void UnSetTop() => this.IsForceToTop = false;
    #endregion

    #region Public Events
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion
}

步骤 2.1:将我的状态管理器类添加到我的 ViewModel 中。 (MVVM)

  internal class MainWindowViewModel : INotifyPropertyChanged
  {
    #region Constructor
    public MainWindowViewModel() 
    {
        ClientStateManager = new ClientStateManager();
    }
    #endregion

    #region Public Properties  
    public ClientStateManager ClientStateManager { get; private set; }
    #endregion
  }

步骤 2.2:然后将窗口数据上下文设置为视图模型。

  private MainWindowViewModel model;
  private MainWindow()
  {
        InitializeComponent();
        this.model = new MainWindowViewModel();
        this.DataContext = model;
  }   

第 3 步:将数据绑定添加到窗口。

  <Window x:Class="Intouch_Work.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ojects="clr-namespace:Framework.Object;assembly=Framework"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"     
    mc:Ignorable="d"
    Title="Intouch" Height="800" Width="1100"
    x:Name="mainWindow"
    Topmost="{Binding Path=ClientStateManager.IsForceToTop, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">

现在您可以使用视图模型中初始化的状态管理器对象来管理窗口状态。您可以从状态管理器调用 SetTop() 将其向前推进,或调用 UnSetTop() 将其停止。 希望这可以帮助任何想要做同样事情的人。


2
投票

我需要类似的工业质量控制应用程序,其中非管理员操作员不应在应用程序运行时最小化或使用专用计算机上的任何其他内容,甚至不能打开桌面。我发现实现这一目标的最干净、最简单的方法是:


设置正确的
    Windows+D
  1. Width
    Height
    WindowStyle
    WindowState
    属性。
    处理一些相关事件:
  2. Topmost
  3. StateChanged
    Deactivated
    LostFocuse
    LostMouseCapture
    LostKeyboardFocus
    使用 
  4. PreviewLostKeyboardFocus
  5. 或自定义按钮处理关闭事件。
    
    
  6. 无需P/Invoke,完整代码如下:

ALT+F4

您还可以将其中一些放入 XAML 中:

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Loaded += OnLoaded; Closing += OnClosing; StateChanged += OnStateChanged; Deactivated += (sender, args) => Activate(); LostFocus += (sender, args) => Focus(); LostMouseCapture += (sender, args) => Mouse.Capture(this); LostKeyboardFocus += (sender, args) => Keyboard.Focus(this); PreviewLostKeyboardFocus += (sender, args) => Keyboard.Focus(this); } private void OnLoaded(object sender, RoutedEventArgs e) { Width = SystemParameters.PrimaryScreenWidth; Height = SystemParameters.PrimaryScreenHeight; WindowStyle = WindowStyle.None; WindowState = WindowState.Maximized; Topmost = true; // Other stuff here } private void OnClosing(object sender, CancelEventArgs e) { // You might want to allow only some users to close the app if (MessageBox.Show("Are you an admin?", "Admin Check", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No) e.Cancel = true; } private void OnStateChanged(object sender, EventArgs e) { if (WindowState == WindowState.Minimized) WindowState = WindowState.Maximized; } }



0
投票
这对我有用。希望这对某人有帮助。


<Window x:Class="FullScreen.MainWindow" ... Title="MainWindow" WindowState="Maximized" WindowStyle="None" Topmost="True"> <Grid> </Grid> </Window>



0
投票
我的这个

答案展示了如何在“一切”之上设置一个窗口,甚至是 Windows 的任务栏。

© www.soinside.com 2019 - 2024. All rights reserved.