WPF窗口置顶

2022-04-19 08:57:06 浏览数 (2)

前言

窗口置顶有两种情况

  • 应用内的窗口置顶
  • 应用外的窗口置顶

一般我们这样设置窗口置顶

代码语言:javascript复制
<Window Topmost="True"></Window>

但是如果其他程序也置顶,后来的置顶就会覆盖之前的置顶,所以我们要保证我们的窗口永远置顶就要做如下设置。

窗口永远置顶

Deactivated(推荐)

这不会在100%的时间内起作用,但它会在某种程度上改善这种情况.您可以Topmost = trueWindow.Deactivated事件的处理程序中设置:

Window.Deactivated在窗口成为后台窗口时发生。

XAML:

代码语言:javascript复制
<Window 
        Title="工具条"
        Width="276"
        Height="728" 
        Deactivated="Window_Deactivated"
        >
</Window>

代码

代码语言:javascript复制
private void Window_Deactivated(object sender, EventArgs e)
{
  Window window = (Window)sender;
  window.Topmost = true;
  Console.WriteLine("工具条窗口置顶");
}

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

停用窗口后 (成为后台窗口) :

  • 用户切换到当前应用程序中的另一个窗口。
  • 用户使用 ALT TAB 或使用任务管理器切换到另一个应用程序中的窗口。
  • 用户单击另一应用程序中窗口的任务栏按钮。

Windows,需要通过处理事件来检测它们何时变为停用状态 Deactivated 。

第一次停用窗口后,它可能会在其生存期内重新激活和停用多次。 如果应用程序的行为或状态取决于其激活状态,它可以 IsActive 进行检查以确定它所在的激活状态。

应用程序也可以是 Deactivated 。

PreviewLostKeyboardFocus

要使其保持在顶部,您只需设置失去焦点事件以使其回到顶部。

PreviewLostKeyboardFocus:当元素正在失去键盘焦点时发生

XAML:

代码语言:javascript复制
<Window 
        Title="工具条"
        Width="276"
        Height="728" 
        PreviewLostKeyboardFocus="Window_PreviewLostKeyboardFocus"
        >
</Window>

背后的代码:

代码语言:javascript复制
private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
  Window window = (Window)sender;
  window.Topmost = true;
  Console.WriteLine("工具条窗口置顶");
}

外部应用窗口置顶

工具类

代码语言:javascript复制
public class ZWinUtil
{
  #region ShowWindow 方法窗体状态的参数枚举

    /// <summary>
    /// 隐藏窗口并激活其他窗口
    /// </summary>
    private const int SW_HIDE = 0;

  /// <summary>
  /// 激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志
  /// </summary>
  private const int SW_SHOWNORMAL = 1;

  /// <summary>
  /// 激活窗口并将其最小化
  /// </summary>
  private const int SW_SHOWMINIMIZED = 2;

  /// <summary>
  /// 激活窗口并将其最大化
  /// </summary>
  private const int SW_SHOWMAXIMIZED = 3;

  /// <summary>
  /// 以窗口最近一次的大小和状态显示窗口。此值与SW_SHOWNORMAL相似,只是窗口没有被激活
  /// </summary>
  private const int SW_SHOWNOACTIVATE = 4;

  /// <summary>
  /// 在窗口原来的位置以原来的尺寸激活和显示窗口
  /// </summary>
  private const int SW_SHOW = 5;

  /// <summary>
  /// 最小化指定的窗口并且激活在Z序中的下一个顶层窗口
  /// </summary>
  private const int SW_MINIMIZE = 6;

  /// <summary>
  /// 最小化的方式显示窗口,此值与SW_SHOWMINIMIZED相似,只是窗口没有被激活
  /// </summary>
  private const int SW_SHOWMINNOACTIVE = 7;

  /// <summary>
  /// 以窗口原来的状态显示窗口。此值与SW_SHOW相似,只是窗口没有被激活
  /// </summary>
  private const int SW_SHOWNA = 8;

  /// <summary>
  /// 激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志
  /// </summary>
  private const int SW_RESTORE = 9;

  /// <summary>
  /// 依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的
  /// </summary>
  private const int SW_SHOWDEFAULT = 10;

  /// <summary>
  /// 最小化窗口,即使拥有窗口的线程被挂起也会最小化。在从其他线程最小化窗口时才使用这个参数
  /// </summary>
  private const int SW_FORCEMINIMIZE = 11;

  #endregion ShowWindow 方法窗体状态的参数枚举

    //窗体置顶
    private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);

  //取消窗体置顶
  private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);

  //不调整窗体位置
  private const uint SWP_NOMOVE = 0x0002;

  //不调整窗体大小
  private const uint SWP_NOSIZE = 0x0001;

  [DllImport("User32.dll", EntryPoint = "FindWindow")]
  private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

  [DllImport("user32.dll")]
  private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

  [DllImport("user32.dll", EntryPoint = "ShowWindow")]
  private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

  /// <summary>
  /// 使窗体置顶
  /// </summary>
  /// <param name="Name">需要置顶的窗体的名字</param>
  public static void SetTop(string Name)
  {
    IntPtr CustomBar = FindWindow(null, Name);
    if (CustomBar != null)
    {
      SetWindowPos(CustomBar, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    }
  }

  /// <summary>
  /// 取消窗体置顶
  /// </summary>
  /// <param name="Name">需要置顶的窗体的名字</param>
  public static void SetTopNO(string Name)
  {
    IntPtr CustomBar = FindWindow(null, Name);
    if (CustomBar != null)
    {
      SetWindowPos(CustomBar, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    }
  }

  /// <summary>
  /// 显示窗口
  /// </summary>
  /// <param name="Name"></param>
  public static void SetWinShow(string Name)
  {
    IntPtr CustomBar = FindWindow(null, Name);
    if (CustomBar != null)
    {
      ShowWindow(CustomBar, SW_SHOW);
    }
  }

  /// <summary>
  /// 隐藏窗口
  /// </summary>
  /// <param name="Name"></param>
  public static void SetWinHide(string Name)
  {
    IntPtr CustomBar = FindWindow(null, Name);
    if (CustomBar != null)
    {
      ShowWindow(CustomBar, SW_HIDE);
    }
  }
}

调用

代码语言:javascript复制
ZWinUtil.SetWinShow("文件资源管理器");
ZWinUtil.SetTop("文件资源管理器");
ZWinUtil.SetWinHide("文件资源管理器");

程序内获取当前窗口句柄

代码语言:javascript复制
IntPtr handle;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
  handle = new WindowInteropHelper(this).Handle;
}

0 人点赞