# HG changeset patch
# User moel.mich
# Date 1308782177 0
# Node ID 44c0e7f76e9e024a6c8a7da442934bde676191b8
# Parent  d14ce71cef445b3afcb1375b677e5e5a6bcbe111
Removed the bitmap.GetHbitmap call for every redraw of the gadget. This should reduce dynamic memory allocation and freeing and removes some of the page faults increasing.

diff -r d14ce71cef44 -r 44c0e7f76e9e GUI/Gadget.cs
--- a/GUI/Gadget.cs	Sun Jun 19 14:14:00 2011 +0000
+++ b/GUI/Gadget.cs	Wed Jun 22 22:36:17 2011 +0000
@@ -16,7 +16,7 @@
 
   The Initial Developer of the Original Code is 
   Michael Möller <m.moeller@gmx.ch>.
-  Portions created by the Initial Developer are Copyright (C) 2010
+  Portions created by the Initial Developer are Copyright (C) 2010-2011
   the Initial Developer. All Rights Reserved.
 
   Contributor(s):
@@ -37,25 +37,22 @@
 
 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();
+      this.window.Paint += delegate(object sender, PaintEventArgs e) {
+        OnPaint(e);
+      };
     }
 
     public virtual void Dispose() {
-      DisposeBuffer();
+      window.Dispose();
     }
 
     public Point Location {
@@ -148,27 +145,6 @@
       }
     }
 
-    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;
@@ -187,17 +163,7 @@
     public event EventHandler VisibleChanged;
 
     public void Redraw() {
-      if (!window.Visible)
-        return;
-      
-      if (window.Size != buffer.Size) {
-        DisposeBuffer();
-        CreateBuffer();
-      }
-
-      OnPaint(new PaintEventArgs(graphics, 
-        new Rectangle(Point.Empty, window.Size)));
-      window.Update(buffer);
+      window.Redraw();
     }
 
     protected abstract void OnPaint(PaintEventArgs e);
diff -r d14ce71cef44 -r 44c0e7f76e9e GUI/GadgetWindow.cs
--- a/GUI/GadgetWindow.cs	Sun Jun 19 14:14:00 2011 +0000
+++ b/GUI/GadgetWindow.cs	Wed Jun 22 22:36:17 2011 +0000
@@ -16,7 +16,7 @@
 
   The Initial Developer of the Original Code is 
   Michael Möller <m.moeller@gmx.ch>.
-  Portions created by the Initial Developer are Copyright (C) 2010
+  Portions created by the Initial Developer are Copyright (C) 2010-2011
   the Initial Developer. All Rights Reserved.
 
   Contributor(s):
@@ -37,13 +37,15 @@
 
 using System;
 using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
 using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Windows.Forms;
 
 namespace OpenHardwareMonitor.GUI {
 
-  public class GadgetWindow : NativeWindow {
+  public class GadgetWindow : NativeWindow, IDisposable {
 
     private bool visible = false;
     private bool lockPositionAndSize = false;
@@ -53,6 +55,9 @@
     private Size size = new Size(130, 84);
     private ContextMenu contextMenu = null;
     private MethodInfo commandDispatch;
+    private IntPtr handleBitmapDC;
+    private Size bufferSize;
+    private Graphics graphics;
 
     public GadgetWindow() {
       Type commandType = 
@@ -73,6 +78,8 @@
           WindowAttribute.DWMWA_EXCLUDED_FROM_PEEK, ref value,
           Marshal.SizeOf(value));
       } catch (DllNotFoundException) { } catch (EntryPointNotFoundException) { }
+
+      CreateBuffer();
     }
 
     private void ShowDesktopChanged(bool showDesktop) {
@@ -223,35 +230,66 @@
       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;
+    private void CreateBuffer() {      
+      IntPtr handleScreenDC = NativeMethods.GetDC(IntPtr.Zero);
+      handleBitmapDC = NativeMethods.CreateCompatibleDC(handleScreenDC);
+      NativeMethods.ReleaseDC(IntPtr.Zero, handleScreenDC);
+      bufferSize = size;
 
-      try {
-        newHBitmap = bitmap.GetHbitmap(Color.Black);
-        oldHBitmap = NativeMethods.SelectObject(memory, newHBitmap);
+      BitmapInfo info = new BitmapInfo();
+      info.Size = Marshal.SizeOf(info);
+      info.Width = size.Width;
+      info.Height = -size.Height;
+      info.BitCount = 32;
+      info.Planes = 1;
+
+      IntPtr ptr;
+      IntPtr hBmp = NativeMethods.CreateDIBSection(handleBitmapDC, ref info, 0, 
+        out ptr, IntPtr.Zero, 0);
+      IntPtr hBmpOld = NativeMethods.SelectObject(handleBitmapDC, hBmp);
+      NativeMethods.DeleteObject(hBmpOld);
+      
+      graphics = Graphics.FromHdc(handleBitmapDC);
+
+      if (Environment.OSVersion.Version.Major > 5) {
+        this.graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
+        this.graphics.SmoothingMode = SmoothingMode.HighQuality;
+      } 
+    }
+
+    private void DisposeBuffer() {
+      graphics.Dispose();
+      NativeMethods.DeleteDC(handleBitmapDC);
+    }
+
+    public virtual void Dispose() {
+      DisposeBuffer();
+    } 
+
+    public PaintEventHandler Paint; 
+
+    public void Redraw() {
+      if (!visible || Paint == null)
+        return;
+
+      if (size != bufferSize) {
+        DisposeBuffer();
+        CreateBuffer();
+      }
+
+      Paint(this, 
+        new PaintEventArgs(graphics, new Rectangle(Point.Empty, size))); 
 
         Point pointSource = Point.Empty;
         BlendFunction blend = CreateBlendFunction();
 
-        NativeMethods.UpdateLayeredWindow(Handle, screen, IntPtr.Zero,
-          ref size, memory, ref pointSource, 0, ref blend, ULW_ALPHA);
+        NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
+          ref size, handleBitmapDC, ref pointSource, 0, ref blend, ULW_ALPHA);
 
         // make sure the window is at the right location
-        NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 
-          location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | 
+        NativeMethods.SetWindowPos(Handle, IntPtr.Zero,
+          location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE |
           SWP_NOZORDER | SWP_NOSENDCHANGING);
-
-      } finally {        
-        if (newHBitmap != IntPtr.Zero) {
-          NativeMethods.SelectObject(memory, oldHBitmap);
-          NativeMethods.DeleteObject(newHBitmap);
-        }
-        NativeMethods.DeleteDC(memory);
-        NativeMethods.ReleaseDC(IntPtr.Zero, screen);
-      }
     }
 
     public byte Opacity {
@@ -386,6 +424,22 @@
       public uint flags;
     }
 
+    [StructLayout(LayoutKind.Sequential)]
+    public struct BitmapInfo {
+      public Int32 Size;
+      public Int32 Width;
+      public Int32 Height;
+      public Int16 Planes;
+      public Int16 BitCount;
+      public Int32 Compression;
+      public Int32 SizeImage;
+      public Int32 XPelsPerMeter;
+      public Int32 YPelsPerMeter;
+      public Int32 ClrUsed;
+      public Int32 ClrImportant;
+      public Int32 Colors;
+    }
+
     public static readonly IntPtr HWND_BOTTOM = (IntPtr)1;
     public static readonly IntPtr HWND_TOPMOST = (IntPtr)(-1);
 
@@ -501,6 +555,11 @@
       public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
 
       [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
+      public static extern IntPtr CreateDIBSection(IntPtr hdc, 
+        [In] ref BitmapInfo pbmi, uint pila, out IntPtr ppvBits, 
+        IntPtr hSection, uint dwOffset);
+
+      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool DeleteDC(IntPtr hdc);