GUI/GadgetWindow.cs
author moel.mich
Sun, 09 Jun 2013 16:44:19 +0000
changeset 397 243b6d5afa7c
parent 302 44c0e7f76e9e
permissions -rw-r--r--
Added an option to disable stacked axes in the plot.
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
}