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.
moel@176
     1
/*
moel@176
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@176
     6
 
moel@344
     7
  Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	
moel@176
     9
*/
moel@176
    10
moel@176
    11
using System;
moel@176
    12
using System.Runtime.InteropServices;
moel@176
    13
using System.Windows.Forms;
moel@176
    14
moel@176
    15
namespace OpenHardwareMonitor.GUI {
moel@176
    16
  public class ShowDesktop {
moel@176
    17
    private static ShowDesktop instance = new ShowDesktop();
moel@176
    18
moel@176
    19
    public delegate void ShowDesktopChangedEventHandler(bool showDesktop);
moel@176
    20
    
moel@176
    21
    private event ShowDesktopChangedEventHandler ShowDesktopChangedEvent;
moel@176
    22
moel@176
    23
    private System.Threading.Timer timer;
moel@176
    24
    private bool showDesktop = false;   
moel@176
    25
    private NativeWindow referenceWindow;
moel@176
    26
    private string referenceWindowCaption =
moel@176
    27
      "OpenHardwareMonitorShowDesktopReferenceWindow";
moel@176
    28
moel@176
    29
    private ShowDesktop() {
moel@176
    30
      // create a reference window to detect show desktop
moel@176
    31
      referenceWindow = new NativeWindow();
moel@176
    32
      CreateParams cp = new CreateParams();
moel@176
    33
      cp.ExStyle = GadgetWindow.WS_EX_TOOLWINDOW;
moel@176
    34
      cp.Caption = referenceWindowCaption;
moel@176
    35
      referenceWindow.CreateHandle(cp);
moel@176
    36
      NativeMethods.SetWindowPos(referenceWindow.Handle, 
moel@176
    37
        GadgetWindow.HWND_BOTTOM, 0, 0, 0, 0, GadgetWindow.SWP_NOMOVE | 
moel@176
    38
        GadgetWindow.SWP_NOSIZE | GadgetWindow.SWP_NOACTIVATE | 
moel@176
    39
        GadgetWindow.SWP_NOSENDCHANGING);
moel@176
    40
moel@176
    41
      // start a repeated timer to detect "Show Desktop" events 
moel@176
    42
      timer = new System.Threading.Timer(OnTimer, null,
moel@176
    43
        System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
moel@176
    44
    }
moel@176
    45
moel@176
    46
    private void StartTimer() {
moel@176
    47
      timer.Change(0, 200);
moel@176
    48
    }
moel@176
    49
moel@176
    50
    private void StopTimer() {
moel@176
    51
      timer.Change(System.Threading.Timeout.Infinite,
moel@176
    52
        System.Threading.Timeout.Infinite);
moel@176
    53
    }
moel@176
    54
moel@176
    55
    // the desktop worker window (if available) can hide the reference window
moel@176
    56
    private IntPtr GetDesktopWorkerWindow() {
moel@176
    57
      IntPtr shellWindow = NativeMethods.GetShellWindow();
moel@176
    58
      if (shellWindow == IntPtr.Zero)
moel@176
    59
        return IntPtr.Zero;
moel@176
    60
moel@176
    61
      int shellId;
moel@176
    62
      NativeMethods.GetWindowThreadProcessId(shellWindow, out shellId);
moel@176
    63
moel@176
    64
      IntPtr workerWindow = IntPtr.Zero;
moel@176
    65
      while ((workerWindow = NativeMethods.FindWindowEx(
moel@176
    66
          IntPtr.Zero, workerWindow, "WorkerW", null)) != IntPtr.Zero) {
moel@176
    67
moel@176
    68
        int workerId;
moel@176
    69
        NativeMethods.GetWindowThreadProcessId(workerWindow, out workerId);
moel@176
    70
        if (workerId == shellId) {
moel@176
    71
          IntPtr window = NativeMethods.FindWindowEx(
moel@176
    72
            workerWindow, IntPtr.Zero, "SHELLDLL_DefView", null);
moel@176
    73
          if (window != IntPtr.Zero) {
moel@176
    74
            IntPtr desktopWindow = NativeMethods.FindWindowEx(
moel@176
    75
              window, IntPtr.Zero, "SysListView32", null);
moel@176
    76
            if (desktopWindow != IntPtr.Zero)
moel@176
    77
              return workerWindow;
moel@176
    78
          }
moel@176
    79
        }
moel@176
    80
      }
moel@176
    81
      return IntPtr.Zero;
moel@176
    82
    }
moel@176
    83
moel@176
    84
    private void OnTimer(Object state) {
moel@176
    85
      bool showDesktopDetected;
moel@176
    86
moel@176
    87
      IntPtr workerWindow = GetDesktopWorkerWindow();
moel@176
    88
      if (workerWindow != IntPtr.Zero) {
moel@176
    89
        // search if the reference window is behind the worker window
moel@176
    90
        IntPtr reference = NativeMethods.FindWindowEx(
moel@176
    91
          IntPtr.Zero, workerWindow, null, referenceWindowCaption);
moel@179
    92
        showDesktopDetected = reference != IntPtr.Zero;
moel@176
    93
      } else {
moel@176
    94
        // if there is no worker window, then nothing can hide the reference
moel@176
    95
        showDesktopDetected = false;
moel@176
    96
      }
moel@176
    97
moel@176
    98
      if (showDesktop != showDesktopDetected) {
moel@176
    99
        showDesktop = showDesktopDetected;
moel@176
   100
        if (ShowDesktopChangedEvent != null) {
moel@176
   101
          ShowDesktopChangedEvent(showDesktop);
moel@176
   102
        }
moel@176
   103
      }
moel@176
   104
    }
moel@176
   105
moel@176
   106
    public static ShowDesktop Instance {
moel@176
   107
      get { return instance; }
moel@176
   108
    }
moel@176
   109
moel@176
   110
    // notify when the "show desktop" mode is changed
moel@176
   111
    public event ShowDesktopChangedEventHandler ShowDesktopChanged {
moel@176
   112
      add {
moel@176
   113
        // start the monitor timer when someone is listening
moel@176
   114
        if (ShowDesktopChangedEvent == null)           
moel@176
   115
          StartTimer();
moel@176
   116
        ShowDesktopChangedEvent += value;
moel@176
   117
      }
moel@176
   118
      remove {
moel@176
   119
        ShowDesktopChangedEvent -= value;
moel@176
   120
        // stop the monitor timer if nobody is interested
moel@176
   121
        if (ShowDesktopChangedEvent == null)
moel@176
   122
          StopTimer();
moel@176
   123
      }
moel@176
   124
    }
moel@176
   125
moel@176
   126
    private static class NativeMethods {
moel@176
   127
      private const string USER = "user32.dll";
moel@176
   128
moel@176
   129
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   130
      public static extern bool SetWindowPos(IntPtr hWnd,
moel@176
   131
        IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
moel@176
   132
moel@176
   133
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   134
      public static extern IntPtr FindWindowEx(IntPtr hwndParent,
moel@176
   135
        IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
moel@176
   136
moel@176
   137
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   138
      public static extern IntPtr GetShellWindow();
moel@176
   139
moel@176
   140
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   141
      public static extern int GetWindowThreadProcessId(IntPtr hWnd,
moel@176
   142
        out int processId);
moel@176
   143
    }  
moel@176
   144
  }
moel@176
   145
}