Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / MS / Internal / Ink / GestureRecognizer / NativeRecognizer.cs / 1 / NativeRecognizer.cs
//---------------------------------------------------------------------------- // // File: NativeRecognizer.cs // // Description: // A wrapper class which interoperates with the unmanaged recognition APIS // in mshwgst.dll // // Features: // // History: // 01/14/2005 [....]: Created // // Copyright (C) 2001 by Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using Microsoft.Win32; using MS.Win32; using System; using System.Security; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Security.Permissions; using System.Text; using System.Windows.Media; using System.Windows.Ink; using System.Windows.Input; using MS.Internal.PresentationCore; using MS.Utility; using SR = MS.Internal.PresentationCore.SR; using SRID = MS.Internal.PresentationCore.SRID; #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace MS.Internal.Ink.GestureRecognition { ////// NativeRecognizer class /// internal sealed class NativeRecognizer : IDisposable { //------------------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------------------- #region Constructors ////// Static constructor /// ////// Critical: Calls a SecurityCritical methods /// LoadRecognizerDll(); /// [SecurityCritical] static NativeRecognizer() { s_isSupported = LoadRecognizerDll(); } ////// Private constructor /// ////// Critical: Calls a SecurityCritical method /// NativeRecognizer.UnsafeNativeMethods.CreateContext() /// Accesses the SecurityCritical member /// _hContext /// [SecurityCritical] private NativeRecognizer() { Debug.Assert(NativeRecognizer.RecognizerHandleSingleton != null); int hr = MS.Win32.Recognizer.UnsafeNativeMethods.CreateContext(NativeRecognizer.RecognizerHandleSingleton, out _hContext); if (HRESULT.Failed(hr)) { //don't throw a com exception here, we don't need to pass out any details throw new InvalidOperationException(SR.Get(SRID.UnspecifiedGestureConstructionException)); } // We add a reference of the recognizer to the context handle. // The context will dereference the recognizer reference when it gets disposed. // This trick will prevent the GC from disposing the recognizer before all contexts. _hContext.AddReferenceOnRecognizer(NativeRecognizer.RecognizerHandleSingleton); } #endregion Constructors //-------------------------------------------------------------------------------- // // Internal Methods // //------------------------------------------------------------------------------- #region Internal Methods ////// Create an Instance of the NativeRecognizer. /// ///null if it fails ////// Critical: Calls a SecurityCritical method /// NativeRecognizer(); /// TreatAsSafe: The method is safe because no arguments are passed. /// The NativeRecognizer return value is protected with SecurityCritical /// attributes /// [SecurityCritical, SecurityTreatAsSafe] internal static NativeRecognizer CreateInstance() { if (NativeRecognizer.RecognizerHandleSingleton != null) { return new NativeRecognizer(); } else { return null; } } ////// Set the enabled gestures /// /// ////// Critical: Handles _hContext, which is SecurityCritical /// TreatAsSafe: The method is safe because argument passed can not be /// used maliciously. And we verify the length of the passed in array. /// [SecurityCritical, SecurityTreatAsSafe] internal ApplicationGesture[] SetEnabledGestures(IEnumerableapplicationGestures) { if (_disposed) { throw new ObjectDisposedException("NativeRecognizer"); } //validate and get an array out ApplicationGesture[] enabledGestures = GetApplicationGestureArrayAndVerify(applicationGestures); // Set enabled Gestures. int hr = SetEnabledGestures(_hContext, enabledGestures); if (HRESULT.Failed(hr)) { //don't throw a com exception here, we don't need to pass out any details throw new InvalidOperationException(SR.Get(SRID.UnspecifiedSetEnabledGesturesException)); } return enabledGestures; } /// /// Recognize the strokes. /// /// ////// /// Critical: Calls a SecurityCritical method /// NativeRecognizer.UnsafeNativeMethods.ResetContext, /// AddStrokes, /// NativeRecognizer.UnsafeNativeMethods.Process /// InvokeGetAlternateList /// InvokeGetLatticePtr /// [SecurityCritical] internal GestureRecognitionResult[] Recognize(StrokeCollection strokes) { if (_disposed) { throw new ObjectDisposedException("NativeRecognizer"); } // // note that we validate this argument from GestureRecognizer // but since this is marked TAS, we want to do it here as well // if (strokes == null) { throw new ArgumentNullException("strokes"); // Null is not allowed as the argument value } if (strokes.Count > 2) { throw new ArgumentException(SR.Get(SRID.StrokeCollectionCountTooBig), "strokes"); } // Create an empty result. GestureRecognitionResult[] recResults = new GestureRecognitionResult[]{}; if ( strokes.Count == 0 ) { return recResults; } int hr = 0; try { // Reset the context hr = MS.Win32.Recognizer.UnsafeNativeMethods.ResetContext(_hContext); if (HRESULT.Failed(hr)) { //finally block will clean up and throw return recResults; } // Add strokes hr = AddStrokes(_hContext, strokes); if (HRESULT.Failed(hr)) { //AddStrokes's finally block will clean up this finally block will throw return recResults; } // recognize the ink bool bIncremental; hr = MS.Win32.Recognizer.UnsafeNativeMethods.Process(_hContext, out bIncremental); if (HRESULT.Succeeded(hr)) { if ( s_GetAlternateListExists ) { recResults = InvokeGetAlternateList(); } else { recResults = InvokeGetLatticePtr(); } } } finally { // Check if we should report any error. if ( HRESULT.Failed(hr) ) { //don't throw a com exception here, we don't need to pass out any details throw new InvalidOperationException(SR.Get(SRID.UnspecifiedGestureException)); } } return recResults; } internal static ApplicationGesture[] GetApplicationGestureArrayAndVerify(IEnumerableapplicationGestures) { if (applicationGestures == null) { // Null is not allowed as the argument value throw new ArgumentNullException("applicationGestures"); } uint count = 0; //we need to make a disconnected copy ICollection collection = applicationGestures as ICollection ; if (collection != null) { count = (uint)collection.Count; } else { foreach (ApplicationGesture gesture in applicationGestures) { count++; } } // Cannot be empty if (count == 0) { // An empty array is not allowed. throw new ArgumentException(SR.Get(SRID.ApplicationGestureArrayLengthIsZero), "applicationGestures"); } bool foundAllGestures = false; List gestures = new List (); foreach (ApplicationGesture gesture in applicationGestures) { if (!ApplicationGestureHelper.IsDefined(gesture)) { throw new ArgumentException(SR.Get(SRID.ApplicationGestureIsInvalid), "applicationGestures"); } //check for allgestures if (gesture == ApplicationGesture.AllGestures) { foundAllGestures = true; } //check for dupes if (gestures.Contains(gesture)) { throw new ArgumentException(SR.Get(SRID.DuplicateApplicationGestureFound), "applicationGestures"); } gestures.Add(gesture); } // AllGesture cannot be specified with other gestures if (foundAllGestures && gestures.Count != 1) { // no dupes allowed throw new ArgumentException(SR.Get(SRID.AllGesturesMustExistAlone), "applicationGestures"); } return gestures.ToArray(); } #endregion Internal Methods //-------------------------------------------------------------------------------- // // IDisposable // //-------------------------------------------------------------------------------- #region IDisposable /// /// A simple pattern of the dispose implementation. /// There is no finalizer since the SafeHandle will take care of releasing the context. /// ////// Critical: Calls a SecurityCritical method and the SecurityCritical handle /// _hContext.Dispose() /// TreatAsSafe: The method is safe because no arguments are passed. We guard /// against dispose being called twice. /// [SecurityCritical, SecurityTreatAsSafe] public void Dispose() { if (_disposed) { return; } _hContext.Dispose(); _disposed = true; } #endregion IDisposable //------------------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------------------- #region Private Methods ////// Load the mshwgst.dll from the path in the registry. Make sure this loading action prior to invoking /// any native functions marked with DllImport in mshwgst.dll /// This method is called from the NativeRecognizer's static construtor. /// ////// Critical: Requires read registry and unmanaged code access /// [SecurityCritical] private static bool LoadRecognizerDll() { // String path = null; System.Security.PermissionSet permissionSet = new PermissionSet(null); permissionSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, System.Security.AccessControl.AccessControlActions.View, GestureRecognizerFullPath)); permissionSet.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted)); permissionSet.Assert(); // BlessedAssert: try { RegistryKey regkey = Registry.LocalMachine; RegistryKey recognizerKey = regkey.OpenSubKey(GestureRecognizerPath); if (recognizerKey != null) { try { // Try to read the recognizer path subkey path = recognizerKey.GetValue(GestureRecognizerValueName) as string; if (path == null) { return false; } } finally { recognizerKey.Close(); } } else { // we couldn't find the path in the registry // no key to close return false; } } finally { CodeAccessPermission.RevertAssert(); } if (path != null) { IntPtr hModule = MS.Win32.UnsafeNativeMethods.LoadLibrary(path); // Check whether GetAlternateList exists in the loaded Dll. s_GetAlternateListExists = false; if ( hModule != IntPtr.Zero ) { s_GetAlternateListExists = MS.Win32.UnsafeNativeMethods.GetProcAddressNoThrow( new HandleRef(null, hModule), "GetAlternateList") != IntPtr.Zero ? true : false; } return hModule != IntPtr.Zero ? true : false; } return false; //path was null } ////// Set the enabled gestures. /// This method is called from the internal SetEnabledGestures method. /// ////// Critical: Calls a critical pinvoke /// NativeRecognizer.UnsafeNativeMethods.SetEnabledUnicodeRanges /// [SecurityCritical] private int SetEnabledGestures(MS.Win32.Recognizer.ContextSafeHandle recContext, ApplicationGesture[] enabledGestures) { Debug.Assert(recContext != null && !recContext.IsInvalid); // NOTICE-2005/01/11-[....], // The following usage was copied from drivers\tablet\recognition\ink\core\twister\src\wispapis.c // SetEnabledUnicodeRanges // Set ranges of gestures enabled in this recognition context // The behavior of this function is the following: // (a) (A part of) One of the requested ranges lies outside // gesture interval---currently [GESTURE_NULL, GESTURE_NULL + 255) // return E_UNEXPECTED and keep the previously set ranges // (b) All requested ranges are within the gesture interval but // some of them are not supported: // return S_TRUNCATED and set those requested gestures that are // supported (possibly an empty set) // (c) All requested gestures are supported // return S_OK and set all requested gestures. // Note: An easy way to set all supported gestures as enabled is to use // SetEnabledUnicodeRanges() with one range=(GESTURE_NULL,255). // Enabel gestures uint cRanges = (uint)( enabledGestures.Length ); MS.Win32.Recognizer.CHARACTER_RANGE[] charRanges = new MS.Win32.Recognizer.CHARACTER_RANGE[cRanges]; if ( cRanges == 1 && enabledGestures[0] == ApplicationGesture.AllGestures ) { charRanges[0].cChars = MAX_GESTURE_COUNT; charRanges[0].wcLow = GESTURE_NULL; } else { for ( int i = 0; i < cRanges; i++ ) { charRanges[i].cChars = 1; charRanges[i].wcLow = (ushort)( enabledGestures[i] ); } } int hr = MS.Win32.Recognizer.UnsafeNativeMethods.SetEnabledUnicodeRanges(recContext, cRanges, charRanges); return hr; } ////// Add the strokes to the recoContext. /// The method is called from the internal Recognize method. /// ////// Critical: Calls a critical PInvoke /// GetPacketData, /// NativeRecognizer.UnsafeNativeMethods.AddStroke, /// ReleaseResourcesinPacketDescription /// [SecurityCritical] private int AddStrokes(MS.Win32.Recognizer.ContextSafeHandle recContext, StrokeCollection strokes) { Debug.Assert(recContext != null && !recContext.IsInvalid); int hr; foreach ( Stroke stroke in strokes ) { MS.Win32.Recognizer.PACKET_DESCRIPTION packetDescription = new MS.Win32.Recognizer.PACKET_DESCRIPTION(); IntPtr packets = IntPtr.Zero; try { int countOfBytes; NativeMethods.XFORM xForm; GetPacketData(stroke, out packetDescription, out countOfBytes, out packets, out xForm); if (packets == IntPtr.Zero) { return -2147483640; //E_FAIL - 0x80000008. We never raise this in an exception } hr = MS.Win32.Recognizer.UnsafeNativeMethods.AddStroke(recContext, ref packetDescription, (uint)countOfBytes, packets, xForm); if ( HRESULT.Failed(hr) ) { // Return from here. The finally block will free the memory and report the error properly. return hr; } } finally { // Release the resources in the finally block ReleaseResourcesinPacketDescription(packetDescription, packets); } } return MS.Win32.Recognizer.UnsafeNativeMethods.EndInkInput(recContext); } ////// Retrieve the packet description, packets data and XFORM which is the information the native recognizer needs. /// The method is called from AddStrokes. /// ////// Critical: Contains unsafe code /// [SecurityCritical] private void GetPacketData ( Stroke stroke, out MS.Win32.Recognizer.PACKET_DESCRIPTION packetDescription, out int countOfBytes, out IntPtr packets, out NativeMethods.XFORM xForm ) { int i; countOfBytes = 0; packets = IntPtr.Zero; packetDescription = new MS.Win32.Recognizer.PACKET_DESCRIPTION(); Matrix matrix = Matrix.Identity; xForm = new NativeMethods.XFORM((float)(matrix.M11), (float)(matrix.M12), (float)(matrix.M21), (float)(matrix.M22), (float)(matrix.OffsetX), (float)(matrix.OffsetY)); StylusPointCollection stylusPoints = stroke.StylusPoints; if (stylusPoints.Count == 0) { return; //we'll fail when the calling routine sees that packets is IntPtr.Zer } if (stylusPoints.Description.PropertyCount > StylusPointDescription.RequiredCountOfProperties) { // // reformat to X, Y, P // StylusPointDescription reformatDescription = new StylusPointDescription( new StylusPointPropertyInfo[]{ new StylusPointPropertyInfo(StylusPointProperties.X), new StylusPointPropertyInfo(StylusPointProperties.Y), stylusPoints.Description.GetPropertyInfo(StylusPointProperties.NormalPressure)}); stylusPoints = stylusPoints.Reformat(reformatDescription); } // // now make sure we only take a finite amount of data for the stroke // if (stylusPoints.Count > MaxStylusPoints) { stylusPoints = stylusPoints.Clone(MaxStylusPoints); } Guid[] propertyGuids = new Guid[]{ StylusPointPropertyIds.X, //required index for SPD StylusPointPropertyIds.Y, //required index for SPD StylusPointPropertyIds.NormalPressure}; //required index for SPD Debug.Assert(stylusPoints != null); Debug.Assert(propertyGuids.Length == StylusPointDescription.RequiredCountOfProperties); // Get the packet description packetDescription.cbPacketSize = (uint)(propertyGuids.Length * Marshal.SizeOf(typeof(Int32))); packetDescription.cPacketProperties = (uint)propertyGuids.Length; // // use X, Y defaults for metrics, sometimes mouse metrics can be bogus // always use NormalPressure metrics, though. // StylusPointPropertyInfo[] infosToUse = new StylusPointPropertyInfo[StylusPointDescription.RequiredCountOfProperties]; infosToUse[StylusPointDescription.RequiredXIndex] = StylusPointPropertyInfoDefaults.X; infosToUse[StylusPointDescription.RequiredYIndex] = StylusPointPropertyInfoDefaults.Y; infosToUse[StylusPointDescription.RequiredPressureIndex] = stylusPoints.Description.GetPropertyInfo(StylusPointProperties.NormalPressure); MS.Win32.Recognizer.PACKET_PROPERTY[] packetProperties = new MS.Win32.Recognizer.PACKET_PROPERTY[packetDescription.cPacketProperties]; StylusPointPropertyInfo propertyInfo; for ( i = 0; i < packetDescription.cPacketProperties; i++ ) { packetProperties[i].guid = propertyGuids[i]; propertyInfo = infosToUse[i]; MS.Win32.Recognizer.PROPERTY_METRICS propertyMetrics = new MS.Win32.Recognizer.PROPERTY_METRICS( ); propertyMetrics.nLogicalMin = propertyInfo.Minimum; propertyMetrics.nLogicalMax = propertyInfo.Maximum; propertyMetrics.Units = (int)(propertyInfo.Unit); propertyMetrics.fResolution = propertyInfo.Resolution; packetProperties[i].PropertyMetrics = propertyMetrics; } unsafe { int allocationSize = (int)(Marshal.SizeOf(typeof(MS.Win32.Recognizer.PACKET_PROPERTY)) * packetDescription.cPacketProperties); packetDescription.pPacketProperties = Marshal.AllocCoTaskMem(allocationSize); MS.Win32.Recognizer.PACKET_PROPERTY* pPacketProperty = (MS.Win32.Recognizer.PACKET_PROPERTY*)(packetDescription.pPacketProperties.ToPointer()); MS.Win32.Recognizer.PACKET_PROPERTY* pElement = pPacketProperty; for ( i = 0 ; i < packetDescription.cPacketProperties ; i ++ ) { Marshal.StructureToPtr(packetProperties[i], new IntPtr(pElement), false); pElement++; } } // Get packet data int[] rawPackets = stylusPoints.ToHiMetricArray(); int packetCount = rawPackets.Length; if (packetCount != 0) { countOfBytes = packetCount * Marshal.SizeOf(typeof(Int32)); packets = Marshal.AllocCoTaskMem(countOfBytes); Marshal.Copy(rawPackets, 0, packets, packetCount); } } ////// Release the memory blocks which has been created for mashalling purpose. /// The method is called from AddStrokes. /// ////// Critical: Calls unsafe code, requires UnmanageCode permission /// [SecurityCritical] private void ReleaseResourcesinPacketDescription(MS.Win32.Recognizer.PACKET_DESCRIPTION pd, IntPtr packets) { if ( pd.pPacketProperties != IntPtr.Zero ) { unsafe { MS.Win32.Recognizer.PACKET_PROPERTY* pPacketProperty = (MS.Win32.Recognizer.PACKET_PROPERTY*)( pd.pPacketProperties.ToPointer( ) ); MS.Win32.Recognizer.PACKET_PROPERTY* pElement = pPacketProperty; for ( int i = 0; i < pd.cPacketProperties; i++ ) { Marshal.DestroyStructure(new IntPtr(pElement), typeof(MS.Win32.Recognizer.PACKET_PROPERTY)); pElement++; } } Marshal.FreeCoTaskMem(pd.pPacketProperties); pd.pPacketProperties = IntPtr.Zero; } if ( pd.pguidButtons != IntPtr.Zero ) { Marshal.FreeCoTaskMem(pd.pguidButtons); pd.pguidButtons = IntPtr.Zero; } if ( packets != IntPtr.Zero ) { Marshal.FreeCoTaskMem(packets); packets = IntPtr.Zero; } } ////// Invokes GetAlternateList in the native dll /// ////// /// Critical: Calls the native methods /// NativeRecognizer.UnsafeNativeMethods.GetAlternateList /// NativeRecognizer.UnsafeNativeMethods.GetString /// NativeRecognizer.UnsafeNativeMethods.GetConfidenceLevel /// NativeRecognizer.UnsafeNativeMethods.DestroyAlternate /// [SecurityCritical] private GestureRecognitionResult[] InvokeGetAlternateList() { GestureRecognitionResult[] recResults = new GestureRecognitionResult[] { }; int hr = 0; MS.Win32.Recognizer.RECO_RANGE recoRange; recoRange.iwcBegin = 0; recoRange.cCount = 1; uint countOfAlternates = IRAS_DefaultCount; IntPtr[] pRecoAlternates = new IntPtr[IRAS_DefaultCount]; try { hr = MS.Win32.Recognizer.UnsafeNativeMethods.GetAlternateList(_hContext, ref recoRange, ref countOfAlternates, pRecoAlternates, MS.Win32.Recognizer.ALT_BREAKS.ALT_BREAKS_SAME); if ( HRESULT.Succeeded(hr) && countOfAlternates != 0 ) { ListresultList = new List (); for ( int i = 0; i < countOfAlternates; i++ ) { uint size = 1; // length of string == 1 since gesture id is a single WCHAR StringBuilder recoString = new StringBuilder(1); RecognitionConfidence confidenceLevel; if ( HRESULT.Failed(MS.Win32.Recognizer.UnsafeNativeMethods.GetString(pRecoAlternates[i], out recoRange, ref size, recoString)) || HRESULT.Failed(MS.Win32.Recognizer.UnsafeNativeMethods.GetConfidenceLevel(pRecoAlternates[i], out recoRange, out confidenceLevel)) ) { // Fail to retrieve the reco result, skip this one continue; } ApplicationGesture gesture = (ApplicationGesture)recoString[0]; Debug.Assert(ApplicationGestureHelper.IsDefined(gesture)); if (ApplicationGestureHelper.IsDefined(gesture)) { resultList.Add(new GestureRecognitionResult(confidenceLevel, gesture)); } } recResults = resultList.ToArray(); } } finally { // Destroy the alternates for ( int i = 0; i < countOfAlternates; i++ ) { if (pRecoAlternates[i] != IntPtr.Zero) { #pragma warning suppress 6031, 56031 // Return value ignored on purpose. MS.Win32.Recognizer.UnsafeNativeMethods.DestroyAlternate(pRecoAlternates[i]); pRecoAlternates[i] = IntPtr.Zero; } } } return recResults; } /// /// Invokes GetLatticePtr in the native dll /// ////// /// Critical: Calls the native methods /// NativeRecognizer.UnsafeNativeMethods.GetLatticePtr /// And uses unsafe code /// [SecurityCritical] private GestureRecognitionResult[] InvokeGetLatticePtr() { GestureRecognitionResult[] recResults = new GestureRecognitionResult[] { }; // int hr = 0; IntPtr ptr = IntPtr.Zero; // NOTICE-2005/07/11-[....], // There is no need to free the returned the structure. // The memory will be released when ResetContext, which is invoked in the callee - Recognize, is called. if ( HRESULT.Succeeded( MS.Win32.Recognizer.UnsafeNativeMethods.GetLatticePtr( _hContext, ref ptr)) ) { unsafe { MS.Win32.Recognizer.RECO_LATTICE* pRecoLattice = (MS.Win32.Recognizer.RECO_LATTICE*)ptr; uint bestResultColumnCount = pRecoLattice->ulBestResultColumnCount; Debug.Assert(!(bestResultColumnCount != 0 && pRecoLattice->pLatticeColumns == IntPtr.Zero), "Invalid results!"); if ( bestResultColumnCount > 0 && pRecoLattice->pLatticeColumns != IntPtr.Zero ) { ListresultList = new List (); MS.Win32.Recognizer.RECO_LATTICE_COLUMN* pLatticeColumns = (MS.Win32.Recognizer.RECO_LATTICE_COLUMN*)(pRecoLattice->pLatticeColumns); ulong* pulBestResultColumns = (ulong*)(pRecoLattice->pulBestResultColumns); for ( uint i = 0; i < bestResultColumnCount; i++ ) { ulong column = pulBestResultColumns[i]; MS.Win32.Recognizer.RECO_LATTICE_COLUMN recoColumn = pLatticeColumns[column]; Debug.Assert(0 < recoColumn.cLatticeElements, "Invalid results!"); for ( int j = 0; j < recoColumn.cLatticeElements; j++ ) { MS.Win32.Recognizer.RECO_LATTICE_ELEMENT recoElement = ((MS.Win32.Recognizer.RECO_LATTICE_ELEMENT*)(recoColumn.pLatticeElements))[j]; Debug.Assert((RECO_TYPE)(recoElement.type) == RECO_TYPE.RECO_TYPE_WCHAR, "The Application gesture has to be WCHAR type" ); if ( (RECO_TYPE)(recoElement.type) == RECO_TYPE.RECO_TYPE_WCHAR ) { // Retrieve the confidence lever RecognitionConfidence confidenceLevel = RecognitionConfidence.Poor; MS.Win32.Recognizer.RECO_LATTICE_PROPERTIES recoProperties = recoElement.epProp; uint propertyCount = recoProperties.cProperties; MS.Win32.Recognizer.RECO_LATTICE_PROPERTY** apProps = (MS.Win32.Recognizer.RECO_LATTICE_PROPERTY**)recoProperties.apProps; for ( int k = 0; k < propertyCount; k++ ) { MS.Win32.Recognizer.RECO_LATTICE_PROPERTY* pProps = apProps[k]; if ( pProps->guidProperty == GUID_CONFIDENCELEVEL ) { Debug.Assert(pProps->cbPropertyValue == sizeof(uint) / sizeof(byte)); RecognitionConfidence level = (RecognitionConfidence)(((uint*)pProps->pPropertyValue))[0]; if ( level >= RecognitionConfidence.Strong && level <= RecognitionConfidence.Poor ) { confidenceLevel = level; } break; } } ApplicationGesture gesture = (ApplicationGesture)((char)(recoElement.pData)); Debug.Assert(ApplicationGestureHelper.IsDefined(gesture)); if (ApplicationGestureHelper.IsDefined(gesture)) { // Get the gesture result resultList.Add(new GestureRecognitionResult(confidenceLevel,gesture)); } } } } recResults = (GestureRecognitionResult[])(resultList.ToArray()); } } } return recResults; } #endregion Private Methods /// /// RecognizerHandle is a static property. But it's a SafeHandle. /// So, we don't have to worry about releasing the handle since RecognizerSafeHandle when there is no reference on it. /// ////// Critical: Calls a SecurityCritical pinvoke and accesses SecurityCritical fields /// private static MS.Win32.Recognizer.RecognizerSafeHandle RecognizerHandleSingleton { [SecurityCritical] get { if (s_isSupported && s_hRec == null) { lock (_syncRoot) { if (s_isSupported && s_hRec == null) { if (HRESULT.Failed(MS.Win32.Recognizer.UnsafeNativeMethods.CreateRecognizer(ref s_Gesture, out s_hRec))) { s_hRec = null; } } } } return s_hRec; } } enum RECO_TYPE : ushort { RECO_TYPE_WSTRING = 0, RECO_TYPE_WCHAR = 1 } private const string GestureRecognizerPath = @"SOFTWARE\MICROSOFT\TPG\SYSTEM RECOGNIZERS\{BED9A940-7D48-48E3-9A68-F4887A5A1B2E}"; private const string GestureRecognizerFullPath = "HKEY_LOCAL_MACHINE" + @"\" + GestureRecognizerPath; private const string GestureRecognizerValueName = "RECOGNIZER DLL"; private const string GestureRecognizerGuid = "{BED9A940-7D48-48E3-9A68-F4887A5A1B2E}"; // This constant is an identical value as the one in drivers\tablet\recognition\ink\core\common\inc\gesture\gesturedefs.h private const ushort MAX_GESTURE_COUNT = 256; // This constant is an identical value as the one in drivers\tablet\include\sdk\recdefs.h private const ushort GESTURE_NULL = 0xf000; // This constant is an identical value as the one in public\internal\drivers\inc\msinkaut.h private const ushort IRAS_DefaultCount = 10; private const ushort MaxStylusPoints = 10000; // The GUID has been copied from public\internal\drivers\inc\tpcguid.h //// {7DFE11A7-FB5D-4958-8765-154ADF0D833F} //DEFINE_GUID(GUID_CONFIDENCELEVEL, 0x7dfe11a7, 0xfb5d, 0x4958, 0x87, 0x65, 0x15, 0x4a, 0xdf, 0xd, 0x83, 0x3f); private static readonly Guid GUID_CONFIDENCELEVEL = new Guid("{7DFE11A7-FB5D-4958-8765-154ADF0D833F}"); ////// IDisposable support /// private bool _disposed = false; ////// Each NativeRecognizer instance has it's own recognizer context /// ////// Critical: The SecurityCritical handle /// [SecurityCritical] private MS.Win32.Recognizer.ContextSafeHandle _hContext; ////// Used to lock for instancing the native recognizer handle /// private static object _syncRoot = new object(); ////// All NativeRecognizer share a single handle to the recognizer /// ////// Critical: The SecurityCritical handle /// [SecurityCritical] private static MS.Win32.Recognizer.RecognizerSafeHandle s_hRec; ////// The Guid of the GestureRecognizer used for registry lookup /// private static Guid s_Gesture = new Guid(GestureRecognizerGuid); ////// can we load the recognizer? /// private static readonly bool s_isSupported; ////// A flag indicates whether we can find the entry point of /// GetAlternateList function in mshwgst.dll /// private static bool s_GetAlternateListExists; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- LogWriteRestartAreaAsyncResult.cs
- XmlIncludeAttribute.cs
- filewebresponse.cs
- ServiceDebugElement.cs
- TypeLoadException.cs
- Faults.cs
- Parser.cs
- InstallerTypeAttribute.cs
- JsonDeserializer.cs
- DataGridItemCollection.cs
- AssemblyHelper.cs
- WindowsFormsLinkLabel.cs
- DecoderBestFitFallback.cs
- CodePrimitiveExpression.cs
- ThicknessAnimationBase.cs
- HtmlAnchor.cs
- EdmRelationshipRoleAttribute.cs
- DataGridViewCellValueEventArgs.cs
- WsatTransactionInfo.cs
- UniqueConstraint.cs
- mediaeventargs.cs
- Evidence.cs
- DaylightTime.cs
- GradientSpreadMethodValidation.cs
- XmlSchemaAnyAttribute.cs
- DownloadProgressEventArgs.cs
- SuppressMergeCheckAttribute.cs
- ColorInterpolationModeValidation.cs
- CalculatedColumn.cs
- AdapterDictionary.cs
- StructuredProperty.cs
- InputProcessorProfilesLoader.cs
- Event.cs
- ConfigurationProviderException.cs
- Processor.cs
- PathFigureCollectionConverter.cs
- WindowsGraphics2.cs
- InheritanceAttribute.cs
- PackUriHelper.cs
- PropertyValueChangedEvent.cs
- DecoratedNameAttribute.cs
- MgmtConfigurationRecord.cs
- Preprocessor.cs
- XmlObjectSerializerReadContext.cs
- StructuralType.cs
- JournalNavigationScope.cs
- GroupItemAutomationPeer.cs
- _SSPIWrapper.cs
- Button.cs
- StringWriter.cs
- CaseStatementProjectedSlot.cs
- ThemeDirectoryCompiler.cs
- clipboard.cs
- SoapReflector.cs
- ManagementQuery.cs
- SafeCoTaskMem.cs
- AttachedPropertyInfo.cs
- Console.cs
- XmlByteStreamReader.cs
- ColorTranslator.cs
- StatusStrip.cs
- NotFiniteNumberException.cs
- IUnknownConstantAttribute.cs
- ISAPIRuntime.cs
- VariantWrapper.cs
- HtmlControl.cs
- SystemDiagnosticsSection.cs
- ApplicationProxyInternal.cs
- Enlistment.cs
- SafeArrayTypeMismatchException.cs
- PocoPropertyAccessorStrategy.cs
- SchemaNames.cs
- DataBinder.cs
- DataGridViewCellParsingEventArgs.cs
- ControlIdConverter.cs
- Int16AnimationBase.cs
- oledbconnectionstring.cs
- KeyConverter.cs
- Rule.cs
- EventMappingSettings.cs
- HttpWebRequestElement.cs
- StorageMappingItemLoader.cs
- ContainerAction.cs
- PageOrientation.cs
- LinqDataSourceContextEventArgs.cs
- EnvironmentPermission.cs
- ListDictionary.cs
- ListItemCollection.cs
- ParallelTimeline.cs
- MetadataArtifactLoader.cs
- QilDataSource.cs
- Win32MouseDevice.cs
- NamedElement.cs
- LicenseProviderAttribute.cs
- WindowsStatusBar.cs
- GeneralTransform3DGroup.cs
- XmlSchemaParticle.cs
- DrawingGroup.cs
- StateMachine.cs
- ChangeDirector.cs