Fixed Issue 86.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Runtime.InteropServices;
13 using System.Windows.Forms;
15 namespace OpenHardwareMonitor.GUI {
16 public class ShowDesktop {
17 private static ShowDesktop instance = new ShowDesktop();
19 public delegate void ShowDesktopChangedEventHandler(bool showDesktop);
21 private event ShowDesktopChangedEventHandler ShowDesktopChangedEvent;
23 private System.Threading.Timer timer;
24 private bool showDesktop = false;
25 private NativeWindow referenceWindow;
26 private string referenceWindowCaption =
27 "OpenHardwareMonitorShowDesktopReferenceWindow";
29 private ShowDesktop() {
30 // create a reference window to detect show desktop
31 referenceWindow = new NativeWindow();
32 CreateParams cp = new CreateParams();
33 cp.ExStyle = GadgetWindow.WS_EX_TOOLWINDOW;
34 cp.Caption = referenceWindowCaption;
35 referenceWindow.CreateHandle(cp);
36 NativeMethods.SetWindowPos(referenceWindow.Handle,
37 GadgetWindow.HWND_BOTTOM, 0, 0, 0, 0, GadgetWindow.SWP_NOMOVE |
38 GadgetWindow.SWP_NOSIZE | GadgetWindow.SWP_NOACTIVATE |
39 GadgetWindow.SWP_NOSENDCHANGING);
41 // start a repeated timer to detect "Show Desktop" events
42 timer = new System.Threading.Timer(OnTimer, null,
43 System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
46 private void StartTimer() {
50 private void StopTimer() {
51 timer.Change(System.Threading.Timeout.Infinite,
52 System.Threading.Timeout.Infinite);
55 // the desktop worker window (if available) can hide the reference window
56 private IntPtr GetDesktopWorkerWindow() {
57 IntPtr shellWindow = NativeMethods.GetShellWindow();
58 if (shellWindow == IntPtr.Zero)
62 NativeMethods.GetWindowThreadProcessId(shellWindow, out shellId);
64 IntPtr workerWindow = IntPtr.Zero;
65 while ((workerWindow = NativeMethods.FindWindowEx(
66 IntPtr.Zero, workerWindow, "WorkerW", null)) != IntPtr.Zero) {
69 NativeMethods.GetWindowThreadProcessId(workerWindow, out workerId);
70 if (workerId == shellId) {
71 IntPtr window = NativeMethods.FindWindowEx(
72 workerWindow, IntPtr.Zero, "SHELLDLL_DefView", null);
73 if (window != IntPtr.Zero) {
74 IntPtr desktopWindow = NativeMethods.FindWindowEx(
75 window, IntPtr.Zero, "SysListView32", null);
76 if (desktopWindow != IntPtr.Zero)
84 private void OnTimer(Object state) {
85 bool showDesktopDetected;
87 IntPtr workerWindow = GetDesktopWorkerWindow();
88 if (workerWindow != IntPtr.Zero) {
89 // search if the reference window is behind the worker window
90 IntPtr reference = NativeMethods.FindWindowEx(
91 IntPtr.Zero, workerWindow, null, referenceWindowCaption);
92 showDesktopDetected = reference != IntPtr.Zero;
94 // if there is no worker window, then nothing can hide the reference
95 showDesktopDetected = false;
98 if (showDesktop != showDesktopDetected) {
99 showDesktop = showDesktopDetected;
100 if (ShowDesktopChangedEvent != null) {
101 ShowDesktopChangedEvent(showDesktop);
106 public static ShowDesktop Instance {
107 get { return instance; }
110 // notify when the "show desktop" mode is changed
111 public event ShowDesktopChangedEventHandler ShowDesktopChanged {
113 // start the monitor timer when someone is listening
114 if (ShowDesktopChangedEvent == null)
116 ShowDesktopChangedEvent += value;
119 ShowDesktopChangedEvent -= value;
120 // stop the monitor timer if nobody is interested
121 if (ShowDesktopChangedEvent == null)
126 private static class NativeMethods {
127 private const string USER = "user32.dll";
129 [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
130 public static extern bool SetWindowPos(IntPtr hWnd,
131 IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
133 [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
134 public static extern IntPtr FindWindowEx(IntPtr hwndParent,
135 IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
137 [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
138 public static extern IntPtr GetShellWindow();
140 [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
141 public static extern int GetWindowThreadProcessId(IntPtr hWnd,