# HG changeset patch # User moel.mich # Date 1283802793 0 # Node ID c16fd81b520ab323f96346c8ea1f2f9c0fd63b01 # Parent e4ee19d583bdfe84212e90ffcf35c7a02309d8cf Added a desktop gadget implementation. diff -r e4ee19d583bd -r c16fd81b520a GUI/Gadget.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GUI/Gadget.cs Mon Sep 06 19:53:13 2010 +0000 @@ -0,0 +1,172 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Drawing.Text; +using System.Windows.Forms; + +namespace OpenHardwareMonitor.GUI { + public abstract class Gadget : IDisposable { + + private GadgetWindow window; + private Bitmap buffer; + private Graphics graphics; + + public Gadget() { + this.window = new GadgetWindow(); + CreateBuffer(); + } + + public void Dispose() { + this.graphics.Dispose(); + this.buffer.Dispose(); + } + + public Point Location { + get { + return window.Location; + } + set { + window.Location = value; + } + } + + public event EventHandler LocationChanged { + add { + window.LocationChanged += value; + } + remove { + window.LocationChanged -= value; + } + } + + protected virtual Size Size { + get { + return window.Size; + } + set { + if (window.Size != value) { + DisposeBuffer(); + this.window.Size = value; + CreateBuffer(); + } + } + } + + public byte Opacity { + get { + return window.Opacity; + } + set { + window.Opacity = value; + } + } + + public bool LockPosition { + get { + return window.LockPosition; + } + set { + window.LockPosition = value; + } + } + + public bool AlwaysOnTop { + get { + return window.AlwaysOnTop; + } + set { + window.AlwaysOnTop = value; + } + } + + public ContextMenu ContextMenu { + get { + return window.ContextMenu; + } + set { + window.ContextMenu = value; + } + } + + private void CreateBuffer() { + this.buffer = new Bitmap(window.Size.Width, window.Size.Height, + PixelFormat.Format32bppArgb); + this.graphics = Graphics.FromImage(this.buffer); + if (Environment.OSVersion.Version.Major > 5) { + this.graphics.TextRenderingHint = TextRenderingHint.SystemDefault; + this.graphics.SmoothingMode = SmoothingMode.HighQuality; + } + } + + private void DisposeBuffer() { + if (buffer != null) { + this.buffer.Dispose(); + this.buffer = null; + } + if (graphics != null) { + this.graphics.Dispose(); + this.graphics = null; + } + } + + public bool Visible { + get { + return window.Visible; + } + set { + if (value != window.Visible) { + if (value) + Redraw(); + window.Visible = value; + } + } + } + + public void Redraw() { + OnPaint(new PaintEventArgs(graphics, + new Rectangle(Point.Empty, window.Size))); + window.Update(buffer); + } + + protected abstract void OnPaint(PaintEventArgs e); + + } +} diff -r e4ee19d583bd -r c16fd81b520a GUI/GadgetWindow.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GUI/GadgetWindow.cs Mon Sep 06 19:53:13 2010 +0000 @@ -0,0 +1,423 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Drawing; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace OpenHardwareMonitor.GUI { + public class GadgetWindow : NativeWindow { + + private bool visible = false; + private bool lockPosition = false; + private bool alwaysOnTop = false; + private byte opacity = 255; + private Point location = new Point(100, 100); + private Size size = new Size(130, 84); + private ContextMenu contextMenu = null; + private MethodInfo commandDispatch; + + public GadgetWindow() { + Type commandType = + typeof(Form).Assembly.GetType("System.Windows.Forms.Command"); + commandDispatch = commandType.GetMethod("DispatchID", + BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, + null, new Type[]{ typeof(int) }, null); + + this.CreateHandle(CreateParams); + + // move window to the bottom + MoveToBottom(Handle); + + // prevent window from fading to a glass sheet when peek is invoked + try { + bool value = true; + int r = NativeMethods.DwmSetWindowAttribute(Handle, + WindowAttribute.DWMWA_EXCLUDED_FROM_PEEK, ref value, + Marshal.SizeOf(value)); + } catch (DllNotFoundException) { } catch (EntryPointNotFoundException) { } + } + + private void ShowDesktopChanged(bool showDesktop) { + if (showDesktop) { + MoveToTopMost(Handle); + } else { + MoveToBottom(Handle); + } + } + + private void MoveToBottom(IntPtr handle) { + NativeMethods.SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + } + + private void MoveToTopMost(IntPtr handle) { + NativeMethods.SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + } + + private void ShowContextMenu(Point position) { + NativeMethods.TrackPopupMenuEx(contextMenu.Handle, + TPM_RIGHTBUTTON | TPM_VERTICAL, position.X, + position.Y, Handle, IntPtr.Zero); + } + + protected virtual CreateParams CreateParams { + get { + CreateParams cp = new CreateParams(); + cp.Width = size.Width; + cp.Height = size.Height; + cp.X = location.X; + cp.Y = location.Y; + cp.ExStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW; + return cp; + } + } + + protected override void WndProc(ref Message message) { + switch (message.Msg) { + case WM_COMMAND: + // need to dispatch the message for the context menu + if (message.LParam == IntPtr.Zero) + commandDispatch.Invoke(null, new object[] { + message.WParam.ToInt32() & 0xFFFF }); + break; + case WM_NCHITTEST: + // all pixels of the form belong to the caption + message.Result = HTCAPTION; + break; + case WM_NCLBUTTONDBLCLK: + message.Result = IntPtr.Zero; break; + case WM_NCRBUTTONDOWN: + message.Result = IntPtr.Zero; break; + case WM_NCRBUTTONUP: + if (contextMenu != null) + ShowContextMenu(new Point( + (int)((uint)message.LParam & 0xFFFF), + (int)(((uint)message.LParam >>16) & 0xFFFF))); + message.Result = IntPtr.Zero; + break; + case WM_WINDOWPOSCHANGING: + WindowPos wp = (WindowPos)Marshal.PtrToStructure( + message.LParam, typeof(WindowPos)); + + // add the nomove flag if position is locked + if (lockPosition) + wp.flags |= SWP_NOMOVE; + + // prevent the window from leaving the screen + if ((wp.flags & SWP_NOMOVE) == 0) { + Rectangle rect = Screen.GetWorkingArea(new Point(wp.x, wp.y)); + const int margin = 20; + wp.x = Math.Max(wp.x, rect.Left - wp.cx + margin); + wp.x = Math.Min(wp.x, rect.Right - margin); + wp.y = Math.Max(wp.y, rect.Top - wp.cy + margin); + wp.y = Math.Min(wp.y, rect.Bottom - margin); + + // raise the event if location changed + if (location.X != wp.x || location.Y != wp.y) { + location = new Point(wp.x, wp.y); + if (LocationChanged != null) + LocationChanged(this, EventArgs.Empty); + } + } + + Marshal.StructureToPtr(wp, message.LParam, false); + message.Result = IntPtr.Zero; + break; + default: + base.WndProc(ref message); break; + } + } + + private BlendFunction CreateBlendFunction() { + BlendFunction blend = new BlendFunction(); + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + blend.SourceConstantAlpha = opacity; + blend.AlphaFormat = AC_SRC_ALPHA; + return blend; + } + + public void Update(Bitmap bitmap) { + IntPtr screen = NativeMethods.GetDC(IntPtr.Zero); + IntPtr memory = NativeMethods.CreateCompatibleDC(screen); + IntPtr newHBitmap = IntPtr.Zero; + IntPtr oldHBitmap = IntPtr.Zero; + + try { + newHBitmap = bitmap.GetHbitmap(Color.Black); + oldHBitmap = NativeMethods.SelectObject(memory, newHBitmap); + + Size size = bitmap.Size; + Point pointSource = Point.Empty; + Point topPos = Location; + + BlendFunction blend = CreateBlendFunction(); + NativeMethods.UpdateLayeredWindow(Handle, screen, ref topPos, + ref size, memory, ref pointSource, 0, ref blend, ULW_ALPHA); + } finally { + NativeMethods.ReleaseDC(IntPtr.Zero, screen); + if (newHBitmap != IntPtr.Zero) { + NativeMethods.SelectObject(memory, oldHBitmap); + NativeMethods.DeleteObject(newHBitmap); + } + NativeMethods.DeleteDC(memory); + } + } + + public byte Opacity { + get { + return opacity; + } + set { + if (opacity != value) { + opacity = value; + BlendFunction blend = CreateBlendFunction(); + NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero, + IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, ref blend, ULW_ALPHA); + } + } + } + + public bool Visible { + get { + return visible; + } + set { + if (visible != value) { + visible = value; + NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | + (value ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); + if (value) + ShowDesktop.Instance.ShowDesktopChanged += ShowDesktopChanged; + else + ShowDesktop.Instance.ShowDesktopChanged -= ShowDesktopChanged; + } + } + } + + // if locked, the window can not be moved + public bool LockPosition { + get { + return lockPosition; + } + set { + lockPosition = value; + } + } + + public bool AlwaysOnTop { + get { + return alwaysOnTop; + } + set { + if (value != alwaysOnTop) { + alwaysOnTop = value; + if (alwaysOnTop) { + ShowDesktop.Instance.ShowDesktopChanged -= ShowDesktopChanged; + MoveToTopMost(Handle); + } else { + MoveToBottom(Handle); + ShowDesktop.Instance.ShowDesktopChanged += ShowDesktopChanged; + } + } + } + } + + public Size Size { + get { + return size; + } + set { + if (size != value) { + size = value; + NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 0, 0, size.Width, + size.Height, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | + SWP_NOSENDCHANGING); + } + } + } + + public Point Location { + get { + return location; + } + set { + NativeMethods.SetWindowPos(Handle, IntPtr.Zero, value.X, value.Y, 0, + 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING); + location = value; + if (LocationChanged != null) + LocationChanged(this, EventArgs.Empty); + } + } + + public event EventHandler LocationChanged; + + public ContextMenu ContextMenu { + get { + return contextMenu; + } + set { + this.contextMenu = value; + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct BlendFunction { + public byte BlendOp; + public byte BlendFlags; + public byte SourceConstantAlpha; + public byte AlphaFormat; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct WindowPos { + public IntPtr hwnd; + public IntPtr hwndInsertAfter; + public int x; + public int y; + public int cx; + public int cy; + public uint flags; + } + + public static readonly IntPtr HWND_BOTTOM = (IntPtr)1; + public static readonly IntPtr HWND_TOPMOST = (IntPtr)(-1); + + public const int WS_EX_LAYERED = 0x00080000; + public const int WS_EX_TOOLWINDOW = 0x00000080; + + public const uint SWP_NOSIZE = 0x0001; + public const uint SWP_NOMOVE = 0x0002; + public const uint SWP_NOACTIVATE = 0x0010; + public const uint SWP_HIDEWINDOW = 0x0080; + public const uint SWP_SHOWWINDOW = 0x0040; + public const uint SWP_NOZORDER = 0x0004; + public const uint SWP_NOSENDCHANGING = 0x0400; + + public const int ULW_COLORKEY = 0x00000001; + public const int ULW_ALPHA = 0x00000002; + public const int ULW_OPAQUE = 0x00000004; + + public const byte AC_SRC_OVER = 0x00; + public const byte AC_SRC_ALPHA = 0x01; + + public const int WM_NCHITTEST = 0x0084; + public const int WM_NCLBUTTONDBLCLK = 0x00A3; + public const int WM_NCLBUTTONDOWN = 0x00A1; + public const int WM_NCLBUTTONUP = 0x00A2; + public const int WM_NCRBUTTONDOWN = 0x00A4; + public const int WM_NCRBUTTONUP = 0x00A5; + public const int WM_WINDOWPOSCHANGING = 0x0046; + public const int WM_COMMAND = 0x0111; + + public const int TPM_RIGHTBUTTON = 0x0002; + public const int TPM_VERTICAL = 0x0040; + + public readonly IntPtr HTCAPTION = (IntPtr)2; + + private enum WindowAttribute : int { + DWMWA_NCRENDERING_ENABLED = 1, + DWMWA_NCRENDERING_POLICY, + DWMWA_TRANSITIONS_FORCEDISABLED, + DWMWA_ALLOW_NCPAINT, + DWMWA_CAPTION_BUTTON_BOUNDS, + DWMWA_NONCLIENT_RTL_LAYOUT, + DWMWA_FORCE_ICONIC_REPRESENTATION, + DWMWA_FLIP3D_POLICY, + DWMWA_EXTENDED_FRAME_BOUNDS, + DWMWA_HAS_ICONIC_BITMAP, + DWMWA_DISALLOW_PEEK, + DWMWA_EXCLUDED_FROM_PEEK, + DWMWA_LAST + } + + private static class NativeMethods { + private const string USER = "user32.dll"; + private const string GDI = "gdi32.dll"; + public const string DWMAPI = "dwmapi.dll"; + + [DllImport(USER, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, + ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, + int crKey, ref BlendFunction pblend, int dwFlags); + + [DllImport(USER, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, + IntPtr pptDst, IntPtr psize, IntPtr hdcSrc, IntPtr pprSrc, + int crKey, ref BlendFunction pblend, int dwFlags); + + [DllImport(USER, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr GetDC(IntPtr hWnd); + + [DllImport(USER, CallingConvention = CallingConvention.Winapi)] + public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); + + [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 bool TrackPopupMenuEx(IntPtr hMenu, uint uFlags, + int x, int y, IntPtr hWnd, IntPtr tpmParams); + + [DllImport(GDI, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr CreateCompatibleDC(IntPtr hDC); + + [DllImport(GDI, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DeleteDC(IntPtr hdc); + + [DllImport(GDI, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); + + [DllImport(GDI, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DeleteObject(IntPtr hObject); + + [DllImport(DWMAPI, CallingConvention = CallingConvention.Winapi)] + public static extern int DwmSetWindowAttribute(IntPtr hwnd, + WindowAttribute dwAttribute, ref bool pvAttribute, int cbAttribute); + } + } +} diff -r e4ee19d583bd -r c16fd81b520a GUI/HardwareNode.cs --- a/GUI/HardwareNode.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/GUI/HardwareNode.cs Mon Sep 06 19:53:13 2010 +0000 @@ -55,32 +55,7 @@ this.settings = settings; this.unitManager = unitManager; this.hardware = hardware; - switch (hardware.HardwareType) { - case HardwareType.CPU: - this.Image = Utilities.EmbeddedResources.GetImage("cpu.png"); - break; - case HardwareType.GPU: - if (hardware.Identifier.ToString().Contains("nvidia")) - this.Image = Utilities.EmbeddedResources.GetImage("nvidia.png"); - else - this.Image = Utilities.EmbeddedResources.GetImage("ati.png"); - break; - case HardwareType.HDD: - this.Image = Utilities.EmbeddedResources.GetImage("hdd.png"); - break; - case HardwareType.Heatmaster: - this.Image = Utilities.EmbeddedResources.GetImage("bigng.png"); - break; - case HardwareType.Mainboard: - this.Image = Utilities.EmbeddedResources.GetImage("mainboard.png"); - break; - case HardwareType.SuperIO: - this.Image = Utilities.EmbeddedResources.GetImage("chip.png"); - break; - case HardwareType.TBalancer: - this.Image = Utilities.EmbeddedResources.GetImage("bigng.png"); - break; - } + this.Image = HardwareTypeImage.Instance.GetImage(hardware.HardwareType); typeNodes.Add(new TypeNode(SensorType.Voltage)); typeNodes.Add(new TypeNode(SensorType.Clock)); diff -r e4ee19d583bd -r c16fd81b520a GUI/HardwareTypeImage.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GUI/HardwareTypeImage.cs Mon Sep 06 19:53:13 2010 +0000 @@ -0,0 +1,95 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Drawing; +using System.Collections.Generic; +using OpenHardwareMonitor.Hardware; + +namespace OpenHardwareMonitor.GUI { + public class HardwareTypeImage { + private static HardwareTypeImage instance = new HardwareTypeImage(); + + private IDictionary images = + new Dictionary(); + + private HardwareTypeImage() { } + + public static HardwareTypeImage Instance { + get { return instance; } + } + + public Image GetImage(HardwareType hardwareType) { + Image image; + if (images.TryGetValue(hardwareType, out image)) { + return image; + } else { + switch (hardwareType) { + case HardwareType.CPU: + image = Utilities.EmbeddedResources.GetImage("cpu.png"); + break; + case HardwareType.GpuNvidia: + image = Utilities.EmbeddedResources.GetImage("nvidia.png"); + break; + case HardwareType.GpuAti: + image = Utilities.EmbeddedResources.GetImage("ati.png"); + break; + case HardwareType.HDD: + image = Utilities.EmbeddedResources.GetImage("hdd.png"); + break; + case HardwareType.Heatmaster: + image = Utilities.EmbeddedResources.GetImage("bigng.png"); + break; + case HardwareType.Mainboard: + image = Utilities.EmbeddedResources.GetImage("mainboard.png"); + break; + case HardwareType.SuperIO: + image = Utilities.EmbeddedResources.GetImage("chip.png"); + break; + case HardwareType.TBalancer: + image = Utilities.EmbeddedResources.GetImage("bigng.png"); + break; + default: + image = new Bitmap(1, 1); + break; + } + images.Add(hardwareType, image); + return image; + } + } + } +} diff -r e4ee19d583bd -r c16fd81b520a GUI/MainForm.Designer.cs --- a/GUI/MainForm.Designer.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/GUI/MainForm.Designer.cs Mon Sep 06 19:53:13 2010 +0000 @@ -88,6 +88,7 @@ this.valueMenuItem = new System.Windows.Forms.MenuItem(); this.minMenuItem = new System.Windows.Forms.MenuItem(); this.maxMenuItem = new System.Windows.Forms.MenuItem(); + this.gadgetMenuItem = new System.Windows.Forms.MenuItem(); this.optionsMenuItem = new System.Windows.Forms.MenuItem(); this.startMinMenuItem = new System.Windows.Forms.MenuItem(); this.minTrayMenuItem = new System.Windows.Forms.MenuItem(); @@ -231,6 +232,7 @@ this.MenuItem3, this.hiddenMenuItem, this.plotMenuItem, + this.gadgetMenuItem, this.MenuItem1, this.columnsMenuItem}); this.viewMenuItem.Text = "View"; @@ -258,12 +260,12 @@ // // MenuItem1 // - this.MenuItem1.Index = 4; + this.MenuItem1.Index = 5; this.MenuItem1.Text = "-"; // // columnsMenuItem // - this.columnsMenuItem.Index = 5; + this.columnsMenuItem.Index = 6; this.columnsMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.valueMenuItem, this.minMenuItem, @@ -285,6 +287,11 @@ this.maxMenuItem.Index = 2; this.maxMenuItem.Text = "Max"; // + // gadgetMenuItem + // + this.gadgetMenuItem.Index = 4; + this.gadgetMenuItem.Text = "Show Gadget"; + // // optionsMenuItem // this.optionsMenuItem.Index = 2; @@ -501,6 +508,7 @@ private System.Windows.Forms.MenuItem MenuItem2; private System.Windows.Forms.MenuItem resetMinMaxMenuItem; private System.Windows.Forms.MenuItem MenuItem3; + private System.Windows.Forms.MenuItem gadgetMenuItem; } } diff -r e4ee19d583bd -r c16fd81b520a GUI/MainForm.cs --- a/GUI/MainForm.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/GUI/MainForm.cs Mon Sep 06 19:53:13 2010 +0000 @@ -62,6 +62,7 @@ private SystemTray systemTray; private StartupManager startupManager = new StartupManager(); private UpdateVisitor updateVisitor = new UpdateVisitor(); + private SensorGadget gadget; private UserOption showHiddenSensors; private UserOption showPlot; @@ -72,6 +73,7 @@ private UserOption minimizeToTray; private UserOption autoStart; private UserOption readHddSensors; + private UserOption showGadget; public MainForm() { InitializeComponent(); @@ -138,6 +140,8 @@ systemTray.HideShowCommand += hideShowClick; systemTray.ExitCommand += exitClick; + gadget = new SensorGadget(computer, settings, unitManager); + computer.HardwareAdded += new HardwareEventHandler(HardwareAdded); computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved); computer.Open(); @@ -194,7 +198,7 @@ autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings); autoStart.Changed += delegate(object sender, EventArgs e) { - startupManager.Startup = autoStart.Value; ; + startupManager.Startup = autoStart.Value; }; readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, settings); @@ -203,6 +207,11 @@ UpdatePlotSelection(null, null); }; + showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, settings); + showGadget.Changed += delegate(object sender, EventArgs e) { + gadget.Visible = showGadget.Value; + }; + celciusMenuItem.Checked = unitManager.TemperatureUnit == TemperatureUnit.Celcius; fahrenheitMenuItem.Checked = !celciusMenuItem.Checked; @@ -225,7 +234,7 @@ Microsoft.Win32.SystemEvents.SessionEnded += delegate(object sender, Microsoft.Win32.SessionEndedEventArgs e) { SaveConfiguration(); - }; + }; } private void SubHardwareAdded(IHardware hardware, Node node) { @@ -313,6 +322,7 @@ treeView.Invalidate(); plotPanel.Invalidate(); systemTray.Redraw(); + gadget.Redraw(); } private void SaveConfiguration() { @@ -369,7 +379,7 @@ nodeTextBoxText.BeginEdit(); }; sensorContextMenu.MenuItems.Add(item); - } + } if (node.IsVisible) { MenuItem item = new MenuItem("Hide"); item.Click += delegate(object obj, EventArgs args) { @@ -382,20 +392,30 @@ node.IsVisible = true; }; sensorContextMenu.MenuItems.Add(item); - } - if (systemTray.Contains(node.Sensor)) { - MenuItem item = new MenuItem("Remove From Tray"); - item.Click += delegate(object obj, EventArgs args) { + } + sensorContextMenu.MenuItems.Add(new MenuItem("-")); + + MenuItem menuItem = new MenuItem("Show in Tray"); + menuItem.Checked = systemTray.Contains(node.Sensor); + menuItem.Click += delegate(object obj, EventArgs args) { + if (menuItem.Checked) systemTray.Remove(node.Sensor); - }; - sensorContextMenu.MenuItems.Add(item); - } else { - MenuItem item = new MenuItem("Add To Tray"); - item.Click += delegate(object obj, EventArgs args) { + else systemTray.Add(node.Sensor, true); - }; - sensorContextMenu.MenuItems.Add(item); - } + }; + sensorContextMenu.MenuItems.Add(menuItem); + + menuItem = new MenuItem("Show in Gadget"); + menuItem.Checked = gadget.Contains(node.Sensor); + menuItem.Click += delegate(object obj, EventArgs args) { + if (menuItem.Checked) { + gadget.Remove(node.Sensor); + } else { + gadget.Add(node.Sensor); + } + }; + sensorContextMenu.MenuItems.Add(menuItem); + sensorContextMenu.Show(treeView, new Point(m.X, m.Y)); } } diff -r e4ee19d583bd -r c16fd81b520a GUI/SensorGadget.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GUI/SensorGadget.cs Mon Sep 06 19:53:13 2010 +0000 @@ -0,0 +1,361 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using OpenHardwareMonitor.Hardware; + +namespace OpenHardwareMonitor.GUI { + public class SensorGadget : Gadget { + + private UnitManager unitManager; + + private Image back = Utilities.EmbeddedResources.GetImage("gadget.png"); + private Image barBack = Utilities.EmbeddedResources.GetImage("barback.png"); + private Image barblue = Utilities.EmbeddedResources.GetImage("barblue.png"); + private const int topBorder = 4; + private const int bottomBorder = 6; + private const int leftBorder = 6; + private const int rightBorder = 6; + private const int iconSize = 11; + private const int hardwareLineHeight = 13; + private const int sensorLineHeight = 11; + + private IDictionary> sensors = + new SortedDictionary>(new HardwareComparer()); + + private PersistentSettings settings; + private UserOption alwaysOnTop; + private UserOption lockPosition; + + private Font largeFont; + private Font smallFont; + private Brush darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0)); + + public SensorGadget(IComputer computer, PersistentSettings settings, + UnitManager unitManager) + { + this.unitManager = unitManager; + this.settings = settings; + computer.HardwareAdded += new HardwareEventHandler(HardwareAdded); + computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved); + + this.largeFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f, + FontStyle.Bold); + this.smallFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 6.5f); + + this.Location = new Point( + settings.GetValue("sensorGadget.Location.X", 100), + settings.GetValue("sensorGadget.Location.Y", 100)); + LocationChanged += delegate(object sender, EventArgs e) { + settings.SetValue("sensorGadget.Location.X", Location.X); + settings.SetValue("sensorGadget.Location.Y", Location.Y); + }; + + ContextMenu contextMenu = new ContextMenu(); + MenuItem lockItem = new MenuItem("Lock Position"); + contextMenu.MenuItems.Add(lockItem); + contextMenu.MenuItems.Add(new MenuItem("-")); + MenuItem alwaysOnTopItem = new MenuItem("Always on Top"); + contextMenu.MenuItems.Add(alwaysOnTopItem); + MenuItem opacityMenu = new MenuItem("Opacity"); + contextMenu.MenuItems.Add(opacityMenu); + Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255); + for (int i = 0; i < 5; i++) { + MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %"); + byte o = (byte)(51 * (i + 1)); + item.Tag = o; + item.Checked = Opacity == o; + item.Click += delegate(object sender, EventArgs e) { + Opacity = (byte)item.Tag; + settings.SetValue("sensorGadget.Opacity", Opacity); + foreach (MenuItem mi in opacityMenu.MenuItems) + mi.Checked = (byte)mi.Tag == Opacity; + }; + opacityMenu.MenuItems.Add(item); + } + this.ContextMenu = contextMenu; + + alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false, + alwaysOnTopItem, settings); + alwaysOnTop.Changed += delegate(object sender, EventArgs e) { + this.AlwaysOnTop = alwaysOnTop.Value; + }; + lockPosition = new UserOption("sensorGadget.LockPosition", false, + lockItem, settings); + lockPosition.Changed += delegate(object sender, EventArgs e) { + this.LockPosition = lockPosition.Value; + }; + + Resize(); + } + + private void HardwareRemoved(IHardware hardware) { + hardware.SensorAdded -= new SensorEventHandler(SensorAdded); + hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved); + foreach (ISensor sensor in hardware.Sensors) + SensorRemoved(sensor); + foreach (IHardware subHardware in hardware.SubHardware) + HardwareRemoved(subHardware); + } + + private void HardwareAdded(IHardware hardware) { + foreach (ISensor sensor in hardware.Sensors) + SensorAdded(sensor); + hardware.SensorAdded += new SensorEventHandler(SensorAdded); + hardware.SensorRemoved += new SensorEventHandler(SensorRemoved); + foreach (IHardware subHardware in hardware.SubHardware) + HardwareAdded(subHardware); + } + + private void SensorAdded(ISensor sensor) { + if (settings.GetValue(new Identifier(sensor.Identifier, + "gadget").ToString(), false)) + Add(sensor); + } + + private void SensorRemoved(ISensor sensor) { + if (Contains(sensor)) + Remove(sensor, false); + } + + public bool Contains(ISensor sensor) { + foreach (IList list in sensors.Values) + if (list.Contains(sensor)) + return true; + return false; + } + + public void Add(ISensor sensor) { + if (Contains(sensor)) { + return; + } else { + // get the right hardware + IHardware hardware = sensor.Hardware; + while (hardware.Parent != null) + hardware = hardware.Parent; + + // get the sensor list associated with the hardware + IList list; + if (!sensors.TryGetValue(hardware, out list)) { + list = new List(); + sensors.Add(hardware, list); + } + + // insert the sensor at the right position + int i = 0; + while (i < list.Count && (list[i].SensorType < sensor.SensorType || + (list[i].SensorType == sensor.SensorType && + list[i].Index < sensor.Index))) i++; + list.Insert(i, sensor); + + settings.SetValue( + new Identifier(sensor.Identifier, "gadget").ToString(), true); + + Resize(); + Redraw(); + } + } + + public void Remove(ISensor sensor) { + Remove(sensor, true); + } + + private void Remove(ISensor sensor, bool deleteConfig) { + if (deleteConfig) + settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString()); + + foreach (KeyValuePair> keyValue in sensors) + if (keyValue.Value.Contains(sensor)) { + keyValue.Value.Remove(sensor); + if (keyValue.Value.Count == 0) { + sensors.Remove(keyValue.Key); + break; + } + } + Resize(); + Redraw(); + } + + private void Resize() { + int y = topBorder + 1; + foreach (KeyValuePair> pair in sensors) { + y += hardwareLineHeight; + y += pair.Value.Count * sensorLineHeight; + } + y += bottomBorder + 2; + y = Math.Max(y, topBorder + bottomBorder + 10); + this.Size = new Size(130, y); + } + + private void DrawBackground(Graphics g) { + int w = Size.Width; + int h = Size.Height; + int t = topBorder; + int b = bottomBorder; + int l = leftBorder; + int r = rightBorder; + GraphicsUnit u = GraphicsUnit.Pixel; + + g.DrawImage(back, new Rectangle(0, 0, l, t), + new Rectangle(0, 0, l, t), u); + g.DrawImage(back, new Rectangle(l, 0, w - l - r, t), + new Rectangle(l, 0, back.Width - l - r, t), u); + g.DrawImage(back, new Rectangle(w - r, 0, r, t), + new Rectangle(back.Width - r, 0, r, t), u); + + g.DrawImage(back, new Rectangle(0, t, l, h - t - b), + new Rectangle(0, t, l, back.Height - t - b), u); + g.DrawImage(back, new Rectangle(l, t, w - l - r, h - t - b), + new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u); + g.DrawImage(back, new Rectangle(w - r, t, r, h - t - b), + new Rectangle(back.Width - r, t, r, back.Height - t - b), u); + + g.DrawImage(back, new Rectangle(0, h - b, l, b), + new Rectangle(0, back.Height - b, l, b), u); + g.DrawImage(back, new Rectangle(l, h - b, w - l - r, b), + new Rectangle(l, back.Height - b, back.Width - l - r, b), u); + g.DrawImage(back, new Rectangle(w - r, h - b, r, b), + new Rectangle(back.Width - r, back.Height - b, r, b), u); + } + + private void DrawProgress(Graphics g, int x, int y, int width, int height, + float progress) + { + g.DrawImage(barBack, + new RectangleF(x + width * progress, y, width * (1 - progress), height), + new RectangleF(barBack.Width * progress, 0, + (1 - progress) * barBack.Width, barBack.Height), + GraphicsUnit.Pixel); + g.DrawImage(barblue, + new RectangleF(x, y, width * progress, height), + new RectangleF(0, 0, progress * barblue.Width, barblue.Height), + GraphicsUnit.Pixel); + } + + protected override void OnPaint(PaintEventArgs e) { + Graphics g = e.Graphics; + int w = Size.Width; + int h = Size.Height; + + g.Clear(Color.Transparent); + + DrawBackground(g); + + StringFormat stringFormat = new StringFormat(); + stringFormat.Alignment = StringAlignment.Far; + + int x; + int y = topBorder + 1; + foreach (KeyValuePair> pair in sensors) { + x = leftBorder + 1; + g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType), + new Rectangle(x, y + 2, iconSize, iconSize)); + x += iconSize + 1; + g.DrawString(pair.Key.Name, largeFont, Brushes.White, + new Rectangle(x, y, w - rightBorder - x, 15)); + y += hardwareLineHeight; + + foreach (ISensor sensor in pair.Value) { + + g.DrawString(sensor.Name + ":", smallFont, darkWhite, + new Rectangle(9, y, 64, 15)); + + if (sensor.SensorType != SensorType.Load && + sensor.SensorType != SensorType.Control) + { + string format = ""; + switch (sensor.SensorType) { + case SensorType.Voltage: + format = "{0:F2} V"; + break; + case SensorType.Clock: + format = "{0:F0} MHz"; + break; + case SensorType.Temperature: + format = "{0:F1} °C"; + break; + case SensorType.Fan: + format = "{0:F0} RPM"; + break; + case SensorType.Flow: + format = "{0:F0} L/h"; + break; + } + + string formattedValue; + if (sensor.SensorType == SensorType.Temperature && + unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) { + formattedValue = string.Format("{0:F1} °F", + sensor.Value * 1.8 + 32); + } else { + formattedValue = string.Format(format, sensor.Value); + } + + x = 75; + g.DrawString(formattedValue, smallFont, darkWhite, + new RectangleF(x, y, w - x - 9, 15), stringFormat); + } else { + x = 80; + DrawProgress(g, x, y + 4, w - x - 9, 6, 0.01f * sensor.Value.Value); + } + + y += sensorLineHeight; + } + } + } + + private class HardwareComparer : IComparer { + public int Compare(IHardware x, IHardware y) { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + if (x.HardwareType != y.HardwareType) + return x.HardwareType.CompareTo(y.HardwareType); + + return x.Name.CompareTo(y.Name); + } + } + } +} + diff -r e4ee19d583bd -r c16fd81b520a GUI/SensorNotifyIcon.cs --- a/GUI/SensorNotifyIcon.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/GUI/SensorNotifyIcon.cs Mon Sep 06 19:53:13 2010 +0000 @@ -36,14 +36,12 @@ */ using System; -using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Drawing.Text; -using System.Text; +using System.Runtime.InteropServices; using System.Windows.Forms; -using System.Runtime.InteropServices; using OpenHardwareMonitor.Hardware; using OpenHardwareMonitor.Utilities; diff -r e4ee19d583bd -r c16fd81b520a GUI/ShowDesktop.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GUI/ShowDesktop.cs Mon Sep 06 19:53:13 2010 +0000 @@ -0,0 +1,172 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +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 == referenceWindow.Handle; + } 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); + } + } +} diff -r e4ee19d583bd -r c16fd81b520a Hardware/ATI/ATIGPU.cs --- a/Hardware/ATI/ATIGPU.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/ATI/ATIGPU.cs Mon Sep 06 19:53:13 2010 +0000 @@ -88,7 +88,7 @@ } public override HardwareType HardwareType { - get { return HardwareType.GPU; } + get { return HardwareType.GpuAti; } } public override void Update() { diff -r e4ee19d583bd -r c16fd81b520a Hardware/HDD/HDD.cs --- a/Hardware/HDD/HDD.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/HDD/HDD.cs Mon Sep 06 19:53:13 2010 +0000 @@ -85,6 +85,10 @@ get { return new IHardware[0]; } } + public virtual IHardware Parent { + get { return null; } + } + public ISensor[] Sensors { get { return new ISensor[] { temperature }; diff -r e4ee19d583bd -r c16fd81b520a Hardware/Hardware.cs --- a/Hardware/Hardware.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/Hardware.cs Mon Sep 06 19:53:13 2010 +0000 @@ -48,6 +48,10 @@ get { return new IHardware[0]; } } + public virtual IHardware Parent { + get { return null; } + } + public ISensor[] Sensors { get { return active.ToArray(); } } diff -r e4ee19d583bd -r c16fd81b520a Hardware/IHardware.cs --- a/Hardware/IHardware.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/IHardware.cs Mon Sep 06 19:53:13 2010 +0000 @@ -42,14 +42,15 @@ public delegate void SensorEventHandler(ISensor sensor); - public enum HardwareType { - CPU, - GPU, - HDD, - Heatmaster, + public enum HardwareType { Mainboard, SuperIO, - TBalancer + CPU, + GpuNvidia, + GpuAti, + TBalancer, + Heatmaster, + HDD, } public interface IHardware : IElement { @@ -65,6 +66,8 @@ IHardware[] SubHardware { get; } + IHardware Parent { get; } + ISensor[] Sensors { get; } event SensorEventHandler SensorAdded; diff -r e4ee19d583bd -r c16fd81b520a Hardware/Identifier.cs --- a/Hardware/Identifier.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/Identifier.cs Mon Sep 06 19:53:13 2010 +0000 @@ -40,7 +40,7 @@ using System.Text; namespace OpenHardwareMonitor.Hardware { - public class Identifier { + public class Identifier : IComparable { private string identifier; private static char SEPARATOR = '/'; @@ -92,5 +92,12 @@ public override int GetHashCode() { return identifier.GetHashCode(); } + + public int CompareTo(Identifier other) { + if (other == null) + return 1; + else + return this.identifier.CompareTo(other.identifier); + } } } diff -r e4ee19d583bd -r c16fd81b520a Hardware/Mainboard/Mainboard.cs --- a/Hardware/Mainboard/Mainboard.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/Mainboard/Mainboard.cs Mon Sep 06 19:53:13 2010 +0000 @@ -78,7 +78,7 @@ superIOHardware = new IHardware[superIO.Length]; for (int i = 0; i < superIO.Length; i++) - superIOHardware[i] = new SuperIOHardware(superIO[i], + superIOHardware[i] = new SuperIOHardware(this, superIO[i], smbios.Board != null ? smbios.Board.Manufacturer : Manufacturer.Unknown, smbios.Board != null ? smbios.Board.Model : Model.Unknown, settings); @@ -96,6 +96,10 @@ get { return HardwareType.Mainboard; } } + public virtual IHardware Parent { + get { return null; } + } + public string GetReport() { StringBuilder r = new StringBuilder(); diff -r e4ee19d583bd -r c16fd81b520a Hardware/Mainboard/SuperIOHardware.cs --- a/Hardware/Mainboard/SuperIOHardware.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/Mainboard/SuperIOHardware.cs Mon Sep 06 19:53:13 2010 +0000 @@ -43,6 +43,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { internal class SuperIOHardware : Hardware { + private Mainboard mainboard; private ISuperIO superIO; private string name; @@ -51,9 +52,10 @@ private List fans = new List(); - public SuperIOHardware(ISuperIO superIO, Manufacturer manufacturer, - Model model, ISettings settings) + public SuperIOHardware(Mainboard mainboard, ISuperIO superIO, + Manufacturer manufacturer, Model model, ISettings settings) { + this.mainboard = mainboard; this.superIO = superIO; this.name = ChipName.GetName(superIO.Chip); @@ -614,6 +616,10 @@ get { return HardwareType.SuperIO; } } + public override IHardware Parent { + get { return mainboard; } + } + public override string Name { get { return name; } } diff -r e4ee19d583bd -r c16fd81b520a Hardware/Nvidia/NvidiaGPU.cs --- a/Hardware/Nvidia/NvidiaGPU.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/Nvidia/NvidiaGPU.cs Mon Sep 06 19:53:13 2010 +0000 @@ -123,7 +123,7 @@ } public override HardwareType HardwareType { - get { return HardwareType.GPU; } + get { return HardwareType.GpuNvidia; } } private NvGPUThermalSettings GetThermalSettings() { diff -r e4ee19d583bd -r c16fd81b520a Hardware/TBalancer/TBalancer.cs --- a/Hardware/TBalancer/TBalancer.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Hardware/TBalancer/TBalancer.cs Mon Sep 06 19:53:13 2010 +0000 @@ -285,6 +285,10 @@ get { return new IHardware[0]; } } + public virtual IHardware Parent { + get { return null; } + } + public ISensor[] Sensors { get { return active.ToArray(); } } diff -r e4ee19d583bd -r c16fd81b520a OpenHardwareMonitor.csproj --- a/OpenHardwareMonitor.csproj Tue Aug 24 22:11:10 2010 +0000 +++ b/OpenHardwareMonitor.csproj Mon Sep 06 19:53:13 2010 +0000 @@ -70,6 +70,9 @@ + + + UserControl @@ -92,7 +95,9 @@ ParameterForm.cs + + Component @@ -197,6 +202,11 @@ true + + + + + diff -r e4ee19d583bd -r c16fd81b520a Properties/AssemblyVersion.cs --- a/Properties/AssemblyVersion.cs Tue Aug 24 22:11:10 2010 +0000 +++ b/Properties/AssemblyVersion.cs Mon Sep 06 19:53:13 2010 +0000 @@ -38,5 +38,5 @@ using System; using System.Reflection; -[assembly: AssemblyVersion("0.1.37.9")] -[assembly: AssemblyFileVersion("0.1.37.9")] +[assembly: AssemblyVersion("0.1.37.10")] +[assembly: AssemblyFileVersion("0.1.37.10")] diff -r e4ee19d583bd -r c16fd81b520a Resources/barback.png Binary file Resources/barback.png has changed diff -r e4ee19d583bd -r c16fd81b520a Resources/barblue.png Binary file Resources/barblue.png has changed diff -r e4ee19d583bd -r c16fd81b520a Resources/gadget.png Binary file Resources/gadget.png has changed diff -r e4ee19d583bd -r c16fd81b520a Resources/gadget.xcf Binary file Resources/gadget.xcf has changed