Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows gadget in WPF - show while "Show desktop" is activated

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 =)

like image 996
Jannick Avatar asked Mar 08 '10 22:03

Jannick


2 Answers

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
like image 52
jonathanpeppers Avatar answered Oct 03 '22 06:10

jonathanpeppers


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...

like image 25
Ray Burns Avatar answered Oct 03 '22 08:10

Ray Burns