Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Input / Stylus / StylusPlugInCollection.cs / 2 / StylusPlugInCollection.cs
//------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------- using System; using System.Windows; using System.Collections; using System.Collections.ObjectModel; using System.Windows.Media; using System.Windows.Threading; using System.Windows.Interop; using System.Security; using System.Security.Permissions; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Input.StylusPlugIns { ////// Collection of StylusPlugIn objects /// ////// The collection order is based on the order that StylusPlugIn objects are /// added to the collection via the IList interfaces. The order of the StylusPlugIn /// objects in the collection is modifiable. /// Some of the methods are designed to be called from both the App thread and the Pen thread, /// but some of them are supposed to be called from one thread only. Please look at the /// comments of each method for such an information. /// public sealed class StylusPlugInCollection : Collection{ #region Protected APIs /// /// Insert a StylusPlugIn in the collection at a specific index. /// This method should be called from the application context only /// /// index at which to insert the StylusPlugIn object /// StylusPlugIn object to insert, downcast to an object protected override void InsertItem(int index, StylusPlugIn plugIn) { // Verify it's called from the app dispatcher _element.VerifyAccess(); // Validate the input parameter if (null == plugIn) { throw new ArgumentNullException("plugIn", SR.Get(SRID.Stylus_PlugInIsNull)); } if (IndexOf(plugIn) != -1) { throw new ArgumentException(SR.Get(SRID.Stylus_PlugInIsDuplicated), "plugIn"); } // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { if (IsActiveForInput) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { System.Diagnostics.Debug.Assert(this.Count > 0); // If active must have more than one plugin already base.InsertItem(index, plugIn); plugIn.Added(this); } } else { EnsureEventsHooked(); // Hook up events to track changes to the plugin's element base.InsertItem(index, plugIn); try { plugIn.Added(this); // Notify plugin that it has been added to collection } finally { UpdatePenContextsState(); // Add to PenContexts if element is in proper state (can fire isactiveforinput). } } } } ////// Remove all the StylusPlugIn objects from the collection. /// This method should be called from the application context only. /// protected override void ClearItems() { // Verify it's called from the app dispatcher _element.VerifyAccess(); if (this.Count != 0) { // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { if (IsActiveForInput) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { while (this.Count > 0) { RemoveItem(0); // Does work to fire event and remove from collection and pencontexts } } } else { while (this.Count > 0) { RemoveItem(0); // Does work to fire event and remove from collection. } } } } } ////// Remove the StylusPlugIn in the collection at the specified index. /// This method should be called from the application context only. /// /// protected override void RemoveItem(int index) { // Verify it's called from the app dispatcher _element.VerifyAccess(); // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { if (IsActiveForInput) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { StylusPlugIn removedItem = base[index]; base.RemoveItem(index); try { EnsureEventsAndPenContextsUnhooked(); // Clean up events and remove from pencontexts } finally { removedItem.Removed(); // Notify plugin it has been removed } } } else { StylusPlugIn removedItem = base[index]; base.RemoveItem(index); try { EnsureEventsAndPenContextsUnhooked(); // Clean up events and remove from pencontexts } finally { removedItem.Removed(); // Notify plugin it has been removed } } } } ////// Indexer to retrieve/set a StylusPlugIn at a given index in the collection /// Accessible from both the real time context and application context. /// protected override void SetItem(int index, StylusPlugIn plugIn) { // Verify it's called from the app dispatcher _element.VerifyAccess(); if (null == plugIn) { throw new ArgumentNullException("plugIn", SR.Get(SRID.Stylus_PlugInIsNull)); } if (IndexOf(plugIn) != -1) { throw new ArgumentException(SR.Get(SRID.Stylus_PlugInIsDuplicated), "plugIn"); } // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { if (IsActiveForInput) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { StylusPlugIn originalPlugIn = base[index]; base.SetItem(index, plugIn); try { originalPlugIn.Removed(); } finally { plugIn.Added(this); } } } else { StylusPlugIn originalPlugIn = base[index]; base.SetItem(index, plugIn); try { originalPlugIn.Removed(); } finally { plugIn.Added(this); } } } } #endregion #region Internal APIs ////// Constructor /// /// internal StylusPlugInCollection(UIElement element) { _element = element; _isEnabledChangedEventHandler = new DependencyPropertyChangedEventHandler(OnIsEnabledChanged); _isVisibleChangedEventHandler = new DependencyPropertyChangedEventHandler(OnIsVisibleChanged); _isHitTestVisibleChangedEventHandler = new DependencyPropertyChangedEventHandler(OnIsHitTestVisibleChanged); _sourceChangedEventHandler = new SourceChangedEventHandler(OnSourceChanged); _layoutChangedEventHandler = new EventHandler(OnLayoutUpdated); } ////// Get the UIElement /// This method is called from the real-time context. /// internal UIElement Element { get { return _element; } } ////// Update the rectangular bound of the element /// This method is called from the application context. /// internal void UpdateRect() { // The RenderSize is only valid if IsArrangeValid is true. if (_element.IsArrangeValid && _element.IsEnabled && _element.IsVisible && _element.IsHitTestVisible) { _rc = new Rect(new Point(), _element.RenderSize);// _element.GetContentBoundingBox(); Visual root = VisualTreeHelper.GetContainingVisual2D(InputElement.GetRootVisual(_element)); try { _viewToElement = root.TransformToDescendant(_element); } catch(System.InvalidOperationException) { // This gets hit if the transform is not invertable. In that case // we will just not allow this plugin to be hit. _rc = new Rect(); // empty rect so we don't hittest it. _viewToElement = Transform.Identity; } } else { _rc = new Rect(); // empty rect so we don't hittest it. } if (_viewToElement == null) { _viewToElement = Transform.Identity; } } ////// Check whether a point hits the element /// This method is called from the real-time context. /// /// a point to check ///true if the point is within the bound of the element; false otherwise internal bool IsHit(Point pt) { Point ptElement = pt; _viewToElement.TryTransform(ptElement, out ptElement); return _rc.Contains(ptElement); } ////// Get the transform matrix from the root visual to the current UIElement /// This method is called from the real-time context. /// internal GeneralTransform ViewToElement { get { return _viewToElement; } } ////// Get the current rect for the Element that the StylusPlugInCollection is attached to. /// May be empty rect if plug in is not in tree. /// internal Rect Rect { get { return _rc; } } ////// Get the current rect for the Element that the StylusPlugInCollection is attached to. /// May be empty rect if plug in is not in tree. /// ////// Critical - Accesses SecurityCritical data _penContexts. /// TreatAsSafe - Just returns if _pencontexts is null. No data goes in or out. Knowing /// the fact that you can recieve real time input is something that is safe /// to know and we want to expose. /// internal bool IsActiveForInput { [SecurityCritical, SecurityTreatAsSafe] get { return _penContexts != null; } } ////// Critical - Accesses SecurityCritical data _penContexts. /// TreatAsSafe - The Sync object on the _penContexts object is not considered security /// critical data. It is already internally exposed directly on the /// PenContexts object. /// internal object PenContextsSyncRoot { [SecurityCritical, SecurityTreatAsSafe] get { return _penContexts != null ? _penContexts.SyncRoot : null; } } ////// Fire the Enter notification. /// This method is called from pen threads and app thread. /// internal void FireEnterLeave(bool isEnter, RawStylusInput rawStylusInput, bool confirmed) { if (IsActiveForInput) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { for (int i = 0; i < this.Count; i++) { base[i].StylusEnterLeave(isEnter, rawStylusInput, confirmed); } } } else { for (int i = 0; i < this.Count; i++) { base[i].StylusEnterLeave(isEnter, rawStylusInput, confirmed); } } } ////// Fire RawStylusInputEvent for all the StylusPlugIns /// This method is called from the real-time context (pen thread) only /// /// internal void FireRawStylusInput(RawStylusInput args) { try { if (IsActiveForInput) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { for (int i = 0; i < this.Count; i++) { StylusPlugIn plugIn = base[i]; // set current plugin so any callback data gets an owner. args.CurrentNotifyPlugIn = plugIn; plugIn.RawStylusInput(args); } } } else { for (int i = 0; i < this.Count; i++) { StylusPlugIn plugIn = base[i]; // set current plugin so any callback data gets an owner. args.CurrentNotifyPlugIn = plugIn; plugIn.RawStylusInput(args); } } } finally { args.CurrentNotifyPlugIn = null; } } ////// Critical: Accesses critical member _penContexts. /// internal PenContexts PenContexts { [SecurityCritical] get { return _penContexts; } } #endregion #region Private APIs ////// Add this StylusPlugInCollection to the StylusPlugInCollectionList when it the first /// element is added. /// ////// Critical - Presentation source access /// TreatAsSafe: - PresentationSource makes a SecurityDemand /// - no data handed out or accepted /// - called by Add and Insert /// [SecurityCritical,SecurityTreatAsSafe] private void EnsureEventsHooked() { if (this.Count == 0) { // Grab current element info UpdateRect(); // Now hook up events to track on this element. _element.IsEnabledChanged += _isEnabledChangedEventHandler; _element.IsVisibleChanged += _isVisibleChangedEventHandler; _element.IsHitTestVisibleChanged += _isHitTestVisibleChangedEventHandler; PresentationSource.AddSourceChangedHandler(_element, _sourceChangedEventHandler); // has a security linkdemand _element.LayoutUpdated += _layoutChangedEventHandler; if (_element.RenderTransform != null && !_element.RenderTransform.IsFrozen) { if (_renderTransformChangedEventHandler == null) { _renderTransformChangedEventHandler = new EventHandler(OnRenderTransformChanged); _element.RenderTransform.Changed += _renderTransformChangedEventHandler; } } } } ////// Remove this StylusPlugInCollection from the StylusPlugInCollectionList when it the last /// element is removed for this collection. /// private void EnsureEventsAndPenContextsUnhooked() { if (this.Count == 0) { // Unhook events. _element.IsEnabledChanged -= _isEnabledChangedEventHandler; _element.IsVisibleChanged -= _isVisibleChangedEventHandler; _element.IsHitTestVisibleChanged -= _isHitTestVisibleChangedEventHandler; if (_renderTransformChangedEventHandler != null) { _element.RenderTransform.Changed -= _renderTransformChangedEventHandler; } PresentationSource.RemoveSourceChangedHandler(_element, _sourceChangedEventHandler); _element.LayoutUpdated -= _layoutChangedEventHandler; // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { // Make sure we are unhooked from PenContexts if we don't have any plugins. UnhookPenContexts(); } } } private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) { System.Diagnostics.Debug.Assert(_element.IsEnabled == (bool)e.NewValue); UpdatePenContextsState(); } private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { System.Diagnostics.Debug.Assert(_element.IsVisible == (bool)e.NewValue); UpdatePenContextsState(); } private void OnIsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { System.Diagnostics.Debug.Assert(_element.IsHitTestVisible == (bool)e.NewValue); UpdatePenContextsState(); } private void OnRenderTransformChanged(object sender, EventArgs e) { OnLayoutUpdated(sender, e); } private void OnSourceChanged(object sender, SourceChangedEventArgs e) { // This means that the element has been added or remvoed from its source. UpdatePenContextsState(); } private void OnLayoutUpdated(object sender, EventArgs e) { // Make sure our rect and transform is up to date on layout changes. // NOTE: We need to make sure we do this under a lock if we are active for input since we don't // want the PenContexts code to get a mismatched set of state for this element. if (IsActiveForInput) { // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { // If we are currently active for input then we have a _penContexts that we must lock! lock(PenContextsSyncRoot) { UpdateRect(); } } } else { UpdateRect(); } if (_lastRenderTransform != _element.RenderTransform) { if (_renderTransformChangedEventHandler != null) { _lastRenderTransform.Changed -= _renderTransformChangedEventHandler; _renderTransformChangedEventHandler = null; } _lastRenderTransform = _element.RenderTransform; } if (_lastRenderTransform != null) { if (_lastRenderTransform.IsFrozen) { if (_renderTransformChangedEventHandler != null) { _renderTransformChangedEventHandler = null; } } else { if (_renderTransformChangedEventHandler == null) { _renderTransformChangedEventHandler = new EventHandler(OnRenderTransformChanged); _lastRenderTransform.Changed += _renderTransformChangedEventHandler; } } } } // On app ui dispatcher ////// Critical - Presentation source access /// Calls SecurityCritical routines PresentationSource.CriticalFromVisual and /// HwndSource.CriticalHandle. /// TreatAsSafe: /// - no data handed out or accepted /// [SecurityCritical,SecurityTreatAsSafe] private void UpdatePenContextsState() { bool unhookPenContexts = true; // Disable processing of the queue during blocking operations to prevent unrelated reentrancy // which a call to Lock() can cause. using (_element.Dispatcher.DisableProcessing()) { // See if we should be enabled if (_element.IsVisible && _element.IsEnabled && _element.IsHitTestVisible) { PresentationSource presentationSource = PresentationSource.CriticalFromVisual(_element as Visual); if (presentationSource != null) { unhookPenContexts = false; // Are we currently hooked up? If not then hook up. if (_penContexts == null) { InputManager inputManager = (InputManager)_element.Dispatcher.InputManager; PenContexts penContexts = inputManager.StylusLogic.GetPenContextsFromHwnd(presentationSource); // _penContexts must be non null or don't do anything. if (penContexts != null) { _penContexts = penContexts; lock(penContexts.SyncRoot) { penContexts.AddStylusPlugInCollection(this); foreach (StylusPlugIn spi in this) { spi.InvalidateIsActiveForInput(); // Uses _penContexts being set to determine active state. } // OnLayoutUpdated(this, EventArgs.Empty); } } } } } if (unhookPenContexts) { UnhookPenContexts(); } } } ////// Critical - _penContexts access /// TreatAsSafe: /// - no data handed out or accepted /// [SecurityCritical,SecurityTreatAsSafe] void UnhookPenContexts() { // Are we currently unhooked? If not then unhook. if (_penContexts != null) { lock(_penContexts.SyncRoot) { _penContexts.RemoveStylusPlugInCollection(this); // Can't recieve any more input now! _penContexts = null; // Notify after input is disabled to the PlugIns. foreach (StylusPlugIn spi in this) { spi.InvalidateIsActiveForInput(); } } } } #endregion #region Fields private UIElement _element; private Rect _rc; // In window root measured units private GeneralTransform _viewToElement; private Transform _lastRenderTransform; // Note that this is only set when the Element is in a state to receive input (visible,enabled,in tree). ////// Critical to prevent accidental spread to transparent code /// [SecurityCritical] private PenContexts _penContexts; private DependencyPropertyChangedEventHandler _isEnabledChangedEventHandler; private DependencyPropertyChangedEventHandler _isVisibleChangedEventHandler; private DependencyPropertyChangedEventHandler _isHitTestVisibleChangedEventHandler; private EventHandler _renderTransformChangedEventHandler; private SourceChangedEventHandler _sourceChangedEventHandler; private EventHandler _layoutChangedEventHandler; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConfigXmlCDataSection.cs
- PathTooLongException.cs
- BamlStream.cs
- EpmContentSerializerBase.cs
- EventLog.cs
- InvokeGenerator.cs
- HtmlImage.cs
- XpsPackagingException.cs
- DoubleLinkListEnumerator.cs
- QilTargetType.cs
- EmptyReadOnlyDictionaryInternal.cs
- OleDbDataAdapter.cs
- AsyncDataRequest.cs
- SafeHandles.cs
- BinaryUtilClasses.cs
- DocumentPageTextView.cs
- DBCSCodePageEncoding.cs
- WindowsBrush.cs
- DataControlLinkButton.cs
- Selection.cs
- RtfToXamlReader.cs
- SourceLineInfo.cs
- StateMachineExecutionState.cs
- StylusButtonEventArgs.cs
- GridPattern.cs
- ObjectItemConventionAssemblyLoader.cs
- AssertSection.cs
- SubpageParaClient.cs
- SmiRequestExecutor.cs
- ResXDataNode.cs
- SchemaReference.cs
- TextElementAutomationPeer.cs
- CodeSpit.cs
- CustomBindingElement.cs
- DataReceivedEventArgs.cs
- CompositeActivityValidator.cs
- FontDialog.cs
- ComplusTypeValidator.cs
- HelpInfo.cs
- IisTraceListener.cs
- ProtocolsConfigurationEntry.cs
- DataGridViewCellStyleChangedEventArgs.cs
- UserControl.cs
- TreeNode.cs
- ThreadStartException.cs
- SmiConnection.cs
- MarkupExtensionParser.cs
- ControlDesignerState.cs
- Range.cs
- XmlSubtreeReader.cs
- ControlCodeDomSerializer.cs
- NamedPermissionSet.cs
- TextProviderWrapper.cs
- updatecommandorderer.cs
- PlatformNotSupportedException.cs
- MobilePage.cs
- LogWriteRestartAreaState.cs
- ManagementQuery.cs
- ConvertersCollection.cs
- ObjectDataSourceView.cs
- SimpleApplicationHost.cs
- XmlSchemaChoice.cs
- EntityContainerRelationshipSet.cs
- InstancePersistenceEvent.cs
- LoginName.cs
- WorkflowApplicationIdleEventArgs.cs
- RepeaterItemCollection.cs
- CompilationUnit.cs
- WizardStepBase.cs
- dataSvcMapFileLoader.cs
- BinaryParser.cs
- IgnoreSectionHandler.cs
- InputEventArgs.cs
- SimpleMailWebEventProvider.cs
- ScalarOps.cs
- KeyedHashAlgorithm.cs
- ManagedIStream.cs
- DiscoveryDocumentSearchPattern.cs
- DBPropSet.cs
- CfgParser.cs
- StylusTouchDevice.cs
- Size.cs
- ContextInformation.cs
- BindingSource.cs
- EntityTypeEmitter.cs
- CultureData.cs
- WeakReferenceList.cs
- XsdDuration.cs
- SpoolingTaskBase.cs
- QilPatternFactory.cs
- SecurityTokenTypes.cs
- XPathBinder.cs
- ComponentCollection.cs
- TrustManagerMoreInformation.cs
- C14NUtil.cs
- BaseUriHelper.cs
- dbenumerator.cs
- SettingsPropertyIsReadOnlyException.cs
- Point3DCollection.cs
- XPathMultyIterator.cs