WPF 中的 Windows 小工具 - 在“显示桌面”时显示已激活

发布于 2024-08-24 04:13:59 字数 571 浏览 6 评论 0原文

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

  • 无任务栏条目
  • 当您使用 alt+tab 时不显示 窗口
  • 不总是位于顶部,应用程序可以位于顶部
  • 执行“Aero Peek”时可见 执行“Aero Peek”
  • 时可见使用“显示桌面”/Windows+D

我已经能够完成前四个目标,但无法找到第五个问题的解决方案。我最接近的是使用 如何在 WPF 中进行 AppBar 对接(到屏幕边缘,如 WinAmp)?,但这会将应用程序变成“工具栏”,从而将应用程序从屏幕上的部分排除我的小工具 GUI 已放置。

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

I'm trying to create a "gadget" like application using WPF. The goal is to get the same behavior as a normal Windows 7 gadget:

  • No task-bar entry
  • Doesn't show up when you alt+tab windows
  • NOT always on top, applications can be on top
  • Visible while performing 'Aero Peek'
  • Visible while using 'Show desktop' / Windows+D

I've been able to accomplish the first four goals, but have been unable to find a solution to the fifth problem. The closest I've come is by using the utility class from How do you do AppBar docking (to screen edge, like WinAmp) in WPF?, but this turns the app into a "toolbar", thereby banishing applications from the part of the screen where my gadget GUI is placed.

I can see that similar questions has been asked previously on Stackoverflow, but those have died out before a solution was found. Posting anyway in the hope that there is now someone out there with the knowledge to solve this =)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

怪我闹别瞎闹 2024-08-31 04:13:59

尝试将 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 获取桌面窗口的句柄
  • 使用 ap/invoke 调用为 WndProc
  • Handle WM_ACTIVATE 或相应的 Windows 消息设置回调,并将不透明度设置回 1

Try setting Topmost to true, and when your application loses focus you could set Opacity to 0.

I did this 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>

I did this in C# for the Window:

protected override void OnActivated(EventArgs e)
{
    base.OnActivated(e);

    Opacity = 1;
}

protected override void OnDeactivated(EventArgs e)
{
    base.OnDeactivated(e);

    Opacity = 0;
}

This gets you part of the way there; you need a way to know if the desktop gets focus.

I bet you could do this by hooking into the WndProc event of the desktop window and looking for WM_ACTIVATE.

You could:

  • Call GetDesktopWindow to get the handle of the desktop window
  • Use a p/invoke call to set a callback for the WndProc
  • Handle WM_ACTIVATE or the appropriate windows message and set your Opacity back to 1
一场春暖 2024-08-31 04:13:59

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

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

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

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

这么多选择...

You can implement an actual Windows Gadget using WPF by creating an XBAP. Just add a gadget.xml file and an .html file that contains only an IFRAME that loads the XBAP. That way your WPF application will actually be a gadget and will automatically follow all the rules.

Another option is to use Windows Sidebar Styler. This requires additional software to be installed alongside yours but also allows you to do things you can't do inside the XBAP sandbox without code signing certificates, user authorizaiton, etc.

A third option is to create a gadget that uses something recognizable in the HTML (such as a particular background color), then when your .exe starts up, scan for a hWnd under Explorer that has the attributes you are looking for, inject yourself into the Explorer.exe process, and set your window as a child of it.

A variation of the third option is to not inject into Explorer.exe but rather maintain your Z Index and location (using SetWindowPos) to track the Z Index and location of the hWnd you found.

So many choices...

锦上情书 2024-08-31 04:13:59

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

在 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);

    }

I'll leave this here for future reference.

In Windows 10, parent your gadget window to Desktop using p/invoke. Will work with peek, show desktop and 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);

    }
拥抱我好吗 2024-08-31 04:13:59

实现类似“小工具”行为的一种解决方案是使您的窗口成为桌面的子窗口。这样,即使您按 Windows+D,您的窗口也始终在桌面上可见。
您可以在此处查看其操作方式:“桌面上”窗口

One solution to do achieve "gadget" like behavior, is to make your window a child of the desktop. In this way, your window is always visible on desktop even if you press Windows+D.
You can see how it's done here: Window "on desktop".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文