WPF永远在顶部

时间:2013-11-18 14:39:07

标签: c# wpf topmost

即使其他应用程序在Fullscreen上运行,是否可以使窗口始终保持在顶部?我正在使用TopMost = true但是当其他应用程序在全屏幕上运行时,我的内容变得不可见。顺便说一下,这是WindowStyle = None窗口。

修改:不要让其他窗口最小化课程

7 个答案:

答案 0 :(得分:43)

这在100%的时间都不会起作用,但它会在一定程度上改善这种情况。您可以在Window.Deactivated事件的处理程序中设置Topmost = true

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

只要您的应用程序失去焦点(通常在另一个应用程序请求为Deactivated时),就会调用Topmost事件,因此这将在此之后重置您的应用程序。

答案 1 :(得分:11)

从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();

Original post from MSDN

答案 2 :(得分:2)

如果您希望您的应用程序始终处于最佳状态(包括Windows 8中的启动界面,以前称为" Metro"),那么您可以指定UiAccess =" True"在您的清单文件中。这通常由辅助功能应用程序(如屏幕键盘)使用。

从记忆中你需要做3件事;

  1. 请求UiAccess =" True"
  2. 使用认可的证书在您的应用程序的exe文件上签名。我从Certum获得了免费的代码签名证书,因为我的项目是开源。
  3. 将您的应用程序安装到"可信位置",在我的例子中是程序文件目录。没有官方定义" Trusted Location"我能找到。

答案 3 :(得分:2)

所以我最近遇到了同样的要求。似乎最受好评的答案以及第二个答案对我来说都不合适。我找到了一个似乎完美无缺的解决方案,并且有点坚持使用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}">

现在,您可以使用在View Model中初始化的状态管理器对象来管理窗口状态。你可以从状态管理器调用SetTop()来推进它,或者UnSetTop()来阻止它。 希望这有助于任何想要做同样事情的人。

答案 4 :(得分:2)

上面的解决方案对我来说都不起作用,所以这就是我最终要做的事情。它对我来说很完美。

基本上,为了让它保持在最前面,你只需设置失去焦点事件,使其回到顶部。

XAML:

PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus"

代码背后:

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

答案 5 :(得分:1)

我有一个主窗口,我想要保持一切(如果用户检查&#34;总是在顶部&#34;。

这对我有用。希望这有助于某人。

        // If we want main to stay on top, we set the rest of the menus to Not be top 
        if (mnuViewMainWindowAlwaysOnTopo.IsChecked)
        {
            this.Topmost = true;
            foreach (Window window in Application.Current.Windows)
            {
                // Don't change for main window
                if (window.GetType().Name != this.GetType().Name)
                {
                    window.Topmost = false;
                }
            }
        }
        else
        {
            this.Topmost = false;
        }

答案 6 :(得分:0)

对于工业质量控制应用程序,我需要类似的东西,在该应用程序运行时,非管理员操作员不应该能够最小化或使用专用计算机上的任何其他东西,甚至不能Windows+D调出桌面。我发现实现这一目标的最简洁、最简单的方法是:

  1. 设置正确的 WidthHeightWindowStyleWindowStateTopmost 属性。
  2. 处理一些相关事件:StateChangedDeactivatedLostFocuseLostMouseCaptureLostKeyboardFocusPreviewLostKeyboardFocus
  3. 使用 ALT+F4 或自定义按钮处理关闭事件)。

不需要P/Invoke,完整代码如下:

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;
        }
    }

您也可以将其中的一些放在 XAML 中:

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