Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / DragDrop.cs / 2 / DragDrop.cs
//----------------------------------------------------------------------------
//
// File: DragDrop.cs
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// Description: The DragDrop system is for drag-and-drop operation.
//
// See spec at [....]/uis/Data%20Transfer%20clipboard%20dragdrop/DragDrop%20design%20on%20WPP.mht
//
// History:
// 07/10/2003 : [....] Created
// 08/19/2004 : [....] Event name changes and code clean up
//
//---------------------------------------------------------------------------
using MS.Win32;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Threading;
using System.Security;
using System.Security.Permissions;
using MS.Internal;
using MS.Internal.PresentationCore;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;
namespace System.Windows
{
#region DragDrop
///
/// Provides drag-and-drop operation methods.
///
public static class DragDrop
{
//-----------------------------------------------------
//
// DragDrop Event
//
//-----------------------------------------------------
#region DragDrop Event
///
/// PreviewQueryContinueDrag
///
public static readonly RoutedEvent PreviewQueryContinueDragEvent = EventManager.RegisterRoutedEvent("PreviewQueryContinueDrag", RoutingStrategy.Tunnel, typeof(QueryContinueDragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the PreviewQueryContinueDrag attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddPreviewQueryContinueDragHandler(DependencyObject element, QueryContinueDragEventHandler handler)
{
UIElement.AddHandler(element, PreviewQueryContinueDragEvent, handler);
}
///
/// Removes a handler for the PreviewQueryContinueDrag attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemovePreviewQueryContinueDragHandler(DependencyObject element, QueryContinueDragEventHandler handler)
{
UIElement.RemoveHandler(element, PreviewQueryContinueDragEvent, handler);
}
///
/// QueryContinueDrag
///
public static readonly RoutedEvent QueryContinueDragEvent = EventManager.RegisterRoutedEvent("QueryContinueDrag", RoutingStrategy.Bubble, typeof(QueryContinueDragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the QueryContinueDrag attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddQueryContinueDragHandler(DependencyObject element, QueryContinueDragEventHandler handler)
{
UIElement.AddHandler(element, QueryContinueDragEvent, handler);
}
///
/// Removes a handler for the QueryContinueDrag attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemoveQueryContinueDragHandler(DependencyObject element, QueryContinueDragEventHandler handler)
{
UIElement.RemoveHandler(element, QueryContinueDragEvent, handler);
}
///
/// PreviewGiveFeedback
///
public static readonly RoutedEvent PreviewGiveFeedbackEvent = EventManager.RegisterRoutedEvent("PreviewGiveFeedback", RoutingStrategy.Tunnel, typeof(GiveFeedbackEventHandler), typeof(DragDrop));
///
/// Adds a handler for the PreviewGiveFeedback attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddPreviewGiveFeedbackHandler(DependencyObject element, GiveFeedbackEventHandler handler)
{
UIElement.AddHandler(element, PreviewGiveFeedbackEvent, handler);
}
///
/// Removes a handler for the PreviewGiveFeedback attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemovePreviewGiveFeedbackHandler(DependencyObject element, GiveFeedbackEventHandler handler)
{
UIElement.RemoveHandler(element, PreviewGiveFeedbackEvent, handler);
}
///
/// GiveFeedback
///
public static readonly RoutedEvent GiveFeedbackEvent = EventManager.RegisterRoutedEvent("GiveFeedback", RoutingStrategy.Bubble, typeof(GiveFeedbackEventHandler), typeof(DragDrop));
///
/// Adds a handler for the GiveFeedback attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddGiveFeedbackHandler(DependencyObject element, GiveFeedbackEventHandler handler)
{
UIElement.AddHandler(element, GiveFeedbackEvent, handler);
}
///
/// Removes a handler for the GiveFeedback attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemoveGiveFeedbackHandler(DependencyObject element, GiveFeedbackEventHandler handler)
{
UIElement.RemoveHandler(element, GiveFeedbackEvent, handler);
}
///
/// PreviewDragEnter
///
public static readonly RoutedEvent PreviewDragEnterEvent = EventManager.RegisterRoutedEvent("PreviewDragEnter", RoutingStrategy.Tunnel, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the PreviewDragEnter attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddPreviewDragEnterHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, PreviewDragEnterEvent, handler);
}
///
/// Removes a handler for the PreviewDragEnter attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemovePreviewDragEnterHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, PreviewDragEnterEvent, handler);
}
///
/// DragEnter
///
public static readonly RoutedEvent DragEnterEvent = EventManager.RegisterRoutedEvent("DragEnter", RoutingStrategy.Bubble, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the DragEnter attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddDragEnterHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, DragEnterEvent, handler);
}
///
/// Removes a handler for the DragEnter attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemoveDragEnterHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, DragEnterEvent, handler);
}
///
/// PreviewDragOver
///
public static readonly RoutedEvent PreviewDragOverEvent = EventManager.RegisterRoutedEvent("PreviewDragOver", RoutingStrategy.Tunnel, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the PreviewDragOver attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddPreviewDragOverHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, PreviewDragOverEvent, handler);
}
///
/// Removes a handler for the PreviewDragOver attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemovePreviewDragOverHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, PreviewDragOverEvent, handler);
}
///
/// DragOver
///
public static readonly RoutedEvent DragOverEvent = EventManager.RegisterRoutedEvent("DragOver", RoutingStrategy.Bubble, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the DragOver attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddDragOverHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, DragOverEvent, handler);
}
///
/// Removes a handler for the DragOver attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemoveDragOverHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, DragOverEvent, handler);
}
///
/// PreviewDragLeave
///
public static readonly RoutedEvent PreviewDragLeaveEvent = EventManager.RegisterRoutedEvent("PreviewDragLeave", RoutingStrategy.Tunnel, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the PreviewDragLeave attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddPreviewDragLeaveHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, PreviewDragLeaveEvent, handler);
}
///
/// Removes a handler for the PreviewDragLeave attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemovePreviewDragLeaveHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, PreviewDragLeaveEvent, handler);
}
///
/// DragLeave
///
public static readonly RoutedEvent DragLeaveEvent = EventManager.RegisterRoutedEvent("DragLeave", RoutingStrategy.Bubble, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the DragLeave attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddDragLeaveHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, DragLeaveEvent, handler);
}
///
/// Removes a handler for the DragLeave attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemoveDragLeaveHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, DragLeaveEvent, handler);
}
///
/// PreviewDrop
///
public static readonly RoutedEvent PreviewDropEvent = EventManager.RegisterRoutedEvent("PreviewDrop", RoutingStrategy.Tunnel, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the PreviewDrop attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddPreviewDropHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, PreviewDropEvent, handler);
}
///
/// Removes a handler for the PreviewDrop attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemovePreviewDropHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, PreviewDropEvent, handler);
}
///
/// Drop
///
public static readonly RoutedEvent DropEvent = EventManager.RegisterRoutedEvent("Drop", RoutingStrategy.Bubble, typeof(DragEventHandler), typeof(DragDrop));
///
/// Adds a handler for the Drop attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be added
public static void AddDropHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.AddHandler(element, DropEvent, handler);
}
///
/// Removes a handler for the Drop attached event
///
/// UIElement or ContentElement that listens to this event
/// Event Handler to be removed
public static void RemoveDropHandler(DependencyObject element, DragEventHandler handler)
{
UIElement.RemoveHandler(element, DropEvent, handler);
}
#endregion DragDrop Event
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// Begins a drag-and-drop operation.
///
///
/// The drag source object.
///
///
/// The data to drag.
///
///
/// The allowed effects that is one of the DragDropEffects values.
///
///
/// Requires UnmanagedCode permission.
/// If caller does not have this permission, the dragdrop will not occur.
///
///
/// Critical - calls critical code (OleDoDragDrop), but this is OK since we won't
/// allow the initiate DragDrop operation without the unmanaged code permission.
/// Demand the unmanaged code permission to block initiating DragDrop both
/// intranet and internet zone.
/// PublicOK - It's disabled in partial trust.
///
[SecurityCritical]
public static DragDropEffects DoDragDrop(DependencyObject dragSource, object data, DragDropEffects allowedEffects)
{
DataObject dataObject;
// Demand the unmanaged code permission to initiate DragDrop operation.
SecurityHelper.DemandUnmanagedCode();
if (dragSource == null)
{
throw new ArgumentNullException("dragSource");
}
if (data == null)
{
throw new ArgumentNullException("data");
}
dataObject = data as DataObject;
if (dataObject == null)
{
// Create DataObject for DragDrop from the data.
dataObject = new DataObject(data);
}
// Call OleDoDragDrop with DataObject.
return OleDoDragDrop(dragSource, dataObject, allowedEffects);
}
#endregion Public Methods
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
#region Internal Methods
///
/// Register the drop target which want to a droppable window.
///
///
/// The window handle to be drop target .
///
///
/// Critical - calls critical code (OleRegisterDragDrop), and potentially deals with unmanged code..
///
/// TreatAsSafe - RegisterDropTarget check the unmanged code permission.
/// Demmand the unmanaged code permission to block the register drop target
/// both intranet and internet zone.
///
[SecurityCritical, SecurityTreatAsSafe]
internal static void RegisterDropTarget(IntPtr windowHandle)
{
if (SecurityHelper.CheckUnmanagedCodePermission() && windowHandle != IntPtr.Zero)
{
// Create OleDragSource and call Ole DoDragDrop for starting DragDrop.
OleDropTarget oleDropTarget = new OleDropTarget(windowHandle);
// Call OLE RegisterDragDrop and it will get the drop target events during drag-and-drop
// operation on the drop target window.
OleServicesContext.CurrentOleServicesContext.OleRegisterDragDrop(
new HandleRef(null, windowHandle),
(UnsafeNativeMethods.IOleDropTarget)oleDropTarget);
}
}
///
/// Revoke the drop target which was a droppable window.
///
///
/// The window handle that can accept drop.
///
///
/// Critical - calls critical code (OleRevokeDragDrop).We do not want this called excessively
/// TreatAsSafe - RevokeDropTarget check the unmanged code permission.
/// Demmand the unmanaged code permission to block the revoke drop target
/// both intranet and internet zone.
///
[SecurityCritical, SecurityTreatAsSafe]
internal static void RevokeDropTarget(IntPtr windowHandle)
{
if (SecurityHelper.CheckUnmanagedCodePermission() && windowHandle != IntPtr.Zero)
{
// Call OLE RevokeDragDrop to revoke the droppable target window.
OleServicesContext.CurrentOleServicesContext.OleRevokeDragDrop(
new HandleRef(null, windowHandle));
}
}
///
/// Validate the dragdrop effects of DragDrop.
///
internal static bool IsValidDragDropEffects(DragDropEffects dragDropEffects)
{
int dragDropEffectsAll;
dragDropEffectsAll = (int)(DragDropEffects.None |
DragDropEffects.Copy |
DragDropEffects.Move |
DragDropEffects.Link |
DragDropEffects.Scroll |
DragDropEffects.All);
if (((int)dragDropEffects & ~dragDropEffectsAll) != 0)
{
return false;
}
return true;
}
///
/// Validate the drag action of DragDrop.
///
internal static bool IsValidDragAction(DragAction dragAction)
{
if (dragAction == DragAction.Continue ||
dragAction == DragAction.Drop ||
dragAction == DragAction.Cancel)
{
return true;
}
else
{
return false;
}
}
///
/// Validate the key states of DragDrop.
///
internal static bool IsValidDragDropKeyStates(DragDropKeyStates dragDropKeyStates)
{
int keyStatesAll;
keyStatesAll = (int)(DragDropKeyStates.LeftMouseButton |
DragDropKeyStates.RightMouseButton |
DragDropKeyStates.ShiftKey |
DragDropKeyStates.ControlKey |
DragDropKeyStates.MiddleMouseButton |
DragDropKeyStates.AltKey);
if (((int)dragDropKeyStates & ~keyStatesAll) != 0)
{
return false;
}
return true;
}
#endregion Internal Methods
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region Private Methods
///
/// Begins a drag-and-drop operation through OLE DoDragDrop.
///
///
/// The drag source object.
///
///
/// The data object to drag.
///
///
/// The allowed effects that is one of the DragDropEffects values.
///
private static DragDropEffects OleDoDragDrop(DependencyObject dragSource, DataObject dataObject, DragDropEffects allowedEffects)
{
int[] dwEffect;
OleDragSource oleDragSource;
Debug.Assert(dragSource != null, "Invalid dragSource");
Debug.Assert(dataObject != null, "Invalid dataObject");
// Create the int array for passing parameter of OLE DoDragDrop
dwEffect = new int[1];
// Create OleDragSource and call Ole DoDragDrop for starting DragDrop.
oleDragSource = new OleDragSource(dragSource);
// Call OLE DoDragDrop and it will hanlde all mouse and keyboard input until drop the object.
// We don't need to check the error return since PreserveSig attribute is defined as "false"
// which will pops up the exception automatically.
OleServicesContext.CurrentOleServicesContext.OleDoDragDrop(
(IComDataObject)dataObject,
(UnsafeNativeMethods.IOleDropSource)oleDragSource,
(int)allowedEffects,
dwEffect);
// return the drop effect of DragDrop.
return (DragDropEffects)dwEffect[0];
}
#endregion Private Methods
}
#endregion DragDrop
#region OleDragSource
///
/// OleDragSource that handle ole QueryContinueDrag and GiveFeedback.
///
internal class OleDragSource : UnsafeNativeMethods.IOleDropSource
{
//-----------------------------------------------------
//
// Constructor
//
//-----------------------------------------------------
#region Constructor
///
/// OleDragSource constructor.
///
public OleDragSource(DependencyObject dragSource)
{
_dragSource = dragSource;
}
#endregion Constructor
//-----------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
#region IOleDropSource
///
/// Query the source to know the drag continue or not.
///
int UnsafeNativeMethods.IOleDropSource.OleQueryContinueDrag(int escapeKey, int grfkeyState)
{
bool escapePressed;
QueryContinueDragEventArgs args;
escapePressed = false;
if (escapeKey != 0)
{
escapePressed = true;
}
// Create QueryContinueDrag event arguments.
args = new QueryContinueDragEventArgs(escapePressed, (DragDropKeyStates)grfkeyState);
// Raise the query continue drag event for both Tunnel(Preview) and Bubble.
RaiseQueryContinueDragEvent(args);
// Check the drag continue result.
if (args.Action == DragAction.Continue)
{
return NativeMethods.S_OK;
}
else if (args.Action == DragAction.Drop)
{
return NativeMethods.DRAGDROP_S_DROP;
}
else if (args.Action == DragAction.Cancel)
{
return NativeMethods.DRAGDROP_S_CANCEL;
}
return NativeMethods.S_OK;
}
///
/// Give feedback from the source whether use the default cursor or not.
///
int UnsafeNativeMethods.IOleDropSource.OleGiveFeedback(int effect)
{
GiveFeedbackEventArgs args;
// Create GiveFeedback event arguments.
args = new GiveFeedbackEventArgs((DragDropEffects)effect, /*UseDefaultCursors*/ false);
// Raise the give feedback event for both Tunnel(Preview) and Bubble.
RaiseGiveFeedbackEvent(args);
// Check the give feedback result whether use default cursors or not.
if (args.UseDefaultCursors)
{
return NativeMethods.DRAGDROP_S_USEDEFAULTCURSORS;
}
return NativeMethods.S_OK;
}
///
/// Raise QueryContinueDrag event for Tunel and Bubble.
///
private void RaiseQueryContinueDragEvent(QueryContinueDragEventArgs args)
{
// Set PreviewQueryContinueDrag(Tunnel) first.
args.RoutedEvent=DragDrop.PreviewQueryContinueDragEvent;
// Raise the preview QueryContinueDrag event(Tunnel).
if (_dragSource is UIElement)
{
((UIElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is ContentElement)
{
((ContentElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is UIElement3D)
{
((UIElement3D)_dragSource).RaiseEvent(args);
}
else
{
throw new ArgumentException(SR.Get(SRID.ScopeMustBeUIElementOrContent), "scope");
}
// Set QueryContinueDrag(Bubble).
args.RoutedEvent = DragDrop.QueryContinueDragEvent;
// Raise QueryContinueDrag event(Bubble).
if (!args.Handled)
{
if (_dragSource is UIElement)
{
((UIElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is ContentElement)
{
((ContentElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is UIElement3D)
{
((UIElement3D)_dragSource).RaiseEvent(args);
}
else
{
throw new ArgumentException(SR.Get(SRID.ScopeMustBeUIElementOrContent), "scope");
}
}
// Call the default event handling method internally if no one handle the drag source events.
if (!args.Handled)
{
OnDefaultQueryContinueDrag(args);
}
}
///
/// Raise GiveFeedback event for Tunnel and Bubble.
///
private void RaiseGiveFeedbackEvent(GiveFeedbackEventArgs args)
{
// Set PreviewGiveFeedback(Tunnel) first.
args.RoutedEvent=DragDrop.PreviewGiveFeedbackEvent;
// Raise the preview GiveFeedback(Tunnel).
if (_dragSource is UIElement)
{
((UIElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is ContentElement)
{
((ContentElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is UIElement3D)
{
((UIElement3D)_dragSource).RaiseEvent(args);
}
else
{
throw new ArgumentException(SR.Get(SRID.ScopeMustBeUIElementOrContent), "scope");
}
// Set GiveFeedback event ID(Bubble).
args.RoutedEvent = DragDrop.GiveFeedbackEvent;
if (!args.Handled)
{
// Raise GiveFeedback event(Bubble).
if (_dragSource is UIElement)
{
((UIElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is ContentElement)
{
((ContentElement)_dragSource).RaiseEvent(args);
}
else if (_dragSource is UIElement3D)
{
((UIElement3D)_dragSource).RaiseEvent(args);
}
else
{
throw new ArgumentException(SR.Get(SRID.ScopeMustBeUIElementOrContent), "scope");
}
}
// Call the default event handling method internally if no one handle the drag source events.
if (!args.Handled)
{
OnDefaultGiveFeedback(args);
}
}
///
/// Default query continue drag during drag-and-drop operation.
///
private void OnDefaultQueryContinueDrag(QueryContinueDragEventArgs e)
{
bool mouseUp;
mouseUp = false;
e.Action = DragAction.Continue;
mouseUp = (((int)e.KeyStates & (int)DragDropKeyStates.LeftMouseButton) == 0);
if (e.EscapePressed)
{
e.Action = DragAction.Cancel;
}
else if (mouseUp)
{
e.Action = DragAction.Drop;
}
}
///
/// Default give feedback during drag-and-drop operation.
///
private void OnDefaultGiveFeedback(GiveFeedbackEventArgs e)
{
// Show the default DragDrop cursor.
e.UseDefaultCursors = true;
}
#endregion IOleDropSource
//-----------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
#region Private Fields
private DependencyObject _dragSource;
#endregion Private Fields
}
#endregion OleDragSource
#region OleDropTarget
///
/// OleDropTarget that handle ole DragEnter DragOver DragLeave and DragDrop.
///
internal class OleDropTarget : DispatcherObject, UnsafeNativeMethods.IOleDropTarget
{
//------------------------------------------------------
//
// Constructor
//
//-----------------------------------------------------
#region Constructor
///
/// OleDropTarget Constructor.
///
public OleDropTarget(IntPtr handle)
{
if (handle == IntPtr.Zero)
{
throw new ArgumentNullException("handle");
}
_windowHandle = handle;
}
#endregion Constructor
//------------------------------------------------------
//
// IOleDropTarget Interface
//
//-----------------------------------------------------
#region IOleDropTarget
///
/// OleDragEnter - check the data object and notify DragEnter to the target element.
///
int UnsafeNativeMethods.IOleDropTarget.OleDragEnter(object data, int dragDropKeyStates, long point, ref int effects)
{
DependencyObject target;
Point targetPoint;
// Get the data object and immediately return if there isn't the data object or no available data.
_dataObject = GetDataObject(data);
if (_dataObject == null || !IsDataAvailable(_dataObject))
{
// Set the none effect.
effects = (int)DragDropEffects.None;
return NativeMethods.S_FALSE;
}
// Get the current target from the mouse drag point that is based on screen.
target = GetCurrentTarget(point, out targetPoint);
// Set the last target element with the current target.
_lastTarget = target;
if (target != null)
{
// Create DragEvent agrument and then raise DragEnter event for Tunnel or Buuble event.
RaiseDragEvent(
DragDrop.DragEnterEvent,
dragDropKeyStates,
ref effects,
target,
targetPoint);
}
else
{
// Set the none effect.
effects = (int)DragDropEffects.None;
}
return NativeMethods.S_OK;
}
///
/// OleDragOver - get the drop effect from the target element.
///
int UnsafeNativeMethods.IOleDropTarget.OleDragOver(int dragDropKeyStates, long point, ref int effects)
{
DependencyObject target;
Point targetPoint;
Invariant.Assert(_dataObject != null);
// Get the current target from the mouse drag point that is based on screen.
target = GetCurrentTarget(point, out targetPoint);
// Raise DragOver event to the target to get DragDrop effect status from the target.
if (target != null)
{
// Avalon apps can have only one window handle, so we need to generate DragLeave and
// DragEnter event to target when target is changed by the mouse dragging.
// If the current target is the same as the last target, just raise DragOver event to the target.
if (target != _lastTarget)
{
try
{
if (_lastTarget != null)
{
// Raise DragLeave event to the last target.
RaiseDragEvent(
DragDrop.DragLeaveEvent,
dragDropKeyStates,
ref effects,
_lastTarget,
targetPoint);
}
// Raise DragEnter event to the new target.
RaiseDragEvent(
DragDrop.DragEnterEvent,
dragDropKeyStates,
ref effects,
target,
targetPoint);
}
finally
{
// Reset the last target element to check it with the next current element.
_lastTarget = target;
}
}
else
{
// Raise DragOver event to the target.
RaiseDragEvent(
DragDrop.DragOverEvent,
dragDropKeyStates,
ref effects,
target,
targetPoint);
}
}
else
{
try
{
if (_lastTarget != null)
{
// Raise DragLeave event to the last target.
RaiseDragEvent(
DragDrop.DragLeaveEvent,
dragDropKeyStates,
ref effects,
_lastTarget,
targetPoint);
}
}
finally
{
// Update the last target element as the current target element.
_lastTarget = target;
effects = (int)DragDropEffects.None;
}
}
return NativeMethods.S_OK;
}
///
/// OleDragLeave.
///
int UnsafeNativeMethods.IOleDropTarget.OleDragLeave()
{
if (_lastTarget != null)
{
int effects;
// Set DragDrop effects as DragDropEffects.None
effects = 0;
try
{
// Raise DragLeave event for the last target element.
RaiseDragEvent(
DragDrop.DragLeaveEvent,
/* DragDropKeyStates.None */ 0,
ref effects,
_lastTarget,
new Point(0, 0));
}
finally
{
// Reset the last target and data object.
_lastTarget = null;
_dataObject = null;
}
}
return NativeMethods.S_OK;
}
///
/// OleDrop - drop the object to the target element.
///
int UnsafeNativeMethods.IOleDropTarget.OleDrop(object data, int dragDropKeyStates, long point, ref int effects)
{
IDataObject dataObject;
DependencyObject target;
Point targetPoint;
// Get the data object and then immediately return fail if there isn't the proper data.
dataObject = GetDataObject(data);
if (dataObject == null || !IsDataAvailable(dataObject))
{
effects = (int)DragDropEffects.None;
return NativeMethods.S_FALSE;
}
// Reset last element and target point.
_lastTarget = null;
// Get the current target from the screen mouse point.
target = GetCurrentTarget(point, out targetPoint);
// Raise Drop event to the target element.
if (target != null)
{
// Raise Drop event to the drop target.
RaiseDragEvent(
DragDrop.DropEvent,
dragDropKeyStates,
ref effects,
target,
targetPoint);
}
else
{
effects = (int)DragDropEffects.None;
}
return NativeMethods.S_OK;
}
#endregion IOleDropTarget
#region Private Methods
///
/// Raise Drag(Enter/Over/Leave/Drop) events to the taret.
///
private void RaiseDragEvent(RoutedEvent dragEvent, int dragDropKeyStates, ref int effects, DependencyObject target, Point targetPoint)
{
DragEventArgs dragEventArgs;
Invariant.Assert(_dataObject != null);
Invariant.Assert(target != null);
// Create DragEvent argement to raise DragEnter events to the target.
dragEventArgs = new DragEventArgs(
_dataObject,
(DragDropKeyStates)dragDropKeyStates,
(DragDropEffects)effects,
target,
targetPoint);
// Set the preview(Tunnel) drop target events(Tunnel) first.
if (dragEvent == DragDrop.DragEnterEvent)
{
dragEventArgs.RoutedEvent = DragDrop.PreviewDragEnterEvent;
}
else if (dragEvent == DragDrop.DragOverEvent)
{
dragEventArgs.RoutedEvent = DragDrop.PreviewDragOverEvent;
}
else if (dragEvent == DragDrop.DragLeaveEvent)
{
dragEventArgs.RoutedEvent = DragDrop.PreviewDragLeaveEvent;
}
else if (dragEvent == DragDrop.DropEvent)
{
dragEventArgs.RoutedEvent = DragDrop.PreviewDropEvent;
}
// Raise the preview drop target events(Tunnel).
if (target is UIElement)
{
((UIElement)target).RaiseEvent(dragEventArgs);
}
else if (target is ContentElement)
{
((ContentElement)target).RaiseEvent(dragEventArgs);
}
else if (target is UIElement3D)
{
((UIElement3D)target).RaiseEvent(dragEventArgs);
}
else
{
throw new ArgumentException(SR.Get(SRID.ScopeMustBeUIElementOrContent), "scope");
}
// Raise the bubble DragEvent event if the preview DragEvent isn't handled.
if (!dragEventArgs.Handled)
{
// Set the drop target events(Bubble).
dragEventArgs.RoutedEvent = dragEvent;
// Raise the drop target events(Bubble).
if (target is UIElement)
{
((UIElement)target).RaiseEvent(dragEventArgs);
}
else if (target is ContentElement)
{
((ContentElement)target).RaiseEvent(dragEventArgs);
}
else if (target is UIElement3D)
{
((UIElement3D)target).RaiseEvent(dragEventArgs);
}
else
{
throw new ArgumentException(SR.Get(SRID.ScopeMustBeUIElementOrContent), "scope");
}
}
// Call the default drop target event handling method internally if no one handle the drop target events.
if (!dragEventArgs.Handled)
{
if (dragEvent == DragDrop.DragEnterEvent)
{
OnDefaultDragEnter(dragEventArgs);
}
else if (dragEvent == DragDrop.DragOverEvent)
{
OnDefaultDragOver(dragEventArgs);
}
}
// Update DragDrop effects after raise DragEvent.
effects = (int)dragEventArgs.Effects;
}
///
/// Default drag enter during drag-and-drop operation.
///
private void OnDefaultDragEnter(DragEventArgs e)
{
bool ctrlKeyDown;
// If there's no supported data available, don't allow the drag-and-drop.
if (e.Data == null)
{
e.Effects = DragDropEffects.None;
return;
}
// Ok, there's data to move or copy here.
if ((e.AllowedEffects & DragDropEffects.Move) != 0)
{
e.Effects = DragDropEffects.Move;
}
ctrlKeyDown = ((int)(e.KeyStates & DragDropKeyStates.ControlKey) != 0);
if (ctrlKeyDown)
{
e.Effects = DragDropEffects.Copy;
}
}
///
/// Default drag over during drag-and-drop operation.
///
private void OnDefaultDragOver(DragEventArgs e)
{
bool ctrlKeyDown;
// If there's no supported data available, don't allow the drag-and-drop.
if (e.Data == null)
{
e.Effects = DragDropEffects.None;
return;
}
// Ok, there's data to move or copy here.
if ((e.AllowedEffects & DragDropEffects.Move) != 0)
{
e.Effects = DragDropEffects.Move;
}
ctrlKeyDown = ((int)(e.KeyStates & DragDropKeyStates.ControlKey) != 0);
if (ctrlKeyDown)
{
e.Effects = DragDropEffects.Copy;
}
}
///
/// Get the client point from the screen point.
///
private NativeMethods.POINT GetClientPointFromScreenPoint(long dragPoint)
{
NativeMethods.POINT screenPoint;
NativeMethods.POINT clientPoint;
// Convert the screen point to the client window point
screenPoint = new NativeMethods.POINT((int)(dragPoint & 0xffffffff), (int)((dragPoint >> 32) & 0xffffffff));
clientPoint = screenPoint;
SafeNativeMethods.ScreenToClient(new HandleRef(this, _windowHandle), clientPoint);
return clientPoint;
}
///
/// Get the current target object and target point from the mouse dragging point
/// that is the screen point.
///
private DependencyObject GetCurrentTarget(long dragPoint, out Point targetPoint)
{
HwndSource source;
DependencyObject target;
NativeMethods.POINT clientPoint;
// Initialize the target as null.
target = null;
// Get the client point from the screen point.
clientPoint = GetClientPointFromScreenPoint(dragPoint);
// Set the target point as the client point.
targetPoint = new Point(clientPoint.x, clientPoint.y);
// Get the source from the source to hit-test and translate point.
source = HwndSource.FromHwnd(_windowHandle);
if (source != null)
{
UIElement targetUIElement;
// Hit-Testing to get the target object from the current mouse dragging point.
// LocalHitTest() will get the hit-tested object from the mouse dragging point after
// conversion the pixel to the measure unit.
target = MouseDevice.LocalHitTest(targetPoint, source) as DependencyObject;
targetUIElement = target as UIElement;
if (targetUIElement != null)
{
if (targetUIElement.AllowDrop)
{
// Assign the target as the UIElement.
target = targetUIElement;
}
else
{
target = null;
}
}
else
{
ContentElement targetContentElement;
targetContentElement = target as ContentElement;
if (targetContentElement != null)
{
if (targetContentElement.AllowDrop)
{
// Assign the target as the ContentElement.
target = targetContentElement;
}
else
{
target = null;
}
}
else
{
UIElement3D targetUIElement3D;
targetUIElement3D = target as UIElement3D;
if (targetUIElement3D != null)
{
if (targetUIElement3D.AllowDrop)
{
target = targetUIElement3D;
}
else
{
target = null;
}
}
}
}
if (target != null)
{
// Translate the client point to the root point and then translate it to target point.
targetPoint = PointUtil.ClientToRoot(targetPoint, source);
targetPoint = InputElement.TranslatePoint(targetPoint, source.RootVisual, target);
}
}
return target;
}
///
/// Get the data object.
///
private IDataObject GetDataObject(object data)
{
IDataObject dataObject;
dataObject = null;
// We see if data is available on the data object.
if (data != null)
{
if (data is DataObject)
{
dataObject = (DataObject)data;
}
else
{
dataObject = new DataObject((IComDataObject)data);
}
}
return dataObject;
}
///
/// Check the available data.
///
private bool IsDataAvailable(IDataObject dataObject)
{
bool dataAvailable;
dataAvailable = false;
if (dataObject != null)
{
string[] formats;
formats = dataObject.GetFormats();
for (int i = 0; i < formats.Length; i++)
{
if (dataObject.GetDataPresent(formats[i]))
{
dataAvailable = true;
break;
}
}
}
return dataAvailable;
}
#endregion Private Methods
//-----------------------------------------------------
//
// Private Fields
//
//-----------------------------------------------------
#region Private Fields
private IntPtr _windowHandle;
private IDataObject _dataObject;
private DependencyObject _lastTarget;
#endregion Private Fields
}
#endregion OleDropTarget
}
// 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
- TypeValidationEventArgs.cs
- UserControlBuildProvider.cs
- StyleSheet.cs
- DocumentEventArgs.cs
- DataGridViewColumnDesigner.cs
- PowerEase.cs
- WebPartManagerInternals.cs
- TypeUsageBuilder.cs
- TextDecorationLocationValidation.cs
- Graphics.cs
- XmlUtil.cs
- RegexEditorDialog.cs
- SortDescriptionCollection.cs
- TreeNodeStyleCollection.cs
- WebSysDisplayNameAttribute.cs
- TypeUtil.cs
- SecurityTokenValidationException.cs
- CompleteWizardStep.cs
- ActivityXamlServices.cs
- LingerOption.cs
- DynamicILGenerator.cs
- SliderAutomationPeer.cs
- EntityDataSourceViewSchema.cs
- WebSysDescriptionAttribute.cs
- XPathSelectionIterator.cs
- EventLogEntry.cs
- ImageInfo.cs
- HttpPostServerProtocol.cs
- ToolStripButton.cs
- StringFreezingAttribute.cs
- ScrollProviderWrapper.cs
- ExpressionSelection.cs
- DataColumnMappingCollection.cs
- SqlProfileProvider.cs
- Hyperlink.cs
- StrokeNode.cs
- ScaleTransform3D.cs
- ReceiveReply.cs
- TypeInfo.cs
- SqlParameter.cs
- SendKeys.cs
- CardSpaceException.cs
- ObjectAnimationUsingKeyFrames.cs
- RemotingConfigParser.cs
- ExcCanonicalXml.cs
- PageBuildProvider.cs
- Splitter.cs
- DataSourceXmlAttributeAttribute.cs
- TextBoxView.cs
- ExpressionDumper.cs
- CompilerCollection.cs
- ObjectCloneHelper.cs
- RelationshipSet.cs
- DesignTimeTemplateParser.cs
- DrawingVisual.cs
- InvokePattern.cs
- FontDialog.cs
- ObjectDataSourceWizardForm.cs
- CommonObjectSecurity.cs
- FrameworkReadOnlyPropertyMetadata.cs
- WizardPanelChangingEventArgs.cs
- CardSpaceException.cs
- ParserStack.cs
- GenerateHelper.cs
- SplineKeyFrames.cs
- ContextMenu.cs
- AuditLogLocation.cs
- TransactionCache.cs
- StyleBamlTreeBuilder.cs
- SmtpSection.cs
- InvokeProviderWrapper.cs
- HostedHttpTransportManager.cs
- PersianCalendar.cs
- WebPartDisplayModeCollection.cs
- ToolStripLabel.cs
- ArgIterator.cs
- ReliableChannelFactory.cs
- EntityViewGenerationAttribute.cs
- Condition.cs
- IDQuery.cs
- TraceContextEventArgs.cs
- RadioButtonList.cs
- EventLogEntryCollection.cs
- TableLayoutCellPaintEventArgs.cs
- StateManagedCollection.cs
- MouseGestureValueSerializer.cs
- TextRunCacheImp.cs
- SHA256Managed.cs
- Helper.cs
- NullableLongAverageAggregationOperator.cs
- WindowInteropHelper.cs
- Site.cs
- LinqDataSourceView.cs
- DataError.cs
- EnumUnknown.cs
- MutexSecurity.cs
- SoapEnumAttribute.cs
- PageContentCollection.cs
- XmlReflectionImporter.cs
- TrustManagerPromptUI.cs