GUI/ShowDesktop.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
parent 179 a3530106314b
permissions -rw-r--r--
Converted project to VisualStudio 2012.
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
     1 /*
     2  
     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/.
     6  
     7   Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Runtime.InteropServices;
    13 using System.Windows.Forms;
    14 
    15 namespace OpenHardwareMonitor.GUI {
    16   public class ShowDesktop {
    17     private static ShowDesktop instance = new ShowDesktop();
    18 
    19     public delegate void ShowDesktopChangedEventHandler(bool showDesktop);
    20     
    21     private event ShowDesktopChangedEventHandler ShowDesktopChangedEvent;
    22 
    23     private System.Threading.Timer timer;
    24     private bool showDesktop = false;   
    25     private NativeWindow referenceWindow;
    26     private string referenceWindowCaption =
    27       "OpenHardwareMonitorShowDesktopReferenceWindow";
    28 
    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);
    40 
    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);
    44     }
    45 
    46     private void StartTimer() {
    47       timer.Change(0, 200);
    48     }
    49 
    50     private void StopTimer() {
    51       timer.Change(System.Threading.Timeout.Infinite,
    52         System.Threading.Timeout.Infinite);
    53     }
    54 
    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)
    59         return IntPtr.Zero;
    60 
    61       int shellId;
    62       NativeMethods.GetWindowThreadProcessId(shellWindow, out shellId);
    63 
    64       IntPtr workerWindow = IntPtr.Zero;
    65       while ((workerWindow = NativeMethods.FindWindowEx(
    66           IntPtr.Zero, workerWindow, "WorkerW", null)) != IntPtr.Zero) {
    67 
    68         int workerId;
    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)
    77               return workerWindow;
    78           }
    79         }
    80       }
    81       return IntPtr.Zero;
    82     }
    83 
    84     private void OnTimer(Object state) {
    85       bool showDesktopDetected;
    86 
    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;
    93       } else {
    94         // if there is no worker window, then nothing can hide the reference
    95         showDesktopDetected = false;
    96       }
    97 
    98       if (showDesktop != showDesktopDetected) {
    99         showDesktop = showDesktopDetected;
   100         if (ShowDesktopChangedEvent != null) {
   101           ShowDesktopChangedEvent(showDesktop);
   102         }
   103       }
   104     }
   105 
   106     public static ShowDesktop Instance {
   107       get { return instance; }
   108     }
   109 
   110     // notify when the "show desktop" mode is changed
   111     public event ShowDesktopChangedEventHandler ShowDesktopChanged {
   112       add {
   113         // start the monitor timer when someone is listening
   114         if (ShowDesktopChangedEvent == null)           
   115           StartTimer();
   116         ShowDesktopChangedEvent += value;
   117       }
   118       remove {
   119         ShowDesktopChangedEvent -= value;
   120         // stop the monitor timer if nobody is interested
   121         if (ShowDesktopChangedEvent == null)
   122           StopTimer();
   123       }
   124     }
   125 
   126     private static class NativeMethods {
   127       private const string USER = "user32.dll";
   128 
   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);
   132 
   133       [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
   134       public static extern IntPtr FindWindowEx(IntPtr hwndParent,
   135         IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
   136 
   137       [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
   138       public static extern IntPtr GetShellWindow();
   139 
   140       [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
   141       public static extern int GetWindowThreadProcessId(IntPtr hWnd,
   142         out int processId);
   143     }  
   144   }
   145 }