【问题标题】:Windows gadget in WPF - show while "Show desktop" is activatedWPF 中的 Windows 小工具 - 在“显示桌面”激活时显示
【发布时间】:2011-01-25 04:48:17
【问题描述】:

我正在尝试使用 WPF 创建一个类似“小工具”的应用程序。目标是获得与普通 Windows 7 小工具相同的行为:

  • 没有任务栏条目
  • 当您 alt+tab 窗口时不显示
  • 并不总是在最前面,应用程序可以在最前面
  • 在执行“Aero Peek”时可见
  • 使用“显示桌面”/Windows+D 时可见

我已经能够完成前四个目标,但无法找到第五个问题的解决方案。我最接近的是使用来自How do you do AppBar docking (to screen edge, like WinAmp) in WPF? 的实用程序类,但这会将应用程序变成“工具栏”,从而将应用程序从放置我的小工具 GUI 的屏幕部分中排除。

我可以看到以前在 Stackoverflow 上也有人问过类似的问题,但在找到解决方案之前这些问题就已经消失了。无论如何发布,希望现在有人有知识来解决这个问题=)

【问题讨论】:

    标签: c# wpf windows-desktop-gadgets


    【解决方案1】:

    我将把它留在这里以供将来参考。

    在 Windows 10 中,使用 p/invoke 将您的小工具窗口设置为桌面。将与 peek、显示桌面和 Win + D 一起使用

        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
        public static void SetOnDesktop(Window window)
        {
            IntPtr hWnd = new WindowInteropHelper(window).Handle;
            IntPtr hWndProgMan = FindWindow("Progman", "Program Manager");
            SetParent(hWnd, hWndProgMan);
    
        }
    

    【讨论】:

      【解决方案2】:

      实现类似“小工具”行为的一种解决方案是让您的窗口成为桌面的子窗口。这样,即使您按 Windows+D,您的窗口也始终在桌面上可见。 你可以在这里看到它是如何完成的:Window "on desktop"

      【讨论】:

        【解决方案3】:

        您可以通过创建 XBAP 来使用 WPF 实现实际的 Windows 小工具。只需添加一个 gadget.xml 文件和一个仅包含加载 XBAP 的 IFRAME 的 .html 文件。这样,您的 WPF 应用程序实际上就是一个小工具,并且会自动遵循所有规则。

        另一种选择是使用Windows Sidebar Styler。这需要与您的软件一起安装其他软件,但还允许您在没有代码签名证书、用户授权等的情况下执行您在 XBAP 沙箱中无法执行的操作。

        第三种选择是创建一个使用 HTML 中可识别的东西(例如特定背景颜色)的小工具,然后当您的 .exe 启动时,在资源管理器下扫描具有您正在寻找的属性的 hWnd,将自己注入到 Explorer.exe 进程中,并将您的窗口设置为它的子窗口。

        第三个选项的一个变体是不注入 Explorer.exe,而是维护您的 Z 索引和位置(使用 SetWindowPos)来跟踪您找到的 hWnd 的 Z 索引和位置。

        这么多选择...

        【讨论】:

          【解决方案4】:

          尝试将 Topmost 设置为 true,当您的应用程序失去焦点时,您可以将 Opacity 设置为 0。

          我做了这个 Xaml:

          <Window x:Class="OpacTest.MainWindow"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  Title="MainWindow" Topmost="True" Background="Transparent" ShowInTaskbar="False" AllowsTransparency="True" WindowStyle="None" Width="400" Height="300">
              <Grid>
                 <Border Background="Black" CornerRadius="5" />
              </Grid>
          </Window>
          

          我在 C# 中为 Window 做了这个:

          protected override void OnActivated(EventArgs e)
          {
              base.OnActivated(e);
          
              Opacity = 1;
          }
          
          protected override void OnDeactivated(EventArgs e)
          {
              base.OnDeactivated(e);
          
              Opacity = 0;
          }
          

          这会让你在那儿走上一段路;您需要一种方法来了解桌面是否获得焦点。

          我敢打赌,您可以通过挂接到桌面窗口的 WndProc 事件并查找 WM_ACTIVATE 来做到这一点。

          你可以:

          • 调用GetDesktopWindow获取桌面窗口句柄
          • 使用 p/invoke 调用为 WndProc 设置回调
          • 处理 WM_ACTIVATE 或适当的 windows 消息并将不透明度设置回 1

          【讨论】:

            猜你喜欢
            • 2011-07-25
            • 1970-01-01
            • 2021-02-26
            • 2020-01-22
            • 1970-01-01
            • 1970-01-01
            • 2011-01-04
            • 2017-06-17
            • 2017-07-18
            相关资源
            最近更新 更多