GUI/GadgetWindow.cs
author moel.mich
Sun, 08 May 2011 22:10:13 +0000
changeset 279 6bce967ba1b5
parent 243 07a9329cd87c
child 302 44c0e7f76e9e
permissions -rw-r--r--
Fixed the bus and core clock reading on AMD family 10h model Ah CPUs. The new "Core Performance Boost" feature of these CPUs resulted in very low accuracy of the bus speed (and as a consequence also an inaccurate TSC multiplier). This fixed Issue 205.
moel@202
     1
/*
moel@176
     2
  
moel@176
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@176
     4
moel@176
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@176
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@176
     7
  the License. You may obtain a copy of the License at
moel@176
     8
 
moel@176
     9
  http://www.mozilla.org/MPL/
moel@176
    10
moel@176
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@176
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@176
    13
  for the specific language governing rights and limitations under the License.
moel@176
    14
moel@176
    15
  The Original Code is the Open Hardware Monitor code.
moel@176
    16
moel@176
    17
  The Initial Developer of the Original Code is 
moel@176
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@176
    19
  Portions created by the Initial Developer are Copyright (C) 2010
moel@176
    20
  the Initial Developer. All Rights Reserved.
moel@176
    21
moel@176
    22
  Contributor(s):
moel@176
    23
moel@176
    24
  Alternatively, the contents of this file may be used under the terms of
moel@176
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@176
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@176
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@176
    28
  of those above. If you wish to allow use of your version of this file only
moel@176
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@176
    30
  use your version of this file under the terms of the MPL, indicate your
moel@176
    31
  decision by deleting the provisions above and replace them with the notice
moel@176
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@176
    33
  the provisions above, a recipient may use your version of this file under
moel@176
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@176
    35
 
moel@176
    36
*/
moel@176
    37
moel@176
    38
using System;
moel@176
    39
using System.Drawing;
moel@176
    40
using System.Reflection;
moel@176
    41
using System.Runtime.InteropServices;
moel@176
    42
using System.Windows.Forms;
moel@176
    43
moel@176
    44
namespace OpenHardwareMonitor.GUI {
moel@183
    45
moel@176
    46
  public class GadgetWindow : NativeWindow {
moel@176
    47
moel@176
    48
    private bool visible = false;
moel@183
    49
    private bool lockPositionAndSize = false;
moel@176
    50
    private bool alwaysOnTop = false;
moel@176
    51
    private byte opacity = 255;
moel@176
    52
    private Point location = new Point(100, 100);
moel@176
    53
    private Size size = new Size(130, 84);
moel@176
    54
    private ContextMenu contextMenu = null;
moel@176
    55
    private MethodInfo commandDispatch;
moel@176
    56
moel@176
    57
    public GadgetWindow() {
moel@176
    58
      Type commandType = 
moel@176
    59
        typeof(Form).Assembly.GetType("System.Windows.Forms.Command");
moel@176
    60
      commandDispatch = commandType.GetMethod("DispatchID", 
moel@176
    61
        BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, 
moel@176
    62
        null, new Type[]{ typeof(int) }, null);
moel@176
    63
moel@176
    64
      this.CreateHandle(CreateParams);
moel@176
    65
moel@176
    66
      // move window to the bottom
moel@176
    67
      MoveToBottom(Handle);
moel@176
    68
moel@176
    69
      // prevent window from fading to a glass sheet when peek is invoked
moel@176
    70
      try {
moel@176
    71
        bool value = true;
moel@202
    72
        NativeMethods.DwmSetWindowAttribute(Handle,
moel@176
    73
          WindowAttribute.DWMWA_EXCLUDED_FROM_PEEK, ref value,
moel@176
    74
          Marshal.SizeOf(value));
moel@176
    75
      } catch (DllNotFoundException) { } catch (EntryPointNotFoundException) { }
moel@176
    76
    }
moel@176
    77
moel@176
    78
    private void ShowDesktopChanged(bool showDesktop) {
moel@176
    79
      if (showDesktop) {
moel@176
    80
        MoveToTopMost(Handle);
moel@176
    81
      } else {
moel@176
    82
        MoveToBottom(Handle);
moel@176
    83
      }
moel@176
    84
    }
moel@176
    85
moel@176
    86
    private void MoveToBottom(IntPtr handle) {
moel@176
    87
      NativeMethods.SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0,
moel@176
    88
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
moel@176
    89
    }
moel@176
    90
moel@176
    91
    private void MoveToTopMost(IntPtr handle) {
moel@176
    92
      NativeMethods.SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0,
moel@176
    93
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
moel@176
    94
    }
moel@176
    95
moel@176
    96
    private void ShowContextMenu(Point position) {
moel@176
    97
      NativeMethods.TrackPopupMenuEx(contextMenu.Handle, 
moel@176
    98
        TPM_RIGHTBUTTON | TPM_VERTICAL, position.X,
moel@176
    99
        position.Y, Handle, IntPtr.Zero);
moel@176
   100
    }
moel@176
   101
moel@176
   102
    protected virtual CreateParams CreateParams {
moel@176
   103
      get {
moel@183
   104
        CreateParams cp = new CreateParams();        
moel@183
   105
        cp.Width = 4096;
moel@183
   106
        cp.Height = 4096;
moel@176
   107
        cp.X = location.X;
moel@176
   108
        cp.Y = location.Y;
moel@176
   109
        cp.ExStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW;
moel@176
   110
        return cp;
moel@176
   111
      }
moel@176
   112
    }
moel@176
   113
moel@176
   114
    protected override void WndProc(ref Message message) {
moel@176
   115
      switch (message.Msg) {
moel@183
   116
        case WM_COMMAND: {
moel@183
   117
            // need to dispatch the message for the context menu
moel@183
   118
            if (message.LParam == IntPtr.Zero)
moel@183
   119
              commandDispatch.Invoke(null, new object[] { 
moel@183
   120
              message.WParam.ToInt32() & 0xFFFF });
moel@183
   121
          } break;
moel@183
   122
        case WM_NCHITTEST: {
moel@183
   123
            message.Result = (IntPtr)HitResult.Caption;
moel@183
   124
            if (HitTest != null) {
moel@183
   125
              Point p = new Point(
paulwerelds@208
   126
                Macros.GET_X_LPARAM(message.LParam) - location.X,
paulwerelds@208
   127
                Macros.GET_Y_LPARAM(message.LParam) - location.Y
paulwerelds@208
   128
              );
moel@183
   129
              HitTestEventArgs e = new HitTestEventArgs(p, HitResult.Caption);
moel@183
   130
              HitTest(this, e);
moel@183
   131
              message.Result = (IntPtr)e.HitResult;
moel@183
   132
            }
moel@183
   133
          } break;
moel@183
   134
        case WM_NCLBUTTONDBLCLK: {
moel@244
   135
            if (MouseDoubleClick != null) {
moel@244
   136
              MouseDoubleClick(this, new MouseEventArgs(MouseButtons.Left, 2,
moel@244
   137
                Macros.GET_X_LPARAM(message.LParam) - location.X,
moel@244
   138
                Macros.GET_Y_LPARAM(message.LParam) - location.Y, 0));
moel@244
   139
            }
moel@183
   140
            message.Result = IntPtr.Zero;
moel@183
   141
          } break;
moel@183
   142
        case WM_NCRBUTTONDOWN: {
moel@183
   143
            message.Result = IntPtr.Zero;
moel@183
   144
          } break;
moel@183
   145
        case WM_NCRBUTTONUP: {
moel@183
   146
            if (contextMenu != null)
moel@183
   147
              ShowContextMenu(new Point(
paulwerelds@209
   148
                Macros.GET_X_LPARAM(message.LParam),
paulwerelds@209
   149
                Macros.GET_Y_LPARAM(message.LParam)
paulwerelds@209
   150
              ));
moel@183
   151
            message.Result = IntPtr.Zero;
moel@183
   152
          } break;
moel@183
   153
        case WM_WINDOWPOSCHANGING: {
moel@183
   154
            WindowPos wp = (WindowPos)Marshal.PtrToStructure(
moel@183
   155
              message.LParam, typeof(WindowPos));
moel@183
   156
            
moel@183
   157
            if (!lockPositionAndSize) {
moel@183
   158
              // prevent the window from leaving the screen
moel@183
   159
              if ((wp.flags & SWP_NOMOVE) == 0) {
moel@243
   160
                Rectangle rect = Screen.GetWorkingArea(
moel@243
   161
                  new Rectangle(wp.x, wp.y, wp.cx, wp.cy));
moel@183
   162
                const int margin = 16;
moel@183
   163
                wp.x = Math.Max(wp.x, rect.Left - wp.cx + margin);
moel@183
   164
                wp.x = Math.Min(wp.x, rect.Right - margin);
moel@183
   165
                wp.y = Math.Max(wp.y, rect.Top - wp.cy + margin);
moel@183
   166
                wp.y = Math.Min(wp.y, rect.Bottom - margin);
moel@183
   167
              }
moel@176
   168
moel@183
   169
              // update location and fire event
moel@183
   170
              if ((wp.flags & SWP_NOMOVE) == 0) {
moel@183
   171
                if (location.X != wp.x || location.Y != wp.y) {
moel@183
   172
                  location = new Point(wp.x, wp.y);
moel@183
   173
                  if (LocationChanged != null)
moel@183
   174
                    LocationChanged(this, EventArgs.Empty);
moel@183
   175
                }
moel@183
   176
              }
moel@176
   177
moel@183
   178
              // update size and fire event
moel@183
   179
              if ((wp.flags & SWP_NOSIZE) == 0) {
moel@183
   180
                if (size.Width != wp.cx || size.Height != wp.cy) {
moel@183
   181
                  size = new Size(wp.cx, wp.cy);
moel@183
   182
                  if (SizeChanged != null)
moel@183
   183
                    SizeChanged(this, EventArgs.Empty);
moel@183
   184
                }
moel@183
   185
              } 
moel@176
   186
moel@183
   187
              // update the size of the layered window
moel@183
   188
              if ((wp.flags & SWP_NOSIZE) == 0) {
moel@183
   189
                NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero,
moel@183
   190
                  IntPtr.Zero, ref size, IntPtr.Zero, IntPtr.Zero, 0,
moel@183
   191
                  IntPtr.Zero, 0);                
moel@183
   192
              }
moel@183
   193
moel@183
   194
              // update the position of the layered window
moel@183
   195
              if ((wp.flags & SWP_NOMOVE) == 0) {
moel@183
   196
                NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 
moel@183
   197
                  location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | 
moel@183
   198
                  SWP_NOZORDER | SWP_NOSENDCHANGING);
moel@183
   199
              }
moel@176
   200
            }
moel@183
   201
            
moel@183
   202
            // do not forward any move or size messages
moel@243
   203
            wp.flags |= SWP_NOSIZE | SWP_NOMOVE;
moel@243
   204
moel@243
   205
            // suppress any frame changed events
moel@243
   206
            wp.flags &= ~SWP_FRAMECHANGED;
moel@243
   207
moel@183
   208
            Marshal.StructureToPtr(wp, message.LParam, false);                      
moel@183
   209
            message.Result = IntPtr.Zero;
moel@183
   210
          } break;
moel@183
   211
        default: {
moel@183
   212
            base.WndProc(ref message);
moel@183
   213
          } break;
moel@176
   214
      }      
moel@176
   215
    }
moel@176
   216
moel@176
   217
    private BlendFunction CreateBlendFunction() {
moel@176
   218
      BlendFunction blend = new BlendFunction();
moel@176
   219
      blend.BlendOp = AC_SRC_OVER;
moel@176
   220
      blend.BlendFlags = 0;
moel@176
   221
      blend.SourceConstantAlpha = opacity;
moel@176
   222
      blend.AlphaFormat = AC_SRC_ALPHA;
moel@176
   223
      return blend;
moel@176
   224
    }
moel@176
   225
moel@176
   226
    public void Update(Bitmap bitmap) {
moel@176
   227
      IntPtr screen = NativeMethods.GetDC(IntPtr.Zero);
moel@176
   228
      IntPtr memory = NativeMethods.CreateCompatibleDC(screen);
moel@176
   229
      IntPtr newHBitmap = IntPtr.Zero;
moel@176
   230
      IntPtr oldHBitmap = IntPtr.Zero;
moel@176
   231
moel@176
   232
      try {
moel@176
   233
        newHBitmap = bitmap.GetHbitmap(Color.Black);
moel@176
   234
        oldHBitmap = NativeMethods.SelectObject(memory, newHBitmap);
moel@176
   235
moel@176
   236
        Point pointSource = Point.Empty;
moel@183
   237
        BlendFunction blend = CreateBlendFunction();
moel@176
   238
moel@183
   239
        NativeMethods.UpdateLayeredWindow(Handle, screen, IntPtr.Zero,
moel@176
   240
          ref size, memory, ref pointSource, 0, ref blend, ULW_ALPHA);
moel@183
   241
moel@183
   242
        // make sure the window is at the right location
moel@183
   243
        NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 
moel@183
   244
          location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | 
moel@183
   245
          SWP_NOZORDER | SWP_NOSENDCHANGING);
moel@183
   246
moel@183
   247
      } finally {        
moel@176
   248
        if (newHBitmap != IntPtr.Zero) {
moel@176
   249
          NativeMethods.SelectObject(memory, oldHBitmap);
moel@176
   250
          NativeMethods.DeleteObject(newHBitmap);
moel@176
   251
        }
moel@176
   252
        NativeMethods.DeleteDC(memory);
moel@183
   253
        NativeMethods.ReleaseDC(IntPtr.Zero, screen);
moel@176
   254
      }
moel@176
   255
    }
moel@176
   256
moel@176
   257
    public byte Opacity {
moel@176
   258
      get {
moel@176
   259
        return opacity;
moel@176
   260
      }
moel@176
   261
      set {
moel@176
   262
        if (opacity != value) {
moel@176
   263
          opacity = value;
moel@176
   264
          BlendFunction blend = CreateBlendFunction();
moel@176
   265
          NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
moel@176
   266
            IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, ref blend, ULW_ALPHA);
moel@176
   267
        }
moel@176
   268
      }
moel@176
   269
    }
moel@176
   270
moel@176
   271
    public bool Visible {
moel@176
   272
      get {
moel@176
   273
        return visible;
moel@176
   274
      }
moel@176
   275
      set {
moel@176
   276
        if (visible != value) {
moel@176
   277
          visible = value;
moel@176
   278
          NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 0, 0, 0, 0,
moel@176
   279
            SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER |
moel@176
   280
            (value ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
moel@180
   281
          if (value) {
moel@180
   282
            if (!alwaysOnTop)
moel@180
   283
              ShowDesktop.Instance.ShowDesktopChanged += ShowDesktopChanged;
moel@180
   284
          } else {
moel@180
   285
            if (!alwaysOnTop)
moel@180
   286
              ShowDesktop.Instance.ShowDesktopChanged -= ShowDesktopChanged;
moel@180
   287
          }
moel@176
   288
        }
moel@176
   289
      }
moel@176
   290
    }
moel@176
   291
moel@183
   292
    // if locked, the window can not be moved or resized
moel@183
   293
    public bool LockPositionAndSize {
moel@176
   294
      get {
moel@183
   295
        return lockPositionAndSize;
moel@176
   296
      }
moel@176
   297
      set {
moel@183
   298
        lockPositionAndSize = value;
moel@176
   299
      }
moel@176
   300
    }
moel@176
   301
moel@176
   302
    public bool AlwaysOnTop {
moel@176
   303
      get {
moel@176
   304
        return alwaysOnTop;
moel@176
   305
      }
moel@176
   306
      set {
moel@176
   307
        if (value != alwaysOnTop) {
moel@176
   308
          alwaysOnTop = value;
moel@176
   309
          if (alwaysOnTop) {
moel@180
   310
            if (visible)
moel@180
   311
              ShowDesktop.Instance.ShowDesktopChanged -= ShowDesktopChanged;
moel@176
   312
            MoveToTopMost(Handle);            
moel@176
   313
          } else {
moel@176
   314
            MoveToBottom(Handle);
moel@180
   315
            if (visible)
moel@180
   316
              ShowDesktop.Instance.ShowDesktopChanged += ShowDesktopChanged;
moel@176
   317
          }
moel@176
   318
        }
moel@176
   319
      }
moel@176
   320
    }
moel@176
   321
moel@176
   322
    public Size Size {
moel@176
   323
      get {
moel@176
   324
        return size; 
moel@176
   325
      }
moel@176
   326
      set {
moel@176
   327
        if (size != value) {
moel@176
   328
          size = value;
moel@183
   329
          NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero,
moel@183
   330
            ref size, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero, 0);                    
moel@183
   331
          if (SizeChanged != null)
moel@183
   332
            SizeChanged(this, EventArgs.Empty);
moel@176
   333
        }
moel@176
   334
      }
moel@176
   335
    }
moel@176
   336
moel@183
   337
    public event EventHandler SizeChanged;
moel@183
   338
moel@176
   339
    public Point Location {
moel@176
   340
      get {
moel@176
   341
        return location;
moel@176
   342
      }
moel@176
   343
      set {
moel@183
   344
        if (location != value) {
moel@183
   345
          location = value;
moel@183
   346
          NativeMethods.SetWindowPos(Handle, IntPtr.Zero, 
moel@183
   347
            location.X, location.Y, 0, 0, 
moel@183
   348
            SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING);          
moel@183
   349
          if (LocationChanged != null)
moel@183
   350
            LocationChanged(this, EventArgs.Empty);
moel@183
   351
        }
moel@176
   352
      }
moel@176
   353
    }
moel@176
   354
moel@176
   355
    public event EventHandler LocationChanged;
moel@176
   356
moel@176
   357
    public ContextMenu ContextMenu {
moel@176
   358
      get {
moel@176
   359
        return contextMenu;
moel@176
   360
      }
moel@176
   361
      set {
moel@176
   362
        this.contextMenu = value;
moel@176
   363
      }
moel@176
   364
    }
moel@176
   365
moel@183
   366
    public event HitTestEventHandler HitTest;
moel@183
   367
moel@244
   368
    public event MouseEventHandler MouseDoubleClick;
moel@244
   369
moel@176
   370
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@176
   371
    private struct BlendFunction {
moel@176
   372
      public byte BlendOp;
moel@176
   373
      public byte BlendFlags;
moel@176
   374
      public byte SourceConstantAlpha;
moel@176
   375
      public byte AlphaFormat;
moel@176
   376
    }
moel@176
   377
moel@176
   378
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@176
   379
    private struct WindowPos {
moel@176
   380
      public IntPtr hwnd;
moel@176
   381
      public IntPtr hwndInsertAfter;
moel@176
   382
      public int x;
moel@176
   383
      public int y;
moel@176
   384
      public int cx;
moel@176
   385
      public int cy;
moel@176
   386
      public uint flags;
moel@176
   387
    }
moel@176
   388
moel@176
   389
    public static readonly IntPtr HWND_BOTTOM = (IntPtr)1;
moel@176
   390
    public static readonly IntPtr HWND_TOPMOST = (IntPtr)(-1);
moel@176
   391
moel@176
   392
    public const int WS_EX_LAYERED = 0x00080000;
moel@176
   393
    public const int WS_EX_TOOLWINDOW = 0x00000080;
moel@176
   394
moel@176
   395
    public const uint SWP_NOSIZE = 0x0001;
moel@176
   396
    public const uint SWP_NOMOVE = 0x0002;
moel@176
   397
    public const uint SWP_NOACTIVATE = 0x0010;
moel@243
   398
    public const uint SWP_FRAMECHANGED = 0x0020;
moel@176
   399
    public const uint SWP_HIDEWINDOW = 0x0080;
moel@176
   400
    public const uint SWP_SHOWWINDOW = 0x0040;
moel@176
   401
    public const uint SWP_NOZORDER = 0x0004;
moel@176
   402
    public const uint SWP_NOSENDCHANGING = 0x0400;
moel@176
   403
moel@176
   404
    public const int ULW_COLORKEY = 0x00000001;
moel@176
   405
    public const int ULW_ALPHA = 0x00000002;
moel@176
   406
    public const int ULW_OPAQUE = 0x00000004;
moel@176
   407
moel@176
   408
    public const byte AC_SRC_OVER = 0x00;
moel@176
   409
    public const byte AC_SRC_ALPHA = 0x01;
moel@176
   410
moel@176
   411
    public const int WM_NCHITTEST = 0x0084;
moel@176
   412
    public const int WM_NCLBUTTONDBLCLK = 0x00A3;
moel@176
   413
    public const int WM_NCLBUTTONDOWN = 0x00A1;
moel@176
   414
    public const int WM_NCLBUTTONUP = 0x00A2;
moel@176
   415
    public const int WM_NCRBUTTONDOWN = 0x00A4;
moel@176
   416
    public const int WM_NCRBUTTONUP = 0x00A5;
moel@176
   417
    public const int WM_WINDOWPOSCHANGING = 0x0046;
moel@176
   418
    public const int WM_COMMAND = 0x0111;
moel@176
   419
moel@176
   420
    public const int TPM_RIGHTBUTTON = 0x0002;
moel@176
   421
    public const int TPM_VERTICAL = 0x0040;
moel@176
   422
moel@176
   423
    private enum WindowAttribute : int {
moel@176
   424
      DWMWA_NCRENDERING_ENABLED = 1,
moel@176
   425
      DWMWA_NCRENDERING_POLICY,
moel@176
   426
      DWMWA_TRANSITIONS_FORCEDISABLED,
moel@176
   427
      DWMWA_ALLOW_NCPAINT,
moel@176
   428
      DWMWA_CAPTION_BUTTON_BOUNDS,
moel@176
   429
      DWMWA_NONCLIENT_RTL_LAYOUT,
moel@176
   430
      DWMWA_FORCE_ICONIC_REPRESENTATION,
moel@176
   431
      DWMWA_FLIP3D_POLICY,
moel@176
   432
      DWMWA_EXTENDED_FRAME_BOUNDS,
moel@176
   433
      DWMWA_HAS_ICONIC_BITMAP,
moel@176
   434
      DWMWA_DISALLOW_PEEK,
moel@176
   435
      DWMWA_EXCLUDED_FROM_PEEK,
moel@176
   436
      DWMWA_LAST
moel@176
   437
    }
moel@176
   438
paulwerelds@208
   439
    /// <summary>
paulwerelds@208
   440
    /// Some macros imported and converted from the Windows SDK
paulwerelds@208
   441
    /// </summary>
paulwerelds@208
   442
    private static class Macros {
paulwerelds@210
   443
      public static ushort LOWORD(IntPtr l) {
paulwerelds@210
   444
        return (ushort) ((ulong)l & 0xFFFF);
paulwerelds@208
   445
      }
paulwerelds@208
   446
      
paulwerelds@208
   447
      public static UInt16 HIWORD(IntPtr l) {
paulwerelds@210
   448
        return (ushort) (((ulong)l >> 16) & 0xFFFF);
paulwerelds@208
   449
      }
paulwerelds@208
   450
paulwerelds@208
   451
      public static int GET_X_LPARAM(IntPtr lp) {
paulwerelds@210
   452
        return (short) LOWORD(lp);
paulwerelds@208
   453
      }
paulwerelds@208
   454
paulwerelds@208
   455
      public static int GET_Y_LPARAM(IntPtr lp) {
paulwerelds@210
   456
        return (short) HIWORD(lp);
paulwerelds@208
   457
      }
paulwerelds@208
   458
    }
paulwerelds@208
   459
paulwerelds@208
   460
    /// <summary>
paulwerelds@208
   461
    /// Imported native methods
paulwerelds@208
   462
    /// </summary>
moel@176
   463
    private static class NativeMethods {
moel@176
   464
      private const string USER = "user32.dll";
moel@176
   465
      private const string GDI = "gdi32.dll";
moel@176
   466
      public const string DWMAPI = "dwmapi.dll";
moel@176
   467
moel@176
   468
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   469
      [return: MarshalAs(UnmanagedType.Bool)]
moel@183
   470
      public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
moel@183
   471
        IntPtr pptDst, ref Size psize, IntPtr hdcSrc, IntPtr pprSrc,
moel@183
   472
        int crKey, IntPtr pblend, int dwFlags);
moel@183
   473
moel@183
   474
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@183
   475
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   476
      public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, 
moel@183
   477
        IntPtr pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, 
moel@176
   478
        int crKey, ref BlendFunction pblend, int dwFlags);
moel@176
   479
moel@176
   480
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   481
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   482
      public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
moel@176
   483
        IntPtr pptDst, IntPtr psize, IntPtr hdcSrc, IntPtr pprSrc,
moel@176
   484
        int crKey, ref BlendFunction pblend, int dwFlags);  
moel@176
   485
moel@176
   486
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   487
      public static extern IntPtr GetDC(IntPtr hWnd);
moel@176
   488
moel@176
   489
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   490
      public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
moel@176
   491
moel@176
   492
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   493
      public static extern bool SetWindowPos(IntPtr hWnd,
moel@176
   494
        IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
moel@176
   495
moel@176
   496
      [DllImport(USER, CallingConvention = CallingConvention.Winapi)]
moel@176
   497
      public static extern bool TrackPopupMenuEx(IntPtr hMenu, uint uFlags, 
moel@176
   498
        int x, int y, IntPtr hWnd, IntPtr tpmParams);
moel@176
   499
moel@176
   500
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   501
      public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
moel@176
   502
moel@176
   503
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   504
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   505
      public static extern bool DeleteDC(IntPtr hdc);
moel@176
   506
      
moel@176
   507
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   508
      public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
moel@176
   509
moel@176
   510
      [DllImport(GDI, CallingConvention = CallingConvention.Winapi)]
moel@176
   511
      [return: MarshalAs(UnmanagedType.Bool)]
moel@176
   512
      public static extern bool DeleteObject(IntPtr hObject);
moel@176
   513
moel@176
   514
      [DllImport(DWMAPI, CallingConvention = CallingConvention.Winapi)]
moel@176
   515
      public static extern int DwmSetWindowAttribute(IntPtr hwnd,
moel@176
   516
        WindowAttribute dwAttribute, ref bool pvAttribute, int cbAttribute);
moel@176
   517
    }    
moel@176
   518
  }
moel@183
   519
moel@183
   520
  public enum HitResult {
moel@183
   521
    Transparent = -1,
moel@183
   522
    Nowhere = 0,
moel@183
   523
    Client = 1,
moel@183
   524
    Caption = 2,
moel@183
   525
    Left = 10,
moel@183
   526
    Right = 11,
moel@183
   527
    Top = 12,
moel@183
   528
    TopLeft = 13,
moel@183
   529
    TopRight = 14,
moel@183
   530
    Bottom = 15,
moel@183
   531
    BottomLeft = 16,
moel@183
   532
    BottomRight = 17,
moel@183
   533
    Border = 18
moel@183
   534
  }
moel@183
   535
moel@183
   536
  public delegate void HitTestEventHandler(object sender, HitTestEventArgs e);
moel@183
   537
moel@183
   538
  public class HitTestEventArgs : EventArgs {
moel@183
   539
    public HitTestEventArgs(Point location, HitResult hitResult) {
moel@183
   540
      Location = location;
moel@183
   541
      HitResult = hitResult;
moel@183
   542
    }
moel@183
   543
    public Point Location { get; private set; }
moel@183
   544
    public HitResult HitResult { get; set; }
moel@183
   545
  }
moel@176
   546
}