GUI/GadgetWindow.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
parent 302 44c0e7f76e9e
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@202
     1
/*
moel@344
     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@344
     6
 
moel@344
     7
  Copyright (C) 2010-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	Copyright (C) 2010 Paul Werelds <paul@werelds.net>
moel@176
     9
moel@176
    10
*/
moel@176
    11
moel@176
    12
using System;
moel@176
    13
using System.Drawing;
moel@302
    14
using System.Drawing.Drawing2D;
moel@302
    15
using System.Drawing.Text;
moel@176
    16
using System.Reflection;
moel@176
    17
using System.Runtime.InteropServices;
moel@176
    18
using System.Windows.Forms;
moel@176
    19
moel@176
    20
namespace OpenHardwareMonitor.GUI {
moel@183
    21
moel@302
    22
  public class GadgetWindow : NativeWindow, IDisposable {
moel@176
    23
moel@176
    24
    private bool visible = false;
moel@183
    25
    private bool lockPositionAndSize = false;
moel@176
    26
    private bool alwaysOnTop = false;
moel@176
    27
    private byte opacity = 255;
moel@176
    28
    private Point location = new Point(100, 100);
moel@176
    29
    private Size size = new Size(130, 84);
moel@176
    30
    private ContextMenu contextMenu = null;
moel@176
    31
    private MethodInfo commandDispatch;
moel@302
    32
    private IntPtr handleBitmapDC;
moel@302
    33
    private Size bufferSize;
moel@302
    34
    private Graphics graphics;
moel@176
    35
moel@176
    36
    public GadgetWindow() {
moel@176
    37
      Type commandType = 
moel@176
    38
        typeof(Form).Assembly.GetType("System.Windows.Forms.Command");
moel@176
    39
      commandDispatch = commandType.GetMethod("DispatchID", 
moel@176
    40
        BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, 
moel@176
    41
        null, new Type[]{ typeof(int) }, null);
moel@176
    42
moel@176
    43
      this.CreateHandle(CreateParams);
moel@176
    44
moel@176
    45
      // move window to the bottom
moel@176
    46
      MoveToBottom(Handle);
moel@176
    47
moel@176
    48
      // prevent window from fading to a glass sheet when peek is invoked
moel@176
    49
      try {
moel@176
    50
        bool value = true;
moel@202
    51
        NativeMethods.DwmSetWindowAttribute(Handle,
moel@176
    52
          WindowAttribute.DWMWA_EXCLUDED_FROM_PEEK, ref value,
moel@176
    53
          Marshal.SizeOf(value));
moel@176
    54
      } catch (DllNotFoundException) { } catch (EntryPointNotFoundException) { }
moel@302
    55
moel@302
    56
      CreateBuffer();
moel@176
    57
    }
moel@176
    58
moel@176
    59
    private void ShowDesktopChanged(bool showDesktop) {
moel@176
    60
      if (showDesktop) {
moel@176
    61
        MoveToTopMost(Handle);
moel@176
    62
      } else {
moel@176
    63
        MoveToBottom(Handle);
moel@176
    64
      }
moel@176
    65
    }
moel@176
    66
moel@176
    67
    private void MoveToBottom(IntPtr handle) {
moel@176
    68
      NativeMethods.SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0,
moel@176
    69
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
moel@176
    70
    }
moel@176
    71
moel@176
    72
    private void MoveToTopMost(IntPtr handle) {
moel@176
    73
      NativeMethods.SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0,
moel@176
    74
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
moel@176
    75
    }
moel@176
    76
moel@176
    77
    private void ShowContextMenu(Point position) {
moel@176
    78
      NativeMethods.TrackPopupMenuEx(contextMenu.Handle, 
moel@176
    79
        TPM_RIGHTBUTTON | TPM_VERTICAL, position.X,
moel@176
    80
        position.Y, Handle, IntPtr.Zero);
moel@176
    81
    }
moel@176
    82
moel@176
    83
    protected virtual CreateParams CreateParams {
moel@176
    84
      get {
moel@183
    85
        CreateParams cp = new CreateParams();        
moel@183
    86
        cp.Width = 4096;
moel@183
    87
        cp.Height = 4096;
moel@176
    88
        cp.X = location.X;
moel@176
    89
        cp.Y = location.Y;
moel@176
    90
        cp.ExStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW;
moel@176
    91
        return cp;
moel@176
    92
      }
moel@176
    93
    }
moel@176
    94
moel@176
    95
    protected override void WndProc(ref Message message) {
moel@176
    96
      switch (message.Msg) {
moel@183
    97
        case WM_COMMAND: {
moel@183
    98
            // need to dispatch the message for the context menu
moel@183
    99
            if (message.LParam == IntPtr.Zero)
moel@183
   100
              commandDispatch.Invoke(null, new object[] { 
moel@183
   101
              message.WParam.ToInt32() & 0xFFFF });
moel@183
   102
          } break;
moel@183
   103
        case WM_NCHITTEST: {
moel@183
   104
            message.Result = (IntPtr)HitResult.Caption;
moel@183
   105
            if (HitTest != null) {
moel@183
   106
              Point p = new Point(
paulwerelds@208
   107
                Macros.GET_X_LPARAM(message.LParam) - location.X,
paulwerelds@208
   108
                Macros.GET_Y_LPARAM(message.LParam) - location.Y
paulwerelds@208
   109
              );
moel@183
   110
              HitTestEventArgs e = new HitTestEventArgs(p, HitResult.Caption);
moel@183
   111
              HitTest(this, e);
moel@183
   112
              message.Result = (IntPtr)e.HitResult;
moel@183
   113
            }
moel@183
   114
          } break;
moel@183
   115
        case WM_NCLBUTTONDBLCLK: {
moel@244
   116
            if (MouseDoubleClick != null) {
moel@244
   117
              MouseDoubleClick(this, new MouseEventArgs(MouseButtons.Left, 2,
moel@244
   118
                Macros.GET_X_LPARAM(message.LParam) - location.X,
moel@244
   119
                Macros.GET_Y_LPARAM(message.LParam) - location.Y, 0));
moel@244
   120
            }
moel@183
   121
            message.Result = IntPtr.Zero;
moel@183
   122
          } break;
moel@183
   123
        case WM_NCRBUTTONDOWN: {
moel@183
   124
            message.Result = IntPtr.Zero;
moel@183
   125
          } break;
moel@183
   126
        case WM_NCRBUTTONUP: {
moel@183
   127
            if (contextMenu != null)
moel@183
   128
              ShowContextMenu(new Point(
paulwerelds@209
   129
                Macros.GET_X_LPARAM(message.LParam),
paulwerelds@209
   130
                Macros.GET_Y_LPARAM(message.LParam)
paulwerelds@209
   131
              ));
moel@183
   132
            message.Result = IntPtr.Zero;
moel@183
   133
          } break;
moel@183
   134
        case WM_WINDOWPOSCHANGING: {
moel@183
   135
            WindowPos wp = (WindowPos)Marshal.PtrToStructure(
moel@183
   136
              message.LParam, typeof(WindowPos));
moel@183
   137
            
moel@183
   138
            if (!lockPositionAndSize) {
moel@183
   139
              // prevent the window from leaving the screen
moel@183
   140
              if ((wp.flags & SWP_NOMOVE) == 0) {
moel@243
   141
                Rectangle rect = Screen.GetWorkingArea(
moel@243
   142
                  new Rectangle(wp.x, wp.y, wp.cx, wp.cy));
moel@183
   143
                const int margin = 16;
moel@183
   144
                wp.x = Math.Max(wp.x, rect.Left - wp.cx + margin);
moel@183
   145
                wp.x = Math.Min(wp.x, rect.Right - margin);
moel@183
   146
                wp.y = Math.Max(wp.y, rect.Top - wp.cy + margin);
moel@183
   147
                wp.y = Math.Min(wp.y, rect.Bottom - margin);
moel@183
   148
              }
moel@176
   149
moel@183
   150
              // update location and fire event
moel@183
   151
              if ((wp.flags & SWP_NOMOVE) == 0) {
moel@183
   152
                if (location.X != wp.x || location.Y != wp.y) {
moel@183
   153
                  location = new Point(wp.x, wp.y);
moel@183
   154
                  if (LocationChanged != null)
moel@183
   155
                    LocationChanged(this, EventArgs.Empty);
moel@183
   156
                }
moel@183
   157
              }
moel@176
   158
moel@183
   159
              // update size and fire event
moel@183
   160
              if ((wp.flags & SWP_NOSIZE) == 0) {
moel@183
   161
                if (size.Width != wp.cx || size.Height != wp.cy) {
moel@183
   162
                  size = new Size(wp.cx, wp.cy);
moel@183
   163
                  if (SizeChanged != null)
moel@183
   164
                    SizeChanged(this, EventArgs.Empty);
moel@183
   165
                }
moel@183
   166
              } 
moel@176
   167
moel@183
   168
              // update the size of the layered window
moel@183
   169
              if ((wp.flags & SWP_NOSIZE) == 0) {
moel@183
   170
                NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero,
moel@183
   171
                  IntPtr.Zero, ref size, IntPtr.Zero, IntPtr.Zero, 0,
moel@183
   172
                  IntPtr.Zero, 0);                
moel@183
   173
              }
moel@183
   174
moel@183
   175
              // update the position of the layered window
moel@183
   176
              if ((wp.flags & SWP_NOMOVE) == 0) {
moel@183
   177
                NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 
moel@183
   178
                  location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | 
moel@183
   179
                  SWP_NOZORDER | SWP_NOSENDCHANGING);
moel@183
   180
              }
moel@176
   181
            }
moel@183
   182
            
moel@183
   183
            // do not forward any move or size messages
moel@243
   184
            wp.flags |= SWP_NOSIZE | SWP_NOMOVE;
moel@243
   185
moel@243
   186
            // suppress any frame changed events
moel@243
   187
            wp.flags &= ~SWP_FRAMECHANGED;
moel@243
   188
moel@183
   189
            Marshal.StructureToPtr(wp, message.LParam, false);                      
moel@183
   190
            message.Result = IntPtr.Zero;
moel@183
   191
          } break;
moel@183
   192
        default: {
moel@183
   193
            base.WndProc(ref message);
moel@183
   194
          } break;
moel@176
   195
      }      
moel@176
   196
    }
moel@176
   197
moel@176
   198
    private BlendFunction CreateBlendFunction() {
moel@176
   199
      BlendFunction blend = new BlendFunction();
moel@176
   200
      blend.BlendOp = AC_SRC_OVER;
moel@176
   201
      blend.BlendFlags = 0;
moel@176
   202
      blend.SourceConstantAlpha = opacity;
moel@176
   203
      blend.AlphaFormat = AC_SRC_ALPHA;
moel@176
   204
      return blend;
moel@176
   205
    }
moel@176
   206
moel@302
   207
    private void CreateBuffer() {      
moel@302
   208
      IntPtr handleScreenDC = NativeMethods.GetDC(IntPtr.Zero);
moel@302
   209
      handleBitmapDC = NativeMethods.CreateCompatibleDC(handleScreenDC);
moel@302
   210
      NativeMethods.ReleaseDC(IntPtr.Zero, handleScreenDC);
moel@302
   211
      bufferSize = size;
moel@176
   212
moel@302
   213
      BitmapInfo info = new BitmapInfo();
moel@302
   214
      info.Size = Marshal.SizeOf(info);
moel@302
   215
      info.Width = size.Width;
moel@302
   216
      info.Height = -size.Height;
moel@302
   217
      info.BitCount = 32;
moel@302
   218
      info.Planes = 1;
moel@302
   219
moel@302
   220
      IntPtr ptr;
moel@302
   221
      IntPtr hBmp = NativeMethods.CreateDIBSection(handleBitmapDC, ref info, 0, 
moel@302
   222
        out ptr, IntPtr.Zero, 0);
moel@302
   223
      IntPtr hBmpOld = NativeMethods.SelectObject(handleBitmapDC, hBmp);
moel@302
   224
      NativeMethods.DeleteObject(hBmpOld);
moel@302
   225
      
moel@302
   226
      graphics = Graphics.FromHdc(handleBitmapDC);
moel@302
   227
moel@302
   228
      if (Environment.OSVersion.Version.Major > 5) {
moel@302
   229
        this.graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
moel@302
   230
        this.graphics.SmoothingMode = SmoothingMode.HighQuality;
moel@302
   231
      } 
moel@302
   232
    }
moel@302
   233
moel@302
   234
    private void DisposeBuffer() {
moel@302
   235
      graphics.Dispose();
moel@302
   236
      NativeMethods.DeleteDC(handleBitmapDC);
moel@302
   237
    }
moel@302
   238
moel@302
   239
    public virtual void Dispose() {
moel@302
   240
      DisposeBuffer();
moel@302
   241
    } 
moel@302
   242
moel@302
   243
    public PaintEventHandler Paint; 
moel@302
   244
moel@302
   245
    public void Redraw() {
moel@302
   246
      if (!visible || Paint == null)
moel@302
   247
        return;
moel@302
   248
moel@302
   249
      if (size != bufferSize) {
moel@302
   250
        DisposeBuffer();
moel@302
   251
        CreateBuffer();
moel@302
   252
      }
moel@302
   253
moel@302
   254
      Paint(this, 
moel@302
   255
        new PaintEventArgs(graphics, new Rectangle(Point.Empty, size))); 
moel@176
   256
moel@176
   257
        Point pointSource = Point.Empty;
moel@183
   258
        BlendFunction blend = CreateBlendFunction();
moel@176
   259
moel@302
   260
        NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
moel@302
   261
          ref size, handleBitmapDC, ref pointSource, 0, ref blend, ULW_ALPHA);
moel@183
   262
moel@183
   263
        // make sure the window is at the right location
moel@302
   264
        NativeMethods.SetWindowPos(Handle, IntPtr.Zero,
moel@302
   265
          location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE |
moel@183
   266
          SWP_NOZORDER | SWP_NOSENDCHANGING);
moel@176
   267
    }
moel@176
   268
moel@176
   269
    public byte Opacity {
moel@176
   270
      get {
moel@176
   271
        return opacity;
moel@176
   272
      }
moel@176
   273
      set {
moel@176
   274
        if (opacity != value) {
moel@176
   275
          opacity = value;
moel@176
   276
          BlendFunction blend = CreateBlendFunction();
moel@176
   277
          NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
moel@176
   278
            IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, ref blend, ULW_ALPHA);
moel@176
   279
        }
moel@176
   280
      }
moel@176
   281
    }
moel@176
   282
moel@176
   283
    public bool Visible {
moel@176
   284
      get {
moel@176
   285
        return visible;
moel@176
   286
      }
moel@176
   287
      set {
moel@176
   288
        if (visible != value) {
moel@176
   289
          visible = value;
moel@176
   290
          NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 0, 0, 0, 0,
moel@176
   291
            SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER |
moel@176
   292
            (value ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
moel@180
   293
          if (value) {
moel@180
   294
            if (!alwaysOnTop)
moel@180
   295
              ShowDesktop.Instance.ShowDesktopChanged += ShowDesktopChanged;
moel@180
   296
          } else {
moel@180
   297
            if (!alwaysOnTop)
moel@180
   298
              ShowDesktop.Instance.ShowDesktopChanged -= ShowDesktopChanged;
moel@180
   299
          }
moel@176
   300
        }
moel@176
   301
      }
moel@176
   302
    }
moel@176
   303
moel@183
   304
    // if locked, the window can not be moved or resized
moel@183
   305
    public bool LockPositionAndSize {
moel@176
   306
      get {
moel@183
   307
        return lockPositionAndSize;
moel@176
   308
      }
moel@176
   309
      set {
moel@183
   310
        lockPositionAndSize = value;
moel@176
   311
      }
moel@176
   312
    }
moel@176
   313
moel@176
   314
    public bool AlwaysOnTop {
moel@176
   315
      get {
moel@176
   316
        return alwaysOnTop;
moel@176
   317
      }
moel@176
   318
      set {
moel@176
   319
        if (value != alwaysOnTop) {
moel@176
   320
          alwaysOnTop = value;
moel@176
   321
          if (alwaysOnTop) {
moel@180
   322
            if (visible)
moel@180
   323
              ShowDesktop.Instance.ShowDesktopChanged -= ShowDesktopChanged;
moel@176
   324
            MoveToTopMost(Handle);            
moel@176
   325
          } else {
moel@176
   326
            MoveToBottom(Handle);
moel@180
   327
            if (visible)
moel@180
   328
              ShowDesktop.Instance.ShowDesktopChanged += ShowDesktopChanged;
moel@176
   329
          }
moel@176
   330
        }
moel@176
   331
      }
moel@176
   332
    }
moel@176
   333
moel@176
   334
    public Size Size {
moel@176
   335
      get {
moel@176
   336
        return size; 
moel@176
   337
      }
moel@176
   338
      set {
moel@176
   339
        if (size != value) {
moel@176
   340
          size = value;
moel@183
   341
          NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
moel@183
   342
            ref size, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero, 0);                    
moel@183
   343
          if (SizeChanged != null)
moel@183
   344
            SizeChanged(this, EventArgs.Empty);
moel@176
   345
        }
moel@176
   346
      }
moel@176
   347
    }
moel@176
   348
moel@183
   349
    public event EventHandler SizeChanged;
moel@183
   350
moel@176
   351
    public Point Location {
moel@176
   352
      get {
moel@176
   353
        return location;
moel@176
   354
      }
moel@176
   355
      set {
moel@183
   356
        if (location != value) {
moel@183
   357
          location = value;
moel@183
   358
          NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 
moel@183
   359
            location.X, location.Y, 0, 0, 
moel@183
   360
            SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING);          
moel@183
   361
          if (LocationChanged != null)
moel@183
   362
            LocationChanged(this, EventArgs.Empty);
moel@183
   363
        }
moel@176
   364
      }
moel@176
   365
    }
moel@176
   366
moel@176
   367
    public event EventHandler LocationChanged;
moel@176
   368
moel@176
   369
    public ContextMenu ContextMenu {
moel@176
   370
      get {
moel@176
   371
        return contextMenu;
moel@176
   372
      }
moel@176
   373
      set {
moel@176
   374
        this.contextMenu = value;
moel@176
   375
      }
moel@176
   376
    }
moel@176
   377
moel@183
   378
    public event HitTestEventHandler HitTest;
moel@183
   379
moel@244
   380
    public event MouseEventHandler MouseDoubleClick;
moel@244
   381
moel@176
   382
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@176
   383
    private struct BlendFunction {
moel@176
   384
      public byte BlendOp;
moel@176
   385
      public byte BlendFlags;
moel@176
   386
      public byte SourceConstantAlpha;
moel@176
   387
      public byte AlphaFormat;
moel@176
   388
    }
moel@176
   389
moel@176
   390
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@176
   391
    private struct WindowPos {
moel@176
   392
      public IntPtr hwnd;
moel@176
   393
      public IntPtr hwndInsertAfter;
moel@176
   394
      public int x;
moel@176
   395
      public int y;
moel@176
   396
      public int cx;
moel@176
   397
      public int cy;
moel@176
   398
      public uint flags;
moel@176
   399
    }
moel@176
   400
moel@302
   401
    [StructLayout(LayoutKind.Sequential)]
moel@302
   402
    public struct BitmapInfo {
moel@302
   403
      public Int32 Size;
moel@302
   404
      public Int32 Width;
moel@302
   405
      public Int32 Height;
moel@302
   406
      public Int16 Planes;
moel@302
   407
      public Int16 BitCount;
moel@302
   408
      public Int32 Compression;
moel@302
   409
      public Int32 SizeImage;
moel@302
   410
      public Int32 XPelsPerMeter;
moel@302
   411
      public Int32 YPelsPerMeter;
moel@302
   412
      public Int32 ClrUsed;
moel@302
   413
      public Int32 ClrImportant;
moel@302
   414
      public Int32 Colors;
moel@302
   415
    }
moel@302
   416
moel@176
   417
    public static readonly IntPtr HWND_BOTTOM = (IntPtr)1;
moel@176
   418
    public static readonly IntPtr HWND_TOPMOST = (IntPtr)(-1);
moel@176
   419
moel@176
   420
    public const int WS_EX_LAYERED = 0x00080000;
moel@176
   421
    public const int WS_EX_TOOLWINDOW = 0x00000080;
moel@176
   422
moel@176
   423
    public const uint SWP_NOSIZE = 0x0001;
moel@176
   424
    public const uint SWP_NOMOVE = 0x0002;
moel@176
   425
    public const uint SWP_NOACTIVATE = 0x0010;
moel@243
   426
    public const uint SWP_FRAMECHANGED = 0x0020;
moel@176
   427
    public const uint SWP_HIDEWINDOW = 0x0080;
moel@176
   428
    public const uint SWP_SHOWWINDOW = 0x0040;
moel@176
   429
    public const uint SWP_NOZORDER = 0x0004;
moel@176
   430
    public const uint SWP_NOSENDCHANGING = 0x0400;
moel@176
   431
moel@176
   432
    public const int ULW_COLORKEY = 0x00000001;
moel@176
   433
    public const int ULW_ALPHA = 0x00000002;
moel@176
   434
    public const int ULW_OPAQUE = 0x00000004;
moel@176
   435
moel@176
   436
    public const byte AC_SRC_OVER = 0x00;
moel@176
   437
    public const byte AC_SRC_ALPHA = 0x01;
moel@176
   438
moel@176
   439
    public const int WM_NCHITTEST = 0x0084;
moel@176
   440
    public const int WM_NCLBUTTONDBLCLK = 0x00A3;
moel@176
   441
    public const int WM_NCLBUTTONDOWN = 0x00A1;
moel@176
   442
    public const int WM_NCLBUTTONUP = 0x00A2;
moel@176
   443
    public const int WM_NCRBUTTONDOWN = 0x00A4;
moel@176
   444
    public const int WM_NCRBUTTONUP = 0x00A5;
moel@176
   445
    public const int WM_WINDOWPOSCHANGING = 0x0046;
moel@176
   446
    public const int WM_COMMAND = 0x0111;
moel@176
   447
moel@176
   448
    public const int TPM_RIGHTBUTTON = 0x0002;
moel@176
   449
    public const int TPM_VERTICAL = 0x0040;
moel@176
   450
moel@176
   451
    private enum WindowAttribute : int {
moel@176
   452
      DWMWA_NCRENDERING_ENABLED = 1,
moel@176
   453
      DWMWA_NCRENDERING_POLICY,
moel@176
   454
      DWMWA_TRANSITIONS_FORCEDISABLED,
moel@176
   455
      DWMWA_ALLOW_NCPAINT,
moel@176
   456
      DWMWA_CAPTION_BUTTON_BOUNDS,
moel@176
   457
      DWMWA_NONCLIENT_RTL_LAYOUT,
moel@176
   458
      DWMWA_FORCE_ICONIC_REPRESENTATION,
moel@176
   459
      DWMWA_FLIP3D_POLICY,
moel@176
   460
      DWMWA_EXTENDED_FRAME_BOUNDS,
moel@176
   461
      DWMWA_HAS_ICONIC_BITMAP,
moel@176
   462
      DWMWA_DISALLOW_PEEK,
moel@176
   463
      DWMWA_EXCLUDED_FROM_PEEK,
moel@176
   464
      DWMWA_LAST
moel@176
   465
    }
moel@176
   466
paulwerelds@208
   467
    /// <summary>
paulwerelds@208
   468
    /// Some macros imported and converted from the Windows SDK
paulwerelds@208
   469
    /// </summary>
paulwerelds@208
   470
    private static class Macros {
paulwerelds@210
   471
      public static ushort LOWORD(IntPtr l) {
paulwerelds@210
   472
        return (ushort) ((ulong)l & 0xFFFF);
paulwerelds@208
   473
      }
paulwerelds@208
   474
      
paulwerelds@208
   475
      public static UInt16 HIWORD(IntPtr l) {
paulwerelds@210
   476
        return (ushort) (((ulong)l >> 16) & 0xFFFF);
paulwerelds@208
   477
      }
paulwerelds@208
   478
paulwerelds@208
   479
      public static int GET_X_LPARAM(IntPtr lp) {
paulwerelds@210
   480
        return (short) LOWORD(lp);
paulwerelds@208
   481
      }
paulwerelds@208
   482
paulwerelds@208
   483
      public static int GET_Y_LPARAM(IntPtr lp) {
paulwerelds@210
   484
        return (short) HIWORD(lp);
paulwerelds@208
   485
      }
paulwerelds@208
   486
    }
paulwerelds@208
   487
paulwerelds@208
   488
    /// <summary>
paulwerelds@208
   489
    /// Imported native methods
paulwerelds@208
   490
    /// </summary>
moel@176
   491
    private static class NativeMethods {
moel@176
   492
      private const string USER = "user32.dll";
moel@176
   493
      private const string GDI = "gdi32.dll";
moel@176
   494
      public const string DWMAPI = "dwmapi.dll";
moel@176
   495
moel@176
   496
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   497
      [return: MarshalAs(UnmanagedType.Bool)]
moel@183
   498
      public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
moel@183
   499
        IntPtr pptDst, ref Size psize, IntPtr hdcSrc, IntPtr pprSrc,
moel@183
   500
        int crKey, IntPtr pblend, int dwFlags);
moel@183
   501
moel@183
   502
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@183
   503
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   504
      public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, 
moel@183
   505
        IntPtr pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, 
moel@176
   506
        int crKey, ref BlendFunction pblend, int dwFlags);
moel@176
   507
moel@176
   508
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   509
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   510
      public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
moel@176
   511
        IntPtr pptDst, IntPtr psize, IntPtr hdcSrc, IntPtr pprSrc,
moel@176
   512
        int crKey, ref BlendFunction pblend, int dwFlags);  
moel@176
   513
moel@176
   514
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   515
      public static extern IntPtr GetDC(IntPtr hWnd);
moel@176
   516
moel@176
   517
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   518
      public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
moel@176
   519
moel@176
   520
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   521
      public static extern bool SetWindowPos(IntPtr hWnd,
moel@176
   522
        IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
moel@176
   523
moel@176
   524
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   525
      public static extern bool TrackPopupMenuEx(IntPtr hMenu, uint uFlags, 
moel@176
   526
        int x, int y, IntPtr hWnd, IntPtr tpmParams);
moel@176
   527
moel@176
   528
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   529
      public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
moel@176
   530
moel@176
   531
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@302
   532
      public static extern IntPtr CreateDIBSection(IntPtr hdc, 
moel@302
   533
        [In] ref BitmapInfo pbmi, uint pila, out IntPtr ppvBits, 
moel@302
   534
        IntPtr hSection, uint dwOffset);
moel@302
   535
moel@302
   536
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   537
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   538
      public static extern bool DeleteDC(IntPtr hdc);
moel@176
   539
      
moel@176
   540
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   541
      public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
moel@176
   542
moel@176
   543
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   544
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   545
      public static extern bool DeleteObject(IntPtr hObject);
moel@176
   546
moel@176
   547
      [DllImport(DWMAPI, CallingConvention = CallingConvention.Winapi)]
moel@176
   548
      public static extern int DwmSetWindowAttribute(IntPtr hwnd,
moel@176
   549
        WindowAttribute dwAttribute, ref bool pvAttribute, int cbAttribute);
moel@176
   550
    }    
moel@176
   551
  }
moel@183
   552
moel@183
   553
  public enum HitResult {
moel@183
   554
    Transparent = -1,
moel@183
   555
    Nowhere = 0,
moel@183
   556
    Client = 1,
moel@183
   557
    Caption = 2,
moel@183
   558
    Left = 10,
moel@183
   559
    Right = 11,
moel@183
   560
    Top = 12,
moel@183
   561
    TopLeft = 13,
moel@183
   562
    TopRight = 14,
moel@183
   563
    Bottom = 15,
moel@183
   564
    BottomLeft = 16,
moel@183
   565
    BottomRight = 17,
moel@183
   566
    Border = 18
moel@183
   567
  }
moel@183
   568
moel@183
   569
  public delegate void HitTestEventHandler(object sender, HitTestEventArgs e);
moel@183
   570
moel@183
   571
  public class HitTestEventArgs : EventArgs {
moel@183
   572
    public HitTestEventArgs(Point location, HitResult hitResult) {
moel@183
   573
      Location = location;
moel@183
   574
      HitResult = hitResult;
moel@183
   575
    }
moel@183
   576
    public Point Location { get; private set; }
moel@183
   577
    public HitResult HitResult { get; set; }
moel@183
   578
  }
moel@176
   579
}