TextEditorDragDrop.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / TextEditorDragDrop.cs / 1305600 / TextEditorDragDrop.cs

                            //---------------------------------------------------------------------------- 
//
// File: TextEditorDragDrop.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: A Component of TextEditor class supposrtinng Drag-and-drop 
//              functionality 
//
//--------------------------------------------------------------------------- 

namespace System.Windows.Documents
{
    using MS.Internal; 
    using System.Globalization;
    using System.Threading; 
    using System.ComponentModel; 
    using System.Text;
    using System.Collections; // ArrayList 
    using System.Runtime.InteropServices;

    using System.Windows.Threading;
    using System.Windows.Input; 
    using System.Windows.Interop;  // WindowInteropHelper
    using System.Windows.Controls; // ScrollChangedEventArgs 
    using System.Windows.Controls.Primitives;  // CharacterCasing, TextBoxBase 
    using System.Windows.Data; // BindingExpression
    using System.Windows.Media; 
    using System.Windows.Markup;
    using System.Windows;
    using System.Security;
    using System.Security.Permissions; // UIPermission 

    using MS.Utility; 
    using MS.Win32; 
    using MS.Internal.Documents;
    using MS.Internal.Commands; // CommandHelpers 
    using MS.Internal.PresentationFramework;  //Demand for drag and drop

    using SecurityHelper=MS.Internal.SecurityHelper;
 
    /// 
    /// Text editing service for controls. 
    ///  
    internal static class TextEditorDragDrop
    { 
        //-----------------------------------------------------
        //
        //  Class Internal Methods
        // 
        //-----------------------------------------------------
 
        #region Class Internal Methods 

        // Registers all text editing command handlers for a given control type 
        internal static void _RegisterClassHandlers(Type controlType, bool readOnly, bool registerEventListeners)
        {
            if (!readOnly)
            { 
                EventManager.RegisterClassHandler(controlType, DragDrop.DropEvent, new DragEventHandler(OnClearState),true);
                EventManager.RegisterClassHandler(controlType, DragDrop.DragLeaveEvent, new DragEventHandler(OnClearState), true); 
            } 
            if (registerEventListeners)
            { 
                EventManager.RegisterClassHandler(controlType, DragDrop.QueryContinueDragEvent, new QueryContinueDragEventHandler(OnQueryContinueDrag));
                EventManager.RegisterClassHandler(controlType, DragDrop.GiveFeedbackEvent, new GiveFeedbackEventHandler(OnGiveFeedback));
                EventManager.RegisterClassHandler(controlType, DragDrop.DragEnterEvent, new DragEventHandler(OnDragEnter));
                EventManager.RegisterClassHandler(controlType, DragDrop.DragOverEvent, new DragEventHandler(OnDragOver)); 
                EventManager.RegisterClassHandler(controlType, DragDrop.DragLeaveEvent, new DragEventHandler(OnDragLeave));
                if (!readOnly) 
                { 
                    EventManager.RegisterClassHandler(controlType, DragDrop.DropEvent, new DragEventHandler(OnDrop));
                } 
            }
        }

        #endregion Class Internal Methods 

        //------------------------------------------------------ 
        // 
        //  Class Internal Types
        // 
        //-----------------------------------------------------

        #region Class Internal Types
 
        // A structure used for storing DragDrop status during dragging process
        internal class _DragDropProcess 
        { 
            internal _DragDropProcess(TextEditor textEditor)
            { 
                Invariant.Assert(textEditor != null);
                _textEditor = textEditor;
            }
 
            /// 
            /// Checks whether mouse down position belongs to selected portion of text, 
            /// and initiates a drad-and-drop process in this case. 
            /// Drag-drop initiation does not capture mouse yet, and do not start
            /// OleDragDrop; this will happen on a subsequent mouse move event 
            /// (if it will happen before mouse up).
            /// 
            /// 
            /// TextView-relative coordinates of mouse down event. 
            /// 
            ///  
            /// true if this mouse down was inside of selection and drag-drop process was activated. 
            /// false if the mouse down was outside of selected portion.
            ///  
            internal bool SourceOnMouseLeftButtonDown(Point mouseDownPoint)
            {
                ITextSelection selection = _textEditor.Selection;
 
                if (_textEditor.UiScope is PasswordBox)
                { 
                    // 
                    _dragStarted = false;
                } 
                else
                {
                    // Get the drag minimum width/height from SystemMetrics.DragMinimumWidth/DragMinimumHeight.
                    // dragMinimumWidth and dragMinimumheight of a rectangle centered on a drag point to allow for limited movement 
                    // of the mouse pointer before a drag operation begins.
                    // It allows the user to click and release the mouse button easily without unintentionally starting a drag operation. 
                    int minimumHorizontalDragDistance = (int)SystemParameters.MinimumHorizontalDragDistance; 
                    int minimumVerticalDragDistance = (int)SystemParameters.MinimumVerticalDragDistance;
 
                    _dragRect = new Rect(mouseDownPoint.X - minimumHorizontalDragDistance, mouseDownPoint.Y - minimumVerticalDragDistance, minimumHorizontalDragDistance * 2, minimumVerticalDragDistance * 2);

                    // Check if click happened within existing selection
                    _dragStarted = selection.Contains(mouseDownPoint); 
                }
 
                return _dragStarted; 
            }
 
            // MouseUpEvent handler.
            internal void DoMouseLeftButtonUp(MouseButtonEventArgs e)
            {
                if (_dragStarted) 
                {
                    // We get to this state when drag gesture ends within the selection, 
                    // so we only need to set selection into mouse-releasing point. 
                    if (this.TextView.IsValid)
                    { 
                        Point mouseDownPoint = e.GetPosition(_textEditor.TextView.RenderScope);
                        ITextPointer cursorPosition = this.TextView.GetTextPositionFromPoint(mouseDownPoint, /*snapToText:*/true);
                        if (cursorPosition != null)
                        { 
                            _textEditor.Selection.SetSelectionByMouse(cursorPosition, mouseDownPoint);
                        } 
                    } 
                    _dragStarted = false;
                } 
            }

            // Starts OLE dragdrop process if movement was started from
            // within selection and initial move is big enough for drag to start. 
            // Returns true if drag is in progress
            ///  
            ///   Critical: This code calls into _createDataObject 
            ///   TreatAsSafe: This will bail if called in partial trust
            ///  
            [SecurityCritical,SecurityTreatAsSafe]	
            internal bool SourceOnMouseMove(Point mouseMovePoint)
            {
                // Not allow the initiating DragDrop operation without the unmanaged code permission. 
                // We chose to use this over clipboard because this was causing issues in LocalIntranet
                // which has similar restrictions as internet but has clipboard permission 
                if (!_dragStarted || !SecurityHelper.CheckUnmanagedCodePermission()) 
                {
                    return false; // false means that drag is not involved at all - selection extension should continue 
                }

                // Check the mouse drag to start DragDrop operation.
                if (!InitialThresholdCrossed(mouseMovePoint)) 
                {
                    return true; // true means that drag is in progress, even though not yet started - so selection should not extend 
                } 

                ITextSelection selection = _textEditor.Selection; 

                // NOTE: This calls OnMouseMove recursively;
                // but because UiScope.IsMouseCaptured is false already,
                // we'll return with no actions 
                // This is the first move in drag-drop gesture.
                // Execure the whole drag-drop ssequence: returns after the drop 
                _dragStarted = false; 

                // Execute OLE drag-drop process (synchronousely) 
                // ----------------------------------------------

                // Set the original text range to delete it with DragDropEffects.Move effect.
                _dragSourceTextRange = new TextRange(selection.Start, selection.End); 

                // Prepare data object (including side effects from application customization) 
 
                // Note: _CreateDataObject raises a public event which might throw a recoverable exception.
                IDataObject dataObject = TextEditorCopyPaste._CreateDataObject(_textEditor, /*isDragDrop:*/true); 

                if (dataObject != null) // null would mean that application cancelled the command
                {
                    // 
                    SourceDoDragDrop(selection, dataObject);
 
                    // Release mouse capture, because DoDragDrop is taking 
                    // a mouse resposibility from now on.
                    // ReleaseMouseCapture shouldn't call before calling DoDragDroop 
                    // that cause the generating WM_MOUSELEAVE message by system
                    // (xxxCapture xxxCancelMouseMoverTracking) that appear MouseLeave
                    // event during DragDrop event.
                    _textEditor.UiScope.ReleaseMouseCapture(); 

                    return true; // true means that drag is in progress. Selection should not extend. 
                } 
                else
                { 
                    // The DragDrop process has been terminated by application custom code
                    //
                    return false;
                } 
            }
 
            // Check whether the mouse is dragged with the minimum width and height. 
            // _dragRect is Width and height of a rectangle centered on a drag point to allow for limited movement
            // of the mouse pointer before a drag operation begins. 
            // It allows the user to click and release the mouse button easily without unintentionally starting a drag operation.
            private bool InitialThresholdCrossed(Point dragPoint)
            {
                // Check the current poisition is in the drag rect. 
                return !_dragRect.Contains(dragPoint.X, dragPoint.Y);
            } 
 
            /// 
            /// DragEnd event handler from DragDrop behavior. 
            /// 
            private void SourceDoDragDrop(ITextSelection selection, IDataObject dataObject)
            {
                // Run OLE drag-drop process. It will eat all user input until the drop 
                DragDropEffects allowedDragDropEffects = DragDropEffects.Copy;
                if (!_textEditor.IsReadOnly) 
                { 
                    allowedDragDropEffects |= DragDropEffects.Move;
                } 

                DragDropEffects resultingDragDropEffects = DragDrop.DoDragDrop( //
                    _textEditor.UiScope, // dragSource,
                    dataObject, // 
                    allowedDragDropEffects);
 
                // Remove source selection 
                if (!_textEditor.IsReadOnly && //
                    resultingDragDropEffects == DragDropEffects.Move && // 
                    _dragSourceTextRange != null &&
                    !_dragSourceTextRange.IsEmpty)
                {
                    // Normally we delete the source selection from OnDrop event, 
                    // unless source and target TextBoxes are different.
                    // In this case the source selection is still not empty, 
                    // which means that target was in a different TextBox. 
                    // So we still need to delete the selected content in the source one.
                    // This will create an undo unit different from a dropping one, 
                    // which is ok, because it will be in different TextBox's undo stack.
                    using (selection.DeclareChangeBlock())
                    {
                        // This is end of Move - we need to delete source content 
                        _dragSourceTextRange.Text = String.Empty;
                    } 
                } 

                // Clean up the text range. 
                _dragSourceTextRange = null;

                // Check the data binding expression and update the source and target if the drag source
                // has the binding expression. Without this, data binding is broken after complete the 
                // drag-drop operation because Drop() paste the object then set the focus to the target.
                // The losting focus invoke the data binding expression's Update(), but the source isn't 
                // updated yet before complete DoDragDrop. 
                if (!_textEditor.IsReadOnly)
                { 
                    BindingExpressionBase bindingExpression = BindingOperations.GetBindingExpressionBase(
                        _textEditor.UiScope, TextBox.TextProperty);
                    if (bindingExpression != null)
                    { 
                        bindingExpression.UpdateSource();
                        bindingExpression.UpdateTarget(); 
                    } 
                }
            } 

            // Creates DropCaret
            internal void TargetEnsureDropCaret()
            { 
                if (_caretDragDrop == null)
                { 
                    // 

                    // Add the caret. 
                    // Create caret to show it during the dragging operation.
                    _caretDragDrop = new CaretElement(_textEditor, /*isBlinkEnabled:*/false);

                    // Initialize the caret. 
                    //
                    _caretDragDrop.Hide(); 
                } 
            }
 
            /// A handler for an event reporting that the drag enter during drag-and-drop operation.
            internal void TargetOnDragEnter(DragEventArgs e)
            {
                if (!AllowDragDrop(e)) 
                {
                    return; 
                } 

                // Ok, there's data to move or copy here. 
                if ((e.AllowedEffects & DragDropEffects.Move) != 0)
                {
                    e.Effects = DragDropEffects.Move;
                } 

                bool ctrlKeyDown = ((int)(e.KeyStates & DragDropKeyStates.ControlKey) != 0); 
                if (ctrlKeyDown) 
                {
                    e.Effects |= DragDropEffects.Copy; 
                }

                // Create the drag-and-drop caret to show it on the drop target candidate place.
                TargetEnsureDropCaret(); 
            }
 
            /// A handler for an event reporting that the drag over during drag-and-drop operation. 
            internal void TargetOnDragOver(DragEventArgs e)
            { 
                if (!AllowDragDrop(e))
                {
                    return;
                } 

                // Ok, there's data to move or copy here. 
                if ((e.AllowedEffects & DragDropEffects.Move) != 0) 
                {
                    e.Effects = DragDropEffects.Move; 
                }

                bool ctrlKeyDown = ((int)(e.KeyStates & DragDropKeyStates.ControlKey) != 0);
                if (ctrlKeyDown) 
                {
                    e.Effects |= DragDropEffects.Copy; 
                } 

                // Show the caret on the drag over target position. 
                if (_caretDragDrop != null)
                {
                    // Update the layout to get the corrected text position. Otherwise, we can get the
                    // incorrected text position. 
                    if (!_textEditor.TextView.Validate(e.GetPosition(_textEditor.TextView.RenderScope)))
                    { 
                        return; 
                    }
 
                    // Find the scroller from the render scope
                    FrameworkElement scroller = _textEditor._Scroller;

                    // Automatically scroll the dropable content(line or page up/down) if scroller is available 
                    if (scroller != null)
                    { 
                        // Get the ScrollInfo to scroll a line or page up/down 
                        IScrollInfo scrollInfo = scroller as IScrollInfo;
 
                        if (scrollInfo == null && scroller is ScrollViewer)
                        {
                            scrollInfo = ((ScrollViewer)scroller).ScrollInfo;
                        } 

                        Invariant.Assert(scrollInfo != null); 
 
                        // Takes care of scrolling mechanism when vertical scrollbar is available, it creates a virtual
                        // block within the viewport where if you position your mouse during drag leads to scrolling,here 
                        // it is of 16pixels and within first 8pixels it does scrolling by line and for next it scrolls by page.

                        Point pointScroller = e.GetPosition((IInputElement)scroller);
                        double pageHeight = (double)_textEditor.UiScope.GetValue(TextEditor.PageHeightProperty); 
                        double slowAreaHeight = ScrollViewer._scrollLineDelta;
 
                        if (pointScroller.Y < slowAreaHeight) 
                        {
                            // Drag position is on the scroll area that we need to scroll up 
                            if (pointScroller.Y > slowAreaHeight / 2)
                            {
                                // scroll a line up
                                scrollInfo.LineUp(); 
                            }
                            else 
                            { 
                                // scroll a page up
                                scrollInfo.PageUp(); 
                            }
                        }
                        else if (pointScroller.Y > (pageHeight - slowAreaHeight))
                        { 
                            // Drag position is on the scroll area that we need to scroll down
                            if (pointScroller.Y < (pageHeight - slowAreaHeight / 2)) 
                            { 
                                // scroll a line down
                                scrollInfo.LineDown(); 
                            }
                            else
                            {
                                // scroll a page down 
                                scrollInfo.PageDown();
                            } 
                        } 
                    }
 
                    // Get the current text position from the dropable mouse point.
                    _textEditor.TextView.RenderScope.UpdateLayout(); //

                    if (_textEditor.TextView.IsValid) 
                    {
                        ITextPointer dragPosition = GetDropPosition(_textEditor.TextView.RenderScope as Visual, e.GetPosition(_textEditor.TextView.RenderScope)); 
 
                        if (dragPosition != null)
                        { 
                            // Get the caret position to show the dropable point.
                            Rect caretRectangle = this.TextView.GetRectangleFromTextPosition(dragPosition);

                            // NOTE: We DO NOT use GetCurrentValue because springload formatting should NOT be involved for drop caret. 
                            object fontStylePropertyValue = dragPosition.GetValue(TextElement.FontStyleProperty);
                            bool italic = (_textEditor.AcceptsRichContent && fontStylePropertyValue != DependencyProperty.UnsetValue && (FontStyle)fontStylePropertyValue == FontStyles.Italic); 
                            Brush caretBrush = TextSelection.GetCaretBrush(_textEditor); 

                            // Show the caret on the dropable position. 
                            _caretDragDrop.Update(/*visible:*/true, caretRectangle, caretBrush, 0.5, italic, CaretScrollMethod.None, /*wordWrappingPosition*/ double.NaN);
                        }
                    }
                } 
            }
 
            ///  
            /// Calculates a TextPointer indended for dropping the text.
            ///  
            /// 
            /// 
            /// 
            /// ITextPointer intended for dropping the selected text. 
            /// Adjusts the dropping point to a word boundary (beginning of word)
            /// in case if source range contains whole words. 
            /// The position returned is oriented towards a character 
            /// under the mouse pointer.
            ///  
            private ITextPointer GetDropPosition(Visual target, Point point)
            {
                Invariant.Assert(target != null);
                Invariant.Assert(_textEditor.TextView.IsValid); // caller must guarantee this. 

                // Convert point to RenderScope 
                if (target != _textEditor.TextView.RenderScope && target != null && (_textEditor.TextView.RenderScope).IsAncestorOf(target)) 
                {
                    GeneralTransform transform = target.TransformToAncestor(_textEditor.TextView.RenderScope); 
                    transform.TryTransform(point, out point);
                }

                ITextPointer dropPosition = this.TextView.GetTextPositionFromPoint(point, /*snapToText:*/true); 

                // For rich text content we adjust drop position to word boundary 
                if (dropPosition != null) 
                {
                    // Normalize drop position 
                    dropPosition = dropPosition.GetInsertionPosition(dropPosition.LogicalDirection);

                    if (_textEditor.AcceptsRichContent)
                    { 
                        TextSegment lineRange = TextEditorSelection.GetNormalizedLineRange(this.TextView, dropPosition);
 
                        if (!lineRange.IsNull && 
                            // The drop position must be before of end of line
                            dropPosition.CompareTo(lineRange.End) < 0 && 
                            // We check if we are not at word boundary already:
                            !TextPointerBase.IsAtWordBoundary(dropPosition, /*insideWordDirection:*/LogicalDirection.Forward) &&
                            // We do not do it if the source range was not on word boundaries from both ends
                            _dragSourceTextRange != null && // 
                            TextPointerBase.IsAtWordBoundary(_dragSourceTextRange.Start, LogicalDirection.Forward) && //
                            TextPointerBase.IsAtWordBoundary(_dragSourceTextRange.End, LogicalDirection.Forward)) 
                        { 
                            // Move to word boundary. Select closest one to a dropPosition.
                            TextSegment wordSegment = TextPointerBase.GetWordRange(dropPosition); 
                            string wordText = TextRangeBase.GetTextInternal(wordSegment.Start, wordSegment.End);
                            int indexInWord = wordSegment.Start.GetOffsetToPosition(dropPosition);
                            dropPosition = (indexInWord < (wordText.Length / 2)) ? wordSegment.Start : wordSegment.End;
                        } 
                    }
                } 
 
                return dropPosition;
            } 

            /// 
            /// Responsible for deleteing the caret.
            ///  
            internal void DeleteCaret()
            { 
                // Delete the caret 
                if (_caretDragDrop != null)
                { 
                    AdornerLayer layer = AdornerLayer.GetAdornerLayer(TextView.RenderScope);
                    layer.Remove(_caretDragDrop);
                    _caretDragDrop = null;
                } 
            }
 
            ///  
            /// Called from an event reporting that the drop happened.
            ///  
            internal void TargetOnDrop(DragEventArgs e)
            {
                //
 
                if (!AllowDragDrop(e))
                { 
                    return; 
                }
 
                ITextSelection selection = _textEditor.Selection;
                Invariant.Assert(selection != null);

                if (e.Data == null || e.AllowedEffects == DragDropEffects.None) 
                {
                    e.Effects = DragDropEffects.None; 
                    return; 
                }
 
                if ((int)(e.KeyStates & DragDropKeyStates.ControlKey) != 0)
                {
                    e.Effects = DragDropEffects.Copy;
                } 
                else if (e.Effects != DragDropEffects.Copy)
                { 
                    e.Effects = DragDropEffects.Move; 
                }
 
                // Force a layout update on the content so the GetTextPositionFromPoint
                // call following can succeed.
                if (!_textEditor.TextView.Validate(e.GetPosition(_textEditor.TextView.RenderScope)))
                { 
                    e.Effects = DragDropEffects.None;
                    return; 
                } 

                // Get the text position from the text target point. 
                ITextPointer dropPosition = GetDropPosition(_textEditor.TextView.RenderScope as Visual, e.GetPosition(_textEditor.TextView.RenderScope));

                if (dropPosition != null)
                { 
                    if (_dragSourceTextRange != null && _dragSourceTextRange.Start.TextContainer == selection.Start.TextContainer &&
                        !selection.IsEmpty && IsSelectionContainsDropPosition(selection, dropPosition)) 
                    { 
                        // When we drop inside of selected area, we
                        // should not select dropped content, 
                        // otherwise it looks for end user as if
                        // nothing happened.

                        // Set caret to this position. 
                        selection.SetCaretToPosition(dropPosition, LogicalDirection.Backward, /*allowStopAtLineEnd:*/false, /*allowStopNearSpace:*/true);
 
                        // Indicate the resulting effect of an action 
                        // Note that dropResult may stay equal to DragDropResult.Drop
                        e.Effects = DragDropEffects.None; 

                        // Mark the event as handled
                        e.Handled = true;
                    } 
                    else
                    { 
                        using (selection.DeclareChangeBlock()) 
                        {
                            // For MaxLength filter work correctly in case 
                            // when we dragdrop within the same TextContainer,
                            // we need to delete dragged content first -
                            // before dropping when filtering will occur.
                            // Note, that this will duplicate operation on 
                            // source side, but it will be void deletion action
                            if ((e.Effects & DragDropEffects.Move) != 0 && // 
                                _dragSourceTextRange != null && _dragSourceTextRange.Start.TextContainer == selection.Start.TextContainer) 
                            {
                                _dragSourceTextRange.Text = String.Empty; 
                            }

                            // When we drop outside of selection,
                            // we should ignore current selection and 
                            // move ip into dropping point.
                            selection.SetCaretToPosition(dropPosition, LogicalDirection.Backward, /*allowStopAtLineEnd:*/false, /*allowStopNearSpace:*/true); 
 
                            // _DoPaste raises a public event -- could raise recoverable exception.
                            e.Handled = TextEditorCopyPaste._DoPaste(_textEditor, e.Data, /*isDragDrop:*/true); 
                            //
                        }
                    }
 
                    if (e.Handled)
                    { 
                        // Set the drop target as the foreground window. 
                        Win32SetForegroundWindow();
 
                        // Set the focus into the drop target.
                        _textEditor.UiScope.Focus();
                    }
                    else 
                    {
                        // When a target did not handle a drop event, we must 
                        // prevent from deleting a content on source end - 
                        // otherwise we'll have data loss
                        e.Effects = DragDropEffects.None; 
                    }
                }
            }
 
            // Table cell selection currently include the next adjacent cell start element so that
            // selection always contains the drop position even though the drop position is on the next cell. 
            // This private method check the table range really contains the drop position or not. 
            private bool IsSelectionContainsDropPosition(ITextSelection selection, ITextPointer dropPosition)
            { 
                bool selectionContainedDropPosition = selection.Contains(dropPosition);

                if (selectionContainedDropPosition && selection.IsTableCellRange)
                { 
                    for (int i = 0; i < selection.TextSegments.Count; i++)
                    { 
                        TextSegment textSegment = selection._TextSegments[i]; 

                        if (dropPosition.CompareTo(textSegment.End) == 0) 
                        {
                            selectionContainedDropPosition = false;
                            break;
                        } 
                    }
                } 
 
                return selectionContainedDropPosition;
            } 

            private bool AllowDragDrop(DragEventArgs e)
            {
                if (!_textEditor.IsReadOnly && _textEditor.TextView != null && _textEditor.TextView.RenderScope != null) 
                {
                    Window window = Window.GetWindow(_textEditor.TextView.RenderScope); 
                    if (window == null) 
                    {
                        return true; 
                    }

                    WindowInteropHelper helper = new WindowInteropHelper(window);
                    if (SafeNativeMethods.IsWindowEnabled(new HandleRef(null, helper.Handle))) 
                    {
                        return true; 
                    } 
                }
 
                e.Effects = DragDropEffects.None;
                return false;
            }
 
            /// 
            /// Call Win32 SetForegroundWindow to set the drop target as the foreground window. 
            ///  
            /// 
            /// Critical - This calls PresentationSource.FromVisual() and PresentationSource.Handle 
            ///            under elevation.
            /// Safe - This doesn't expose the information. The SetForegroundWindow call will only
            ///        set the drop window as the foreground without exposing the information.
            ///  
            [SecurityCritical, SecurityTreatAsSafe]
            private void Win32SetForegroundWindow() 
            { 
                PresentationSource source = null;
                IntPtr hwnd = IntPtr.Zero; 
                source = PresentationSource.CriticalFromVisual(_textEditor.UiScope);
                if (source != null)
                {
                    new UIPermission(UIPermissionWindow.AllWindows).Assert();   //BlessedAssert 
                    try
                    { 
                        hwnd = (source as IWin32Window).Handle; 
                    }
                    finally 
                    {

                        UIPermission.RevertAssert();
                    } 
                }
 
                if (hwnd != IntPtr.Zero) 
                {
                    UnsafeNativeMethods.SetForegroundWindow(new HandleRef(null, hwnd)); 
                }
            }

            private ITextView TextView 
            {
                get 
                { 
                    return _textEditor.TextView;
                } 
            }

            private TextEditor _textEditor;
 
            // TextRange for drag source.
            private ITextRange _dragSourceTextRange; 
 
            // Flag indicating that mouse dragging was started within selection.
            // It is used for deferring drag/drop until first move, 
            // and for setting selection on mouseup in case of no move.
            private bool _dragStarted;

            // DragDrop caret to show it on the dropable target position. 
            //
 
 

            private CaretElement _caretDragDrop; 

            // Rectangle centered on a drag point to allow for limited movement of the mouse pointer before a drag operation begins.
            private Rect _dragRect;
        } 

        ///  
        /// An event reporting that the query continue drag during drag-and-drop operation. 
        /// 
        internal static void OnQueryContinueDrag(object sender, QueryContinueDragEventArgs e) 
        {
            TextEditor This = TextEditor._GetTextEditor(sender);

            if (This == null) 
            {
                return; 
            } 

            // Ignore the event if the editor has been detached from its scope 
            if (!This._IsEnabled)
            {
                return;
            } 

            // Consider event handled 
            e.Handled = true; 

            e.Action = DragAction.Continue; 
            bool mouseUp = (((int)e.KeyStates & (int)DragDropKeyStates.LeftMouseButton) == 0);
            if (e.EscapePressed)
            {
                e.Action = DragAction.Cancel; 
            }
            else if (mouseUp) 
            { 
                e.Action = DragAction.Drop;
            } 
        }

        /// 
        /// An event reporting that the give feedback during drag-and-drop operation. 
        /// 
        internal static void OnGiveFeedback(object sender, GiveFeedbackEventArgs e) 
        { 
            TextEditor This = TextEditor._GetTextEditor(sender);
 
            if (This == null)
            {
                return;
            } 

            // Ignore the event if the editor has been detached from its scope 
            if (!This._IsEnabled) 
            {
                return; 
            }

            // Show the default DragDrop cursor.
            e.UseDefaultCursors = true; 

            // Consider event handled 
            e.Handled = true; 
        }
 
        /// 
        /// An event reporting that the drag enter during drag-and-drop operation.
        /// 
        internal static void OnDragEnter(object sender, DragEventArgs e) 
        {
            // Consider event handled 
            e.Handled = true; 

            TextEditor This = TextEditor._GetTextEditor(sender); 

            if (This == null)
            {
                e.Effects = DragDropEffects.None; 
                return;
            } 
 
            // Ignore the event if the editor has been detached from its scope
            if (!This._IsEnabled || This.TextView == null || This.TextView.RenderScope == null) 
            {
                e.Effects = DragDropEffects.None;
                return;
            } 

            // If there's no supported data available, don't allow the drag-and-drop. 
            if (e.Data == null) 
            {
                e.Effects = DragDropEffects.None; 
                return;
            }

            // Ignore the event if there isn't the dropable(pasteable) data format 
            if (TextEditorCopyPaste.GetPasteApplyFormat(This, e.Data) == string.Empty)
            { 
                e.Effects = DragDropEffects.None; 
                return;
            } 

            TextEditorTyping._FlushPendingInputItems(This);

            if (!This.TextView.Validate(e.GetPosition(This.TextView.RenderScope))) 
            {
                e.Effects = DragDropEffects.None; 
                return; 
            }
 
            This._dragDropProcess.TargetOnDragEnter(e);
        }

        ///  
        /// An event reporting that the drag over during drag-and-drop operation.
        ///  
        internal static void OnDragOver(object sender, DragEventArgs e) 
        {
            // Consider event handled 
            e.Handled = true;

            TextEditor This = TextEditor._GetTextEditor(sender);
 
            if (This == null)
            { 
                e.Effects = DragDropEffects.None; 
                return;
            } 

            // Ignore the event if the editor has been detached from its scope
            if (!This._IsEnabled || This.TextView == null || This.TextView.RenderScope == null)
            { 
                e.Effects = DragDropEffects.None;
                return; 
            } 

            // If there's no supported data available, don't allow the drag-and-drop. 
            if (e.Data == null)
            {
                e.Effects = DragDropEffects.None;
                return; 
            }
 
            // Ignore the event if there isn't the dropable(pasteable) data format 
            if (TextEditorCopyPaste.GetPasteApplyFormat(This, e.Data) == string.Empty)
            { 
                e.Effects = DragDropEffects.None;
                return;
            }
 
            TextEditorTyping._FlushPendingInputItems(This);
            if (!This.TextView.Validate(e.GetPosition(This.TextView.RenderScope))) 
            { 
                e.Effects = DragDropEffects.None;
                return; 
            }

            This._dragDropProcess.TargetOnDragOver(e);
        } 

        ///  
        /// An event reporting that the drag leave during drag-and-drop operation. 
        /// 
        internal static void OnDragLeave(object sender, DragEventArgs e) 
        {
            // Consider event handled
            e.Handled = true;
 
            TextEditor This = TextEditor._GetTextEditor(sender);
 
            if (This == null) 
            {
                return; 
            }

            //
            // Remove UI feedback here if UI is specified on DragEnter. 
            //
            // Ignore the event if the editor has been detached from its scope 
            if (!This._IsEnabled) 
            {
                e.Effects = DragDropEffects.None; 
                return;
            }

            TextEditorTyping._FlushPendingInputItems(This); 
            if (!This.TextView.Validate(e.GetPosition(This.TextView.RenderScope)))
            { 
                return; 
            }
 
        }

        /// 
        /// An event reporting that the drop happened. 
        /// 
        internal static void OnDrop(object sender, DragEventArgs e) 
        { 
            TextEditor This = TextEditor._GetTextEditor(sender);
 
            if (This == null)
            {
                return;
            } 

            // Ignore the event if the editor has been detached from its scope 
            if (!This._IsEnabled) 
            {
                return; 
            }

            TextEditorTyping._FlushPendingInputItems(This);
            if (!This.TextView.Validate(e.GetPosition(This.TextView.RenderScope))) 
            {
                return; 
            } 

            This._dragDropProcess.TargetOnDrop(e); 
        }

        /// 
        /// An event for clearing the state of the Text Editor after events like drop or drag leave, 
        /// Currently, It's clearing the caret which is drawn during dragOver and have never been deleted.
        ///  
        internal static void OnClearState(object sender, DragEventArgs e) 
        {
            TextEditor This = TextEditor._GetTextEditor(sender); 

            if (This == null)
            {
                return; 
            }
 
           This._dragDropProcess.DeleteCaret(); 

        } 

        #endregion Class Internal Types
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK