check point

This commit is contained in:
meelstorm
2025-07-14 12:03:59 +02:00
commit d3cb790bd9
431 changed files with 44078 additions and 0 deletions

View File

@@ -0,0 +1,279 @@
#region The MIT License (MIT)
//
// Copyright (c) 2011 Robert Prouse http://www.alteridem.net
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
#region Using Directives
using System;
using System.Drawing;
#endregion
namespace MaterialSkin.Gesture
{
#region GestureEventArgs Class
/// <summary>
/// Base class for all the gesture based events
/// </summary>
public abstract class GestureEventArgs : EventArgs
{
internal GestureEventArgs( GestureInfo info )
{
Location = new Point( info.location.x, info.location.y );
Info = info;
Handled = true;
}
#region Helper Methods
protected static int LoDWord( IntPtr lParam )
{
return LoDWord( lParam.ToInt64() );
}
protected static int HiDWord( IntPtr lParam )
{
return HiDWord( lParam.ToInt64() );
}
protected static int LoDWord( long l )
{
return (int)(l & 0xFFFFFFFF);
}
protected static int HiDWord( long l )
{
return (int)((l >> 32) & 0xFFFFFFFF);
}
protected static short LoWord( int i )
{
return (short)(i & 0xFFFF);
}
protected static short HiWord( int i )
{
return (short)((i >> 16) & 0xFFFF);
}
#endregion
#region Properties
protected GestureInfo Info { get; set; }
/// <summary>
/// Gets the location of the gesture in Screen (not client) coordinates.
/// </summary>
public Point Location { get; private set; }
/// <summary>
/// Gets a value indicating whether this <see cref="GestureEventArgs"/> is beginning.
/// </summary>
public bool Begin
{
get { return Info.Begin; }
}
/// <summary>
/// Gets a value indicating whether this <see cref="GestureEventArgs"/> is ending
/// </summary>
public bool End
{
get { return Info.End; }
}
/// <summary>
/// Gets or sets a value indicating whether the window message was handled. Set this to false if you don't handle the message.
/// </summary>
public bool Handled { get; set; }
#endregion
}
#endregion
#region PanEventArgs Class
/// <summary>
/// Event for the Pan gesture
/// </summary>
public class PanEventArgs : GestureEventArgs
{
internal PanEventArgs( GestureInfo info, Point lastPanPoint )
: base( info )
{
int hiword = HiDWord( info.arguments );
InertiaVector = new Point( LoWord( hiword ), HiWord( hiword ) );
PanOffset = new Point( Location.X - lastPanPoint.X, Location.Y - lastPanPoint.Y );
}
/// <summary>
/// Gets a value indicating whether this <see cref="GestureEventArgs"/> has triggered inertia.
/// </summary>
public bool Inertia
{
get { return Info.Inertia; }
}
public Point InertiaVector { get; private set; }
/// <summary>
/// Gets the pan offset since the last pan message.
/// </summary>
public Point PanOffset { get; private set; }
}
#endregion
#region ZoomEventArgs Class
/// <summary>
/// Event for the Zoom gesture
/// </summary>
public class ZoomEventArgs : GestureEventArgs
{
internal ZoomEventArgs( GestureInfo info, long lastZoomDistance )
: base( info )
{
Distance = info.arguments;
PercentChange = (double)Distance / lastZoomDistance;
}
/// <summary>
/// Gets the distance between the two points as they are being zoomed.
/// </summary>
public long Distance { get; private set; }
/// <summary>
/// Gets the percent changed since the last zoom message
/// </summary>
public double PercentChange { get; private set; }
}
#endregion
#region PressAndTapEventArgs Class
/// <summary>
/// Event for the Press and Tap gesture
/// </summary>
public class PressAndTapEventArgs : GestureEventArgs
{
internal PressAndTapEventArgs( GestureInfo info )
: base( info )
{
int pointsStruct = LoDWord( info.arguments );
Distance = new Point( LoWord( pointsStruct ), HiWord( pointsStruct ) );
}
/// <summary>
/// Gets the distance between the two points.
/// </summary>
public Point Distance { get; private set; }
}
#endregion
#region RotateEventArgs Class
/// <summary>
/// Event for the Rotate gesture
/// </summary>
public class RotateEventArgs : GestureEventArgs
{
internal RotateEventArgs( GestureInfo info, double lastRotation )
: base( info )
{
int loword = LoDWord( info.arguments );
TotalAngle = RotateAngleFromArgument( loword );
Angle = TotalAngle - lastRotation;
string msg = string.Format("Total:{0} Angle:{1} Last:{2}", TotalAngle, Angle, lastRotation );
System.Diagnostics.Debug.WriteLine( msg );
}
/// <summary>
/// Gesture argument helper that converts an argument to a rotation angle.
/// </summary>
/// <param name="arg">The argument to convert. Should be an unsigned 16-bit value.</param>
/// <returns></returns>
private static double RotateAngleFromArgument( int arg )
{
return ((arg / 65535.0) * 4.0 * Math.PI) - 2.0 * Math.PI;
}
/// <summary>
/// Gets the angle of rotation in Radians since the beginning of the gesture
/// </summary>
public double TotalAngle { get; private set; }
/// <summary>
/// Gets the angle of rotation in Degrees since the beginning of the gesture
/// </summary>
public double TotalDegrees
{
get { return RadiandsToDegrees( TotalAngle ); }
}
/// <summary>
/// Gets the angle of rotation in Radians since the last rotation message
/// </summary>
public double Angle { get; private set; }
/// <summary>
/// Gets the angle of rotation in Degrees since the last rotation message
/// </summary>
public double Degrees
{
get { return RadiandsToDegrees( Angle ); }
}
private double RadiandsToDegrees( double radians )
{
return radians * 180.0 / Math.PI;
}
}
#endregion
#region TwoFingerTapEventArgs Class
/// <summary>
/// Base class for the Two Finger Tap gesture
/// </summary>
public class TwoFingerTapEventArgs : GestureEventArgs
{
internal TwoFingerTapEventArgs( GestureInfo info )
: base( info )
{
Distance = info.arguments;
}
/// <summary>
/// Gets the distance between the two points.
/// </summary>
public long Distance { get; private set; }
}
#endregion
}

View File

@@ -0,0 +1,446 @@
#region The MIT License (MIT)
//
// Copyright (c) 2011 Robert Prouse http://www.alteridem.net
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
#region Using Directives
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading.Tasks;
using System.Windows.Forms;
#endregion
namespace MaterialSkin.Gesture
{
[PermissionSet( SecurityAction.Demand, Name = "FullTrust" )]
public sealed class GestureListener : NativeWindow
{
#region Private Members
// Saved state
private Point _lastPanPoint;
private double _lastRotation;
private long _lastZoom;
private readonly Control _parent;
private readonly GestureConfig[] m_configs;
private int _touchInputSize;
#endregion
#region Public Events
public event EventHandler<PanEventArgs> Pan;
public event EventHandler<PressAndTapEventArgs> PressAndTap;
public event EventHandler<RotateEventArgs> Rotate;
public event EventHandler<TwoFingerTapEventArgs> TwoFingerTap;
public event EventHandler<ZoomEventArgs> Zoom;
#endregion
#region Construction
/// <summary>
/// Initializes a new instance of the <see cref="GestureListener"/> class to receive all gestures.
/// </summary>
/// <param name="parent">The parent.</param>
public GestureListener( Control parent )
: this( parent, new[] { new GestureConfig( 0, GestureConfigurationFlag.GC_ALLGESTURES, 0 ) } )
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GestureListener"/> class to receive specific gestures.
/// </summary>
/// <param name="parent">The parent.</param>
/// <param name="configs">The gesture configurations.</param>
public GestureListener( Control parent, GestureConfig[] configs )
{
if ( parent.IsHandleCreated )
{
Initialize( parent );
}
else
{
parent.HandleCreated += OnHandleCreated;
}
parent.HandleDestroyed += OnHandleDestroyed;
_parent = parent;
m_configs = configs;
_touchInputSize = Marshal.SizeOf(new TOUCHINPUT());
}
#endregion
#region Private Methods
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RegisterTouchWindow(System.IntPtr hWnd, ulong ulFlags);
private void Initialize( Control parent )
{
AssignHandle( parent.Handle );
NativeMethods.SetGestureConfig( parent.Handle, m_configs );
}
public void LoadMultitouch()
{
Task.Run(async () =>
{
await Task.Delay(1000);
Action a = () =>
{
if (!RegisterTouchWindow(_parent.Handle, 0))
{
}
};
_parent.Invoke(a);
});
}
private void OnHandleCreated( object sender, EventArgs e )
{
// Window is now created, assign handle to NativeWindow.
var control = sender as Control;
if ( control != null )
{
Initialize( control );
}
}
private void OnHandleDestroyed( object sender, EventArgs e )
{
// Window was destroyed, release hook.
ReleaseHandle();
}
#endregion
#region WndProc
/// <summary>
/// Invokes the default window procedure associated with this window.
/// </summary>
/// <param name="m">A <see cref="T:System.Windows.Forms.Message"/> that is associated with the current Windows message.</param>
[PermissionSet( SecurityAction.Demand, Name = "FullTrust" )]
protected override void WndProc( ref Message m )
{
bool handled = false;
// Listen for operating system messages
switch ( m.Msg )
{
case WindowMessage.WM_GESTURE:
GestureInfo info;
if ( NativeMethods.GetGestureInfo( m.LParam, out info ) )
{
switch ( (GestureId)info.id )
{
case GestureId.Pan:
handled = OnPan( info );
break;
case GestureId.PressAndTap:
handled = OnPressAndTap( info );
break;
case GestureId.Rotate:
handled = OnRotate( info );
break;
case GestureId.TwoFingerTap:
handled = OnTwoFingerTap( info );
break;
case GestureId.Zoom:
handled = OnZoom( info );
break;
}
if ( handled )
{
NativeMethods.CloseGestureInfoHandle( m.LParam );
}
}
break;
case WindowMessage.WM_TOUCH:
MessageBox.Show("touch");
this.DecodeTouch(ref m);
break;
//case WindowMessage.WM_POINTERUPDATE:
// MessageBox.Show("ptr");
// break;
}
if ( !handled )
{
base.WndProc( ref m );
}
}
private static int LoWord(int number)
{
return (number & 0xffff);
}
[StructLayout(LayoutKind.Sequential)]
private struct TOUCHINPUT
{
public int x;
public int y;
public System.IntPtr hSource;
public int dwID;
public int dwFlags;
public int dwMask;
public int dwTime;
public System.IntPtr dwExtraInfo;
public int cxContact;
public int cyContact;
}
[StructLayout(LayoutKind.Sequential)]
private struct POINTS
{
public short x;
public short y;
}
public event EventHandler<WMTouchEventArgs> Touchdown; // touch down event handler
public event EventHandler<WMTouchEventArgs> Touchup; // touch up event handler
public event EventHandler<WMTouchEventArgs> TouchMove; // touch move event handler
// EventArgs passed to Touch handlers
public class WMTouchEventArgs : System.EventArgs
{
// Private data members
private int x; // touch x client coordinate in pixels
private int y; // touch y client coordinate in pixels
private int id; // contact ID
private int mask; // mask which fields in the structure are valid
private int flags; // flags
private int time; // touch event time
private int contactX; // x size of the contact area in pixels
private int contactY; // y size of the contact area in pixels
// Access to data members
public int LocationX
{
get { return x; }
set { x = value; }
}
public int LocationY
{
get { return y; }
set { y = value; }
}
public int Id
{
get { return id; }
set { id = value; }
}
public int Flags
{
get { return flags; }
set { flags = value; }
}
public int Mask
{
get { return mask; }
set { mask = value; }
}
public int Time
{
get { return time; }
set { time = value; }
}
public int ContactX
{
get { return contactX; }
set { contactX = value; }
}
public int ContactY
{
get { return contactY; }
set { contactY = value; }
}
public bool IsPrimaryContact
{
get { return (flags & WindowMessage.TOUCHEVENTF_PRIMARY) != 0; }
}
// Constructor
public WMTouchEventArgs()
{
}
}
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetTouchInputInfo(System.IntPtr hTouchInput, int cInputs, [In, Out] TOUCHINPUT[] pInputs, int cbSize);
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern void CloseTouchInputHandle(System.IntPtr lParam);
public bool DecodeTouch(ref Message m)
{
// More than one touchinput may be associated with a touch message,
// so an array is needed to get all event information.
int inputCount = LoWord(m.WParam.ToInt32()); // Number of touch inputs, actual per-contact messages
TOUCHINPUT[] inputs; // Array of TOUCHINPUT structures
inputs = new TOUCHINPUT[inputCount]; // Allocate the storage for the parameters of the per-contact messages
// Unpack message parameters into the array of TOUCHINPUT structures, each
// representing a message for one single contact.
if (!GetTouchInputInfo(m.LParam, inputCount, inputs, _touchInputSize))
{
// Get touch info failed.
return false;
}
// For each contact, dispatch the message to the appropriate message
// handler.
bool handled = false; // Boolean, is message handled
for (int i = 0; i < inputCount; i++)
{
TOUCHINPUT ti = inputs[i];
// Assign a handler to this message.
EventHandler<WMTouchEventArgs> handler = null; // Touch event handler
if ((ti.dwFlags & WindowMessage.TOUCHEVENTF_DOWN) != 0)
{
handler = Touchdown;
}
else if ((ti.dwFlags & WindowMessage.TOUCHEVENTF_UP) != 0)
{
handler = Touchup;
}
else if ((ti.dwFlags & WindowMessage.TOUCHEVENTF_MOVE) != 0)
{
handler = TouchMove;
}
// Convert message parameters into touch event arguments and handle the event.
if (handler != null)
{
// Convert the raw touchinput message into a touchevent.
WMTouchEventArgs te = new WMTouchEventArgs(); // Touch event arguments
// TOUCHINFO point coordinates and contact size is in 1/100 of a pixel; convert it to pixels.
// Also convert screen to client coordinates.
te.ContactY = ti.cyContact / 100;
te.ContactX = ti.cxContact / 100;
te.Id = ti.dwID;
{
Point pt = _parent.PointToClient(new Point(ti.x / 100, ti.y / 100));
te.LocationX = pt.X;
te.LocationY = pt.Y;
}
te.Time = ti.dwTime;
te.Mask = ti.dwMask;
te.Flags = ti.dwFlags;
// Invoke the event handler.
handler(this, te);
// Mark this event as handled.
handled = true;
}
}
CloseTouchInputHandle(m.LParam);
return handled;
}
private bool OnPan( GestureInfo info )
{
if ( Pan != null )
{
if ( info.Begin )
{
_lastPanPoint = new Point( info.location.x, info.location.y );
}
var args = new PanEventArgs( info, _lastPanPoint );
_lastPanPoint = new Point( info.location.x, info.location.y );
Pan( this, args );
return args.Handled;
}
return false;
}
private bool OnPressAndTap( GestureInfo info )
{
if ( PressAndTap != null )
{
var args = new PressAndTapEventArgs( info );
PressAndTap( this, args );
return args.Handled;
}
return false;
}
private bool OnRotate( GestureInfo info )
{
if ( Rotate != null )
{
if ( info.Begin )
{
_lastRotation = 0;
}
var args = new RotateEventArgs( info, _lastRotation );
if ( !info.Begin )
{
// First rotation is the angle the fingers are at, so don't use it
_lastRotation = args.TotalAngle;
}
Rotate( this, args );
return args.Handled;
}
return false;
}
private bool OnTwoFingerTap( GestureInfo info )
{
if ( TwoFingerTap != null )
{
var args = new TwoFingerTapEventArgs( info );
TwoFingerTap( this, args );
return args.Handled;
}
return false;
}
private bool OnZoom( GestureInfo info )
{
if ( Zoom != null )
{
if ( info.Begin )
{
_lastZoom = info.arguments;
}
var args = new ZoomEventArgs( info, _lastZoom );
_lastZoom = args.Distance;
Zoom( this, args );
return args.Handled;
}
return false;
}
#endregion
}
}

View File

@@ -0,0 +1,341 @@
#region The MIT License (MIT)
//
// Copyright (c) 2011 Robert Prouse http://www.alteridem.net
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
#region Using Directives
using System;
using System.Runtime.InteropServices;
#endregion
namespace MaterialSkin.Gesture
{
internal static class NativeMethods
{
#region Private Delegates
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool GetGestureInfoPtr( IntPtr gestureInfoHandle, ref GestureInfo pGestureInfo );
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool CloseGestureInfoHandlePtr( IntPtr gestureInfoHandle );
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
private delegate bool SetGestureConfigPtr( IntPtr hwnd, uint reserved, uint ids, GestureConfig[] configs, uint size );
private static readonly GetGestureInfoPtr _pGetGestureInfoPtr;
private static readonly CloseGestureInfoHandlePtr _pCloseGestureInfoHandle;
private static readonly SetGestureConfigPtr _pSetGestureConfig;
#endregion
#region Static Construction
static NativeMethods()
{
var user32 = new UnmanagedLibrary( "user32" );
_pGetGestureInfoPtr = user32.GetUnmanagedFunction<GetGestureInfoPtr>( "GetGestureInfo" );
_pCloseGestureInfoHandle = user32.GetUnmanagedFunction<CloseGestureInfoHandlePtr>( "CloseGestureInfoHandle" );
_pSetGestureConfig = user32.GetUnmanagedFunction<SetGestureConfigPtr>( "SetGestureConfig" );
}
#endregion
#region Public Interface
/// <summary>
/// Registers the HWND to receive all gestures.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd353231%28v=vs.85%29.aspx
/// </remarks>
/// <param name="hwnd">The HWND.</param>
/// <returns></returns>
public static bool SetGestureConfig( IntPtr hwnd )
{
if ( _pSetGestureConfig == null )
return false;
var configs = new[] { new GestureConfig( 0, GestureConfigurationFlag.GC_ALLGESTURES, 0 ) };
return SetGestureConfig(hwnd, configs);
}
/// <summary>
/// Registers the HWND to receive specific gestures.
/// </summary>
/// <remarks>
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd353231%28v=vs.85%29.aspx
/// </remarks>
/// <param name="hwnd">The HWND.</param>
/// <param name="configs">The gesture configurations</param>
/// <returns></returns>
public static bool SetGestureConfig( IntPtr hwnd, GestureConfig[] configs )
{
return _pSetGestureConfig( hwnd, 0, 1, configs, (uint)Marshal.SizeOf( typeof( GestureConfig ) ) );
}
/// <summary>
/// Gets the gesture info.
/// </summary>
/// <param name="gestureInfoHandle">The gesture info handle.</param>
/// <param name="gestureInfo">The gesture info.</param>
/// <returns></returns>
public static bool GetGestureInfo( IntPtr gestureInfoHandle, out GestureInfo gestureInfo )
{
gestureInfo = new GestureInfo();
if ( _pGetGestureInfoPtr == null )
return false;
gestureInfo.size = Marshal.SizeOf( gestureInfo );
return _pGetGestureInfoPtr( gestureInfoHandle, ref gestureInfo );
}
/// <summary>
/// Closes the gesture info handle.
/// </summary>
/// <param name="gestureInfoHandle">The gesture info handle.</param>
/// <returns></returns>
public static bool CloseGestureInfoHandle( IntPtr gestureInfoHandle )
{
if ( _pCloseGestureInfoHandle == null )
return false;
return _pCloseGestureInfoHandle( gestureInfoHandle );
}
#endregion
}
/// <summary>
/// Gesture configuration flags
/// </summary>
internal static class GestureConfigurationFlag
{
public const int GC_ALLGESTURES = 0x00000001;
public const int GC_ZOOM = 0x00000001;
public const int GC_PAN = 0x00000001;
public const int GC_PAN_WITH_SINGLE_FINGER_VERTICALLY = 0x00000002;
public const int GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY = 0x00000004;
public const int GC_PAN_WITH_GUTTER = 0x00000008;
public const int GC_PAN_WITH_INERTIA = 0x00000010;
public const int GC_ROTATE = 0x00000001;
public const int GC_TWOFINGERTAP = 0x00000001;
public const int GC_PRESSANDTAP = 0x00000001;
}
/// <summary>
/// Gesture flags - GestureInfo.flags
/// </summary>
[Flags]
public enum GestureFlags
{
/// <summary>
/// GF_BEGIN
/// </summary>
Begin = 0x1,
/// <summary>
/// GF_INERTIA
/// </summary>
Inertia = 0x2,
/// <summary>
/// GF_END
/// </summary>
End = 0x4
}
/// <summary>
/// Gesture IDs - GestureInfo.id
/// </summary>
public enum GestureId
{
/// <summary>
/// GID_BEGIN
/// </summary>
Begin = 1,
/// <summary>
/// GID_END
/// </summary>
End = 2,
/// <summary>
/// GID_ZOOM
/// </summary>
Zoom = 3,
/// <summary>
/// GID_PAN
/// </summary>
Pan = 4,
/// <summary>
/// GID_ROTATE
/// </summary>
Rotate = 5,
/// <summary>
/// GID_TWOFINGERTAP
/// </summary>
TwoFingerTap = 6,
/// <summary>
/// GID_PRESSANDTAP
/// </summary>
PressAndTap = 7
}
/// <summary>
/// Window Messages
/// </summary>
internal static class WindowMessage
{
public const int WM_TOUCH = 0x0240;
public const int WM_POINTERUPDATE =0x0245;
public const int WM_GESTURE = 0x0119;
public const int WM_GESTURENOTIFY = 0x011A;
public const int TOUCHEVENTF_MOVE = 0x0001;
public const int TOUCHEVENTF_DOWN = 0x0002;
public const int TOUCHEVENTF_UP = 0x0004;
public const int TOUCHEVENTF_INRANGE = 0x0008;
public const int TOUCHEVENTF_PRIMARY = 0x0010;
public const int TOUCHEVENTF_NOCOALESCE = 0x0020;
public const int TOUCHEVENTF_PEN = 0x0040;
// Touch input mask values (TOUCHINPUT.dwMask) [winuser.h]
public const int TOUCHINPUTMASKF_TIMEFROMSYSTEM = 0x0001; // the dwTime field contains a system generated value
public const int TOUCHINPUTMASKF_EXTRAINFO = 0x0002; // the dwExtraInfo field is valid
public const int TOUCHINPUTMASKF_CONTACTAREA = 0x0004; // the cxContact and cyContact fields are valid
}
[StructLayout( LayoutKind.Sequential )]
public struct Points
{
public short x;
public short y;
}
/// <summary>
/// Gesture configuration structure
/// </summary>
/// <remarks>
/// Used in SetGestureConfig and GetGestureConfig
/// http://msdn.microsoft.com/en-us/library/windows/desktop/dd353231%28v=vs.85%29.aspx
/// </remarks>
[StructLayout( LayoutKind.Sequential )]
public struct GestureConfig
{
public GestureConfig( uint id, uint want, uint block )
{
Id = id;
Want = want;
Block = block;
}
/// <summary>
/// The identifier for the type of configuration that will have messages enabled or disabled.
/// </summary>
public uint Id;
/// <summary>
/// The messages to enable.
/// </summary>
public uint Want;
/// <summary>
/// The messages to disable.
/// </summary>
public uint Block;
}
/// <summary>
/// Stores information about a gesture.
/// </summary>
/// <remarks>
/// - Pass the HGESTUREINFO received in the WM_GESTURE message lParam into the
/// GetGestureInfo function to retrieve this information.
/// - If cbExtraArgs is non-zero, pass the HGESTUREINFO received in the WM_GESTURE
/// message lParam into the GetGestureExtraArgs function to retrieve extended
/// argument information.
/// </remarks>
[StructLayout( LayoutKind.Sequential )]
public struct GestureInfo
{
/// <summary>
/// The size of the structure, in bytes. The caller must set this.
/// </summary>
public int size;
/// <summary>
/// The state of the gesture. Contains GestureFlags.
/// </summary>
public int flags;
/// <summary>
/// The identifier of the gesture command. Contains GestureId.
/// </summary>
public int id;
/// <summary>
/// A handle to the window that is targeted by this gesture.
/// </summary>
public IntPtr hwnd;
/// <summary>
/// A Points structure containing the coordinates associated with the gesture. These coordinates are always relative to the origin of the screen.
/// </summary>
public Points location;
/// <summary>
/// An internally used identifier for the structure.
/// </summary>
public int instanceId;
/// <summary>
/// An internally used identifier for the sequence.
/// </summary>
public int sequenceId;
/// <summary>
/// A 64-bit unsigned integer that contains the arguments for gestures that fit into 8 bytes.
/// </summary>
public Int64 arguments;
/// <summary>
/// The size, in bytes, of extra arguments that accompany this gesture.
/// </summary>
public int extraArguments;
/// <summary>
/// Gets a value indicating whether the <see cref="GestureFlags"/> Begin is set.
/// </summary>
public bool Begin
{
get { return ((GestureFlags)flags & GestureFlags.Begin) == GestureFlags.Begin; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="GestureFlags"/> End is set.
/// </summary>
public bool End
{
get { return ((GestureFlags)flags & GestureFlags.End) == GestureFlags.End; }
}
/// <summary>
/// Gets a value indicating whether the <see cref="GestureFlags"/> Inertia is set
/// </summary>
public bool Inertia
{
get { return ((GestureFlags)flags & GestureFlags.Inertia) == GestureFlags.Inertia; }
}
}
}

View File

@@ -0,0 +1,142 @@
#region Copyright (c) Microsoft Corporation.
//
// The source code of UnmanagedLibrary.cs is quoted from Mike Stall's article:
//
// Type-safe Managed wrappers for kernel32!GetProcAddress
// http://blogs.msdn.com/jmstall/archive/2007/01/06/Typesafe-GetProcAddress.aspx
//
// This source is subject to the Microsoft Public License.
// See http://www.opensource.org/licenses/MS-PL.
// All other rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
#endregion
#region Using Directives
using System;
using System.IO;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
#endregion
namespace MaterialSkin.Gesture
{
/// <summary>
/// Utility class to wrap an unmanaged DLL and be responsible for freeing it.
/// </summary>
/// <remarks>This is a managed wrapper over the native LoadLibrary, GetProcAddress, and
/// FreeLibrary calls.
/// </remarks>
public sealed class UnmanagedLibrary : IDisposable
{
#region Safe Handles and Native imports
// See http://msdn.microsoft.com/msdnmag/issues/05/10/Reliability/ for more about safe handles.
[SecurityPermission( SecurityAction.LinkDemand, UnmanagedCode = true )]
sealed class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeLibraryHandle() : base( true ) { }
protected override bool ReleaseHandle()
{
return NativeMethods.FreeLibrary( handle );
}
}
static class NativeMethods
{
const string KERNEL32 = "kernel32";
[DllImport( KERNEL32, CharSet = CharSet.Auto, BestFitMapping = false, SetLastError = true )]
public static extern SafeLibraryHandle LoadLibrary( string fileName );
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
[DllImport( KERNEL32, SetLastError = true )]
[return: MarshalAs( UnmanagedType.Bool )]
public static extern bool FreeLibrary( IntPtr hModule );
[DllImport( KERNEL32 )]
public static extern IntPtr GetProcAddress( SafeLibraryHandle hModule, String procname );
}
#endregion // Safe Handles and Native imports
/// <summary>
/// Constructor to load a dll and be responible for freeing it.
/// </summary>
/// <param name="fileName">full path name of dll to load</param>
/// <exception cref="FileNotFoundException">if fileName can't be found</exception>
/// <remarks>Throws exceptions on failure. Most common failure would be file-not-found, or
/// that the file is not a loadable image.</remarks>
public UnmanagedLibrary( string fileName )
{
m_hLibrary = NativeMethods.LoadLibrary( fileName );
if ( m_hLibrary.IsInvalid )
{
int hr = Marshal.GetHRForLastWin32Error();
Marshal.ThrowExceptionForHR( hr );
}
}
/// <summary>
/// Dynamically lookup a function in the dll via kernel32!GetProcAddress.
/// </summary>
/// <param name="functionName">raw name of the function in the export table.</param>
/// <returns>null if function is not found. Else a delegate to the unmanaged function.
/// </returns>
/// <remarks>GetProcAddress results are valid as long as the dll is not yet unloaded. This
/// is very very dangerous to use since you need to ensure that the dll is not unloaded
/// until after you're done with any objects implemented by the dll. For example, if you
/// get a delegate that then gets an IUnknown implemented by this dll,
/// you can not dispose this library until that IUnknown is collected. Else, you may free
/// the library and then the CLR may call release on that IUnknown and it will crash.</remarks>
public TDelegate GetUnmanagedFunction<TDelegate>( string functionName ) where TDelegate : class
{
IntPtr p = NativeMethods.GetProcAddress( m_hLibrary, functionName );
// Failure is a common case, especially for adaptive code.
if ( p == IntPtr.Zero )
{
return null;
}
Delegate function = Marshal.GetDelegateForFunctionPointer( p, typeof( TDelegate ) );
// Ideally, we'd just make the constraint on TDelegate be
// System.Delegate, but compiler error CS0702 (constrained can't be System.Delegate)
// prevents that. So we make the constraint system.object and do the cast from object-->TDelegate.
object o = function;
return (TDelegate)o;
}
#region IDisposable Members
/// <summary>
/// Call FreeLibrary on the unmanaged dll. All function pointers
/// handed out from this class become invalid after this.
/// </summary>
/// <remarks>This is very dangerous because it suddenly invalidate
/// everything retrieved from this dll. This includes any functions
/// handed out via GetProcAddress, and potentially any objects returned
/// from those functions (which may have an implemention in the
/// dll).
/// </remarks>
public void Dispose()
{
if ( !m_hLibrary.IsClosed )
{
m_hLibrary.Close();
}
}
// Unmanaged resource. CLR will ensure SafeHandles get freed, without requiring a finalizer on this class.
SafeLibraryHandle m_hLibrary;
#endregion
}
}