openhardwaremonitor/GUI/ShowDesktop.cs

146 lines
5.1 KiB
C#
Raw Normal View History

2010-09-06 19:53:13 +00:00
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
2010-09-06 19:53:13 +00:00
Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
2010-09-06 19:53:13 +00:00
*/
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace OpenHardwareMonitor.GUI {
public class ShowDesktop {
private static ShowDesktop instance = new ShowDesktop();
public delegate void ShowDesktopChangedEventHandler(bool showDesktop);
private event ShowDesktopChangedEventHandler ShowDesktopChangedEvent;
private System.Threading.Timer timer;
private bool showDesktop = false;
private NativeWindow referenceWindow;
private string referenceWindowCaption =
"OpenHardwareMonitorShowDesktopReferenceWindow";
private ShowDesktop() {
// create a reference window to detect show desktop
referenceWindow = new NativeWindow();
CreateParams cp = new CreateParams();
cp.ExStyle = GadgetWindow.WS_EX_TOOLWINDOW;
cp.Caption = referenceWindowCaption;
referenceWindow.CreateHandle(cp);
NativeMethods.SetWindowPos(referenceWindow.Handle,
GadgetWindow.HWND_BOTTOM, 0, 0, 0, 0, GadgetWindow.SWP_NOMOVE |
GadgetWindow.SWP_NOSIZE | GadgetWindow.SWP_NOACTIVATE |
GadgetWindow.SWP_NOSENDCHANGING);
// start a repeated timer to detect "Show Desktop" events
timer = new System.Threading.Timer(OnTimer, null,
System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}
private void StartTimer() {
timer.Change(0, 200);
}
private void StopTimer() {
timer.Change(System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
}
// the desktop worker window (if available) can hide the reference window
private IntPtr GetDesktopWorkerWindow() {
IntPtr shellWindow = NativeMethods.GetShellWindow();
if (shellWindow == IntPtr.Zero)
return IntPtr.Zero;
int shellId;
NativeMethods.GetWindowThreadProcessId(shellWindow, out shellId);
IntPtr workerWindow = IntPtr.Zero;
while ((workerWindow = NativeMethods.FindWindowEx(
IntPtr.Zero, workerWindow, "WorkerW", null)) != IntPtr.Zero) {
int workerId;
NativeMethods.GetWindowThreadProcessId(workerWindow, out workerId);
if (workerId == shellId) {
IntPtr window = NativeMethods.FindWindowEx(
workerWindow, IntPtr.Zero, "SHELLDLL_DefView", null);
if (window != IntPtr.Zero) {
IntPtr desktopWindow = NativeMethods.FindWindowEx(
window, IntPtr.Zero, "SysListView32", null);
if (desktopWindow != IntPtr.Zero)
return workerWindow;
}
}
}
return IntPtr.Zero;
}
private void OnTimer(Object state) {
bool showDesktopDetected;
IntPtr workerWindow = GetDesktopWorkerWindow();
if (workerWindow != IntPtr.Zero) {
// search if the reference window is behind the worker window
IntPtr reference = NativeMethods.FindWindowEx(
IntPtr.Zero, workerWindow, null, referenceWindowCaption);
showDesktopDetected = reference != IntPtr.Zero;
2010-09-06 19:53:13 +00:00
} else {
// if there is no worker window, then nothing can hide the reference
showDesktopDetected = false;
}
if (showDesktop != showDesktopDetected) {
showDesktop = showDesktopDetected;
if (ShowDesktopChangedEvent != null) {
ShowDesktopChangedEvent(showDesktop);
}
}
}
public static ShowDesktop Instance {
get { return instance; }
}
// notify when the "show desktop" mode is changed
public event ShowDesktopChangedEventHandler ShowDesktopChanged {
add {
// start the monitor timer when someone is listening
if (ShowDesktopChangedEvent == null)
StartTimer();
ShowDesktopChangedEvent += value;
}
remove {
ShowDesktopChangedEvent -= value;
// stop the monitor timer if nobody is interested
if (ShowDesktopChangedEvent == null)
StopTimer();
}
}
private static class NativeMethods {
private const string USER = "user32.dll";
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
public static extern bool SetWindowPos(IntPtr hWnd,
IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr GetShellWindow();
[DllImport(USER, CallingConvention = CallingConvention.Winapi)]
public static extern int GetWindowThreadProcessId(IntPtr hWnd,
out int processId);
}
}
}