Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / WinForms / System / WinForms / Design / Behavior / DropSourceBehavior.cs / 1 / DropSourceBehavior.cs
//#define DEBUGDROPSOURCE
namespace System.Windows.Forms.Design.Behavior {
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Design;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms.Design;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
///
///
/// The DropSourceBehavior is created by ControlDesigner when it detects that
/// a drag operation has started. This object is passed to the BehaviorService
/// and is used to route GiveFeedback and QueryContinueDrag drag/drop messages.
/// In response to GiveFeedback messages, this class will render the dragging
/// controls in real-time with the help of the DragAssistanceManager (Snaplines)
/// object or by simply snapping to grid dots.
///
internal sealed class DropSourceBehavior : Behavior, IComparer{
private struct DragComponent {
public object dragComponent; //the dragComponent
public int zorderIndex; //the dragComponent's z-order index
public Point originalControlLocation; //the original control of the control in AdornerWindow coordinates
public Point draggedLocation; //the location of the component after each drag - in AdornerWindow coordinates
public Image dragImage; //bitblt'd image of control
public Point positionOffset; //control position offset from primary selection
};
private DragComponent[] dragComponents;
private ArrayList dragObjects; // used to initialize the DragAssistanceManager
private BehaviorDataObject data;//drag data that represents the controls we're dragging & the effect/action
private DragDropEffects allowedEffects;//initial allowed effects for the drag operation
private DragDropEffects lastEffect;//the last effect we saw (used for determining a valid drop)
private bool targetAllowsSnapLines;//indicates if the drop target allows snaplines (flowpanels don't for ex)
private IComponent lastDropTarget;//indicates the drop target on the last 'give feedback' event
private Point lastSnapOffset;//the last snapoffset we used.
// These 2 could be different (e.g. if dropping between forms)
private BehaviorService behaviorServiceSource;//ptr back to the BehaviorService in the drop source
private BehaviorService behaviorServiceTarget;//ptr back to the BehaviorService in the drop target
//this object will integrate SnapLines into the drag
private DragAssistanceManager dragAssistanceManager;
private Graphics graphicsTarget;//graphics object of the adornerwindows (via BehaviorService) in drop target
private IServiceProvider serviceProviderSource;
private IServiceProvider serviceProviderTarget;
private Point initialMouseLoc;//original mouse location in screen coordinates
private Image dragImage;//A single image of the controls we are actually dragging around
private Rectangle dragImageRect;//Rectangle of the dragImage -- in SOURCE AdornerWindow coordinates
private Rectangle clearDragImageRect; //Rectangle used to remember the last dragimage rect we cleared
private Point originalDragImageLocation; //original location of the drag image
private Region dragImageRegion;
private Point lastFeedbackLocation; // the last position we got feedback at
private Control suspendedParent;//pointer to the parent that we suspended @ the beginning of the drag
private Size parentGridSize; //used to snap around to grid dots if layoutmode == SnapToGrid
private Point parentLocation;//location of parent on AdornerWindow - used for grid snap calculations
private bool shareParent = true;//do dragged components share the parent
private bool cleanedUpDrag = false;
private StatusCommandUI statusCommandUITarget;// UI for setting the StatusBar Information in the drop target
private IDesignerHost srcHost;
private IDesignerHost destHost;
private bool currentShowState = true; // Initially the controls are showing
private int primaryComponentIndex = -1; // Index of the primary component (control) in dragComponents
///
///
/// Constuctor that caches all needed vars for perf reasons.
///
internal DropSourceBehavior(ICollection dragComponents, Control source, Point initialMouseLocation) {
this.serviceProviderSource = source.Site as IServiceProvider;
if (this.serviceProviderSource == null) {
Debug.Fail("DragBehavior could not be created because the source ServiceProvider was not found");
return;
}
behaviorServiceSource = (BehaviorService)serviceProviderSource.GetService(typeof(BehaviorService));
if (behaviorServiceSource == null) {
Debug.Fail("DragBehavior could not be created because the BehaviorService was not found");
return;
}
if (dragComponents == null || dragComponents.Count <= 0) {
Debug.Fail("There are no component to drag!");
return;
}
srcHost = (IDesignerHost)serviceProviderSource.GetService(typeof(IDesignerHost));
if (srcHost == null) {
Debug.Fail("DragBehavior could not be created because the srcHost could not be found");
return;
}
this.data = new BehaviorDataObject(dragComponents, source, this);
this.allowedEffects = DragDropEffects.Copy | DragDropEffects.None | DragDropEffects.Move;
this.dragComponents = new DragComponent[dragComponents.Count];
this.parentGridSize = Size.Empty;
lastEffect = DragDropEffects.None;
lastFeedbackLocation = new Point(-1, -1);
lastSnapOffset = Point.Empty;
dragImageRect = Rectangle.Empty;
clearDragImageRect = Rectangle.Empty;
InitiateDrag(initialMouseLocation, dragComponents);
}
///
///
/// This is the initial allowed Effect to start the drag operation with.
///
internal DragDropEffects AllowedEffects {
get {
return allowedEffects;
}
}
///
///
/// This is the DataObject this DropSourceBehavior represents.
///
internal DataObject DataObject {
get {
return data;
}
}
///
/// Here, during our drag operation, we need to determine the offset
/// from the dragging control's position 'dragLoc' and the parent's grid.
/// We'll return an offset for the image to 'snap to'.
///
private Point AdjustToGrid(Point dragLoc) {
//location of the drag with respect to the parent
Point controlLocation = new Point(dragLoc.X - this.parentLocation.X, dragLoc.Y -this.parentLocation.Y);
Point offset = Point.Empty;
//determine which way we need to snap
int xDelta = controlLocation.X % parentGridSize.Width;
int yDelta = controlLocation.Y % parentGridSize.Height;
//if we're more than half way to the next grid - then snap that way,
//otherwise snap back
if (xDelta > parentGridSize.Width /2) {
offset.X = parentGridSize.Width - xDelta;
}
else {
offset.X = -xDelta;
}
if (yDelta > parentGridSize.Height /2) {
offset.Y = parentGridSize.Height - yDelta;
}
else {
offset.Y = -yDelta;
}
return offset;
}
#if PERFORM_AUTO_MARGINS
/* Leaving in in case we want to re-enable this feature. The code as it is does presents major performance problems. */
///
/// Called after a successful drag/drop operation, this method will examine the position
/// of all the controls related (same parent) to the just-dragged control and determine
/// if they were placed within the recommended UI guidelines. If so, we'll attempt to
/// automatically adjust the margin/padding of the violators.
///
private void AutoAdjustMargins(Control dragControl) {
if (dragControl.Parent == null) {
return;
}
PropertyDescriptor marginProperty = TypeDescriptor.GetProperties(dragControl)["Margin"];
//
if (marginProperty == null /*|| autoRelocateProperty == null*/) {
//can't do anything here
return;
}
IDesignerHost designerHost = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (designerHost == null) {
Debug.Fail("Failed to get IDesignerHost!");
return;
}
IComponentChangeService changeService = serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
Control.ControlCollection controls = dragControl.Parent.Controls;
//loop through the controls attempting to identify which controls
//are violating others...
for (int i = 0; i < controls.Count - 1; i++) {
/* See
*/
for (int j = i + 1; j < controls.Count; j++) {
/* See
*/
//check if control i and control j are violating one another...
if (DoesViolateMargin(controls[i], controls[j])) {
//determine the new margins
Padding c1Margin = Padding.Empty;
Padding c2Margin = Padding.Empty;
SetMargins(controls[i], controls[j], ref c1Margin, ref c2Margin);
//set the margins
using (DesignerTransaction dt = designerHost.CreateTransaction(SR.GetString(SR.AutoAdjustMargins, controls[i].Site.Name, controls[j].Site.Name))) {
if (changeService != null) {
changeService.OnComponentChanging(controls[i], marginProperty);
changeService.OnComponentChanging(controls[j], marginProperty);
}
marginProperty.SetValue(controls[i], c1Margin);
marginProperty.SetValue(controls[j], c2Margin);
if (changeService != null) {
changeService.OnComponentChanged(controls[i], marginProperty, null, null);
changeService.OnComponentChanged(controls[j], marginProperty, null, null);
}
dt.Commit();
}
}
}
}
}
///
/// This function determines where the two controls margins are overlapped and
// fills up two Padding structs with suggested non-overlapped values.
///
private void SetMargins(Control c1, Control c2, ref Padding c1Margin, ref Padding c2Margin) {
//Now, perform the actual margin adjustments
//
if (c1.Bottom < c2.Top) {
//adjust the margins @ top of c1 and bottom of c2
int marginDelta = c2.Top - c1.Bottom;
c1Margin = new Padding(c1.Margin.Left, c1.Margin.Top, c1.Margin.Right, marginDelta / 2);
c2Margin = new Padding(c2.Margin.Left, marginDelta - c1Margin.Bottom, c2.Margin.Right, c2.Margin.Bottom);
}
else if (c1.Top > c2.Bottom) {
//adjust the margins @ bottom of c2and top of c1
int marginDelta = c1.Top - c2.Bottom;
c1Margin = new Padding(c1.Margin.Left, marginDelta / 2, c1.Margin.Right, c1.Margin.Bottom);
c2Margin = new Padding(c2.Margin.Left, c2.Margin.Top, c2.Margin.Right, marginDelta - c1Margin.Top);
}
else if (c1.Right < c2.Left) {
//adjust the margins @ left of c2and right of c1
int marginDelta = c2.Left - c1.Right;
c1Margin = new Padding(c1.Margin.Left, c1.Margin.Top, marginDelta / 2, c1.Margin.Bottom);
c2Margin = new Padding(marginDelta - c1Margin.Right, c2.Margin.Top, c2.Margin.Right, c2.Margin.Bottom);
}
else {
//adjust the margins @ right of c2 and left of c1
int marginDelta = c1.Left - c2.Right;
c1Margin = new Padding(marginDelta / 2, c1.Margin.Top, c1.Margin.Right , c1.Margin.Bottom);
c2Margin = new Padding(c2.Margin.Left, c2.Margin.Top, marginDelta - c1Margin.Left, c2.Margin.Bottom);
}
}
#endif
private Point MapPointFromSourceToTarget(Point pt) {
if (srcHost != destHost && destHost != null) {
pt = behaviorServiceSource.AdornerWindowPointToScreen(pt);
return behaviorServiceTarget.MapAdornerWindowPoint(IntPtr.Zero, pt);
}
else {
return pt;
}
}
private Point MapPointFromTargetToSource(Point pt) {
if (srcHost != destHost && destHost != null) {
pt = behaviorServiceTarget.AdornerWindowPointToScreen(pt);
return behaviorServiceSource.MapAdornerWindowPoint(IntPtr.Zero, pt);
}
else {
return pt;
}
}
///
/// This is used to clear the drag images.
///
private void ClearAllDragImages() {
if (dragImageRect != Rectangle.Empty) {
Rectangle rect = dragImageRect;
rect.Location = MapPointFromSourceToTarget(rect.Location);
if (graphicsTarget != null) {
graphicsTarget.SetClip(rect);
}
if (behaviorServiceTarget != null) {
behaviorServiceTarget.Invalidate(rect);
}
if (graphicsTarget != null) {
graphicsTarget.ResetClip();
}
}
}
#if PERFORM_AUTO_ANCHOR
/* Leaving in in case we want to re-enable this feature. The code as it is does presents major usability problems as
it changes anchors out from underneath you.
*/
///
/// This method is called after a drag operation has been completed.
/// Basically, the heuristic is: if we've just moved a control (only 1
/// at a time) and it is aligned with another control - then check
/// the anchoring properties. If the dragged control's anchoring is
/// default - and the aligned control's anchoring has been altered
/// then set the dragged control to mimic the aligned control's
/// anchor value.
///
private void PerformAutoAnchor(object dragControl) {
Control dragCtrl = dragControl as Control;
if (dragCtrl == null || dragCtrl.Parent == null) {
//dragged object is not a control or there is no valid panent
return;
}
PropertyDescriptor dragControlAnchorProp = TypeDescriptor.GetProperties(dragCtrl)["Anchor"];
if (dragControlAnchorProp == null) {
//couldn't get anhor prop
return;
}
DefaultValueAttribute defAttr = (DefaultValueAttribute)dragControlAnchorProp.Attributes[typeof(DefaultValueAttribute)];
if (defAttr != null && (AnchorStyles)defAttr.Value != (AnchorStyles)dragControlAnchorProp.GetValue(dragCtrl)) {
//dragged control's anchor prop was not default
return;
}
AnchorStyles dragControlAnchor = (AnchorStyles)dragControlAnchorProp.GetValue(dragCtrl);
Rectangle dragControlBounds = dragCtrl.Bounds;
//begin a search to find a control the dragControl is aligned with. We'll
//stop looking as soon as we find a control that aligns with us and have a
//different anchor value
foreach (Control c in dragCtrl.Parent.Controls) {
if (c.Equals(dragCtrl)) {
//skip if this is the dragged control
continue;
}
Rectangle bounds = c.Bounds;
//look for a friendly aligned child control
if (c.Left == dragControlBounds.Left || c.Right == dragControlBounds.Right ||
c.Top == dragControlBounds.Top || c.Bottom == dragControlBounds.Bottom) {
PropertyDescriptor anchorProp = TypeDescriptor.GetProperties(c)["Anchor"];
if (anchorProp != null) {
//cache off the anchorstyle for this aligned child control
AnchorStyles style = (AnchorStyles)anchorProp.GetValue(c);
if (style != dragControlAnchor) {
//here, the aligned child control's anchor prop is
//different from our dragcontrol! So we'll create a transaction
//and set the dragControl to the same style.
IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host == null) {
//couldn't find a designer host
return;
}
using (DesignerTransaction dt = host.CreateTransaction(SR.GetString(SR.PerformAutoAnchor, c.Site.Name, dragCtrl.Site.Name))) {
dragControlAnchorProp.SetValue(dragControl, style);
dt.Commit();
break;
}
}
}
}
}
}
#endif
#if PERFORM_AUTO_MARGINS
///
/// Returns true if c1 and c2 are within each others margins
/// but not overlapping.
///
private bool DoesViolateMargin(Control c1, Control c2) {
//if the margin rects intersect and the and the actual
//control bounds do not - then there's a violation
//
return !(Rectangle.Intersect(DesignerUtils.GetMarginBounds(c1), DesignerUtils.GetMarginBounds(c2)).IsEmpty) &&
(Rectangle.Intersect(c1.Bounds, c2.Bounds).IsEmpty);
}
#endif
// Yeah this is recursive, but we also need to resite all
// the children of this control, and their children, and their children...
private void SetDesignerHost(Control c) {
foreach (Control control in c.Controls) {
SetDesignerHost(control);
}
if (c.Site != null && !(c.Site is INestedSite) && destHost != null) {
destHost.Container.Add(c);
}
}
private void DropControl(int dragComponentIndex, Control dragTarget, Control dragSource, bool localDrag) {
Control currentControl = dragComponents[dragComponentIndex].dragComponent as Control;
if (lastEffect == DragDropEffects.Copy || (srcHost != destHost && destHost != null)) {
//between forms or copy
currentControl.Visible = true; // VSWhidbey #527814
bool visibleState = true;
PropertyDescriptor propLoc = TypeDescriptor.GetProperties(currentControl)["Visible"];
if (propLoc != null) {
//store off the visible state. When adding the control to the new designer host,
//a new control designer will be created for the control. Since currentControl.Visible
//is currently FALSE (See InitiateDrag), the shadowed Visible property will be FALSE as well.
//This is not what we want. VSWHIDBEY# 311994
visibleState = (bool)propLoc.GetValue(currentControl);
}
// Hook the control to its new designerHost
SetDesignerHost(currentControl);
currentControl.Parent = dragTarget;
if (propLoc != null) {
//Make sure and set the Visible property to the correct value
propLoc.SetValue(currentControl, visibleState);
}
}
else if (!localDrag && currentControl.Parent.Equals(dragSource)) {
//between containers
dragSource.Controls.Remove(currentControl);
currentControl.Visible = true; // VSWhidbey #527814
dragTarget.Controls.Add(currentControl);
}
}
private void SetLocationPropertyAndChildIndex(int dragComponentIndex, Control dragTarget, Point dropPoint, int newIndex, bool allowSetChildIndexOnDrop) {
Control currentControl = dragComponents[dragComponentIndex].dragComponent as Control;
PropertyDescriptor propLoc = TypeDescriptor.GetProperties(dragComponents[dragComponentIndex].dragComponent)["Location"];
if ((propLoc != null) && (currentControl != null)) {
//VSWhidbey# 361814 - ControlDesigner shadows the Location property. If the control is parented
//and the parent is a scrollable control, then it expects the Location to be in displayrectangle coordinates.
//At this point bounds are in clientrectangle coordinates, so we need to check if we need to adjust the coordinates.
Point pt = new Point(dropPoint.X, dropPoint.Y);
ScrollableControl p = currentControl.Parent as ScrollableControl;
if (p != null) {
Point ptScroll = p.AutoScrollPosition;
pt.Offset(-ptScroll.X, -ptScroll.Y); //always want to add the control below/right of the AutoScrollPosition
}
propLoc.SetValue(currentControl, pt);
// In some cases the target designer wants to maintain its own ZOrder, in that case we shouldn't
// try and set the childindex. FlowLayoutPanelDesigner is one such case. VSWhidbey #321132.
if (allowSetChildIndexOnDrop) {
dragTarget.Controls.SetChildIndex(currentControl, newIndex);
}
}
}
///
/// This is where we end the drag and commit the new control locations.
/// To do this correctly, we loop through every control and find its
/// propertyDescriptor for the Location. Then call SetValue(). After
/// this we re-enable the adorners. Finally, we pop ourselves
/// from the BehaviorStack.
///
private void EndDragDrop(bool allowSetChildIndexOnDrop) {
Control dragTarget = data.Target as Control;
if (dragTarget == null) {
return;//can't deal with a non-control drop target yet
}
// If for some reason we couldn't get these guys, let's try and get them here
if (serviceProviderTarget == null) {
Debug.Fail("EndDragDrop - how can serviceProviderTarget be null?");
serviceProviderTarget = dragTarget.Site as IServiceProvider;
if (serviceProviderTarget == null) {
Debug.Fail("EndDragDrop - how can serviceProviderTarget be null?");
return;
}
}
if (destHost == null) {
Debug.Fail("EndDragDrop - how can destHost be null?");
destHost = (IDesignerHost)serviceProviderTarget.GetService(typeof(IDesignerHost));
if (destHost == null) {
Debug.Fail("EndDragDrop - how can destHost be null?");
return;
}
}
if (behaviorServiceTarget == null) {
Debug.Fail("EndDragDrop - how can behaviorServiceTarget be null?");
behaviorServiceTarget = (BehaviorService)serviceProviderTarget.GetService(typeof(BehaviorService));
if (behaviorServiceTarget == null) {
Debug.Fail("EndDragDrop - how can behaviorServiceTarget be null?");
return;
}
}
#if PERFORM_AUTO_STUFF
bool successfulDrag = false;
#endif
// We use this list when doing a Drag-Copy, so that we can correctly restore state
// when we are done. See Copy code below.
ArrayList originalControls = null;
bool performCopy = (lastEffect == DragDropEffects.Copy);
Control dragSource = data.Source;
bool localDrag = dragSource.Equals(dragTarget);
PropertyDescriptor targetProp = TypeDescriptor.GetProperties(dragTarget)["Controls"];
PropertyDescriptor sourceProp = TypeDescriptor.GetProperties(dragSource)["Controls"];
IComponentChangeService componentChangeSvcSource = (IComponentChangeService)serviceProviderSource.GetService(typeof(IComponentChangeService));
IComponentChangeService componentChangeSvcTarget = (IComponentChangeService)serviceProviderTarget.GetService(typeof(IComponentChangeService));
if (dragAssistanceManager != null) {
dragAssistanceManager.OnMouseUp();
}
// If we are dropping between hosts, we want to set the selection in the new host
// to be the components that we are dropping. VSWhidbey# 395676
// ... or if we are copying
ISelectionService selSvc = null;
if (performCopy || (srcHost != destHost && destHost != null)) {
selSvc = (ISelectionService)serviceProviderTarget.GetService(typeof(ISelectionService));
}
try {
if (dragComponents != null && dragComponents.Length > 0) {
DesignerTransaction transSource = null;
DesignerTransaction transTarget = null;
string transDesc;
if (dragComponents.Length == 1) {
string name = TypeDescriptor.GetComponentName(dragComponents[0].dragComponent);
if (name == null || name.Length == 0) {
name = dragComponents[0].dragComponent.GetType().Name;
}
transDesc = SR.GetString(performCopy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name);
}
else {
transDesc = SR.GetString(performCopy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, dragComponents.Length);
}
// We don't want to create a transaction in the source, if we are doing a cross-form copy
if (srcHost != null && !(srcHost != destHost && destHost != null && performCopy)) {
transSource = srcHost.CreateTransaction(transDesc);
}
if (srcHost != destHost && destHost != null) {
transTarget = destHost.CreateTransaction(transDesc);
}
try {
ComponentTray tray = null;
int numberOfOriginalTrayControls = 0;
// If we are copying the controls, then, well, let's make a copy of'em...
// We then stuff the copy into the dragComponents array, since that keeps the
// rest of this code the same... No special casing needed.
if (performCopy) {
// As part of a Ctrl-Drag, components might have been added to the component tray,
// make sure that their location gets updated as well (think ToolStrips).
// Get the current number of controls in the Component Tray in the target
tray = serviceProviderTarget.GetService(typeof(ComponentTray)) as ComponentTray;
numberOfOriginalTrayControls = tray != null ? tray.Controls.Count : 0;
// Get the objects to copy
ArrayList temp = new ArrayList();
for (int i = 0; i < dragComponents.Length; i++) {
temp.Add(dragComponents[i].dragComponent);
}
// Create a copy of them
temp = DesignerUtils.CopyDragObjects(temp, serviceProviderTarget) as ArrayList;
if (temp == null) {
Debug.Fail("Couldn't create copies of the controls we are dragging.");
return;
}
originalControls = new ArrayList();
// And stick the copied controls back into the dragComponents array
for (int j = 0; j < temp.Count; j++) {
// ... but save off the old controls first
originalControls.Add(dragComponents[j].dragComponent);
dragComponents[j].dragComponent = temp[j];
}
}
if ((!localDrag || performCopy) && componentChangeSvcSource != null && componentChangeSvcTarget != null) {
componentChangeSvcTarget.OnComponentChanging(dragTarget, targetProp);
// If we are performing a copy, then the dragSource will not change
if (!performCopy) {
componentChangeSvcSource.OnComponentChanging(dragSource, sourceProp);
}
}
int baseDestIndex = ParentControlDesigner.DetermineTopChildIndex(dragTarget);
// We need to calculate initialDropPoint first to be able to calculate the new drop point
// for all controls
// Need to drop it first to make sure that the Parent gets set correctly.
DropControl(primaryComponentIndex, dragTarget, dragSource, localDrag);
Point initialDropPoint = behaviorServiceSource.AdornerWindowPointToScreen(dragComponents[primaryComponentIndex].draggedLocation);
// Tricky... initialDropPoint is the dropPoint in the source adornerwindow, which could be different than
// the target adornerwindow. But since we first convert it to screen coordinates, and then to client coordinates using
// the new parent, we end up dropping in the right spot. Cool, huh!
initialDropPoint = ((Control)dragComponents[primaryComponentIndex].dragComponent).Parent.PointToClient(initialDropPoint);
// VSWhidbey 233811: correct (only) the drop point for when Parent is mirrored, then use the offsets
// for the other controls, which were already corrected for mirroring in InitDrag
if (((Control)(dragComponents[primaryComponentIndex].dragComponent)).Parent.IsMirrored) {
initialDropPoint.Offset(-((Control)(dragComponents[primaryComponentIndex].dragComponent)).Width, 0);
}
// check permission to do that
Control primaryComponent = dragComponents[primaryComponentIndex].dragComponent as Control;
PropertyDescriptor propLoc = TypeDescriptor.GetProperties(primaryComponent)["Location"];
if(primaryComponent != null && propLoc!=null) {
try {
componentChangeSvcTarget.OnComponentChanging(primaryComponent, propLoc);
}
catch (CheckoutException coEx) {
if (coEx == CheckoutException.Canceled) {
return;
}
throw;
}
}
// everything is fine, carry on...
SetLocationPropertyAndChildIndex(primaryComponentIndex, dragTarget, initialDropPoint,
shareParent ? baseDestIndex + dragComponents[primaryComponentIndex].zorderIndex : baseDestIndex, allowSetChildIndexOnDrop);
if (selSvc != null) {
selSvc.SetSelectedComponents(new object[] {dragComponents[primaryComponentIndex].dragComponent}, SelectionTypes.Primary | SelectionTypes.Replace);
}
for (int i = 0; i < dragComponents.Length; i++) {
if (i == primaryComponentIndex) {
// did this one above
continue;
}
DropControl(i, dragTarget, dragSource, localDrag);
Point dropPoint = new Point(initialDropPoint.X + dragComponents[i].positionOffset.X,
initialDropPoint.Y + dragComponents[i].positionOffset.Y);
SetLocationPropertyAndChildIndex(i, dragTarget, dropPoint,
shareParent ? baseDestIndex + dragComponents[i].zorderIndex : baseDestIndex, allowSetChildIndexOnDrop);
if (selSvc != null) {
selSvc.SetSelectedComponents(new object[] {dragComponents[i].dragComponent}, SelectionTypes.Add);
}
}
if ((!localDrag || performCopy) && componentChangeSvcSource != null && componentChangeSvcTarget != null) {
componentChangeSvcTarget.OnComponentChanged(dragTarget, targetProp, dragTarget.Controls, dragTarget.Controls);
if (!performCopy) {
componentChangeSvcSource.OnComponentChanged(dragSource, sourceProp, dragSource.Controls, dragSource.Controls);
}
}
// If we did a Copy, then restore the old controls to make sure we set state correctly
if (originalControls != null) {
for (int i = 0; i < originalControls.Count; i++) {
dragComponents[i].dragComponent = originalControls[i];
}
originalControls = null;
}
// Rearrange the Component Tray - if we have to
if (performCopy) {
if (tray == null) {
// the target did not have a tray already, so let's go get it - if there is one
tray = serviceProviderTarget.GetService(typeof(ComponentTray)) as ComponentTray;
}
if (tray != null) {
int numberOfTrayControlsAdded = tray.Controls.Count - numberOfOriginalTrayControls;
if (numberOfTrayControlsAdded > 0) {
ArrayList listOfTrayControls = new ArrayList();
for (int i = 0; i < numberOfTrayControlsAdded; i++) {
listOfTrayControls.Add(tray.Controls[numberOfOriginalTrayControls + i]);
}
tray.UpdatePastePositions(listOfTrayControls);
}
}
}
// We need to CleanupDrag BEFORE we commit the transaction. The reason is that cleaning up can potentially
// cause a layout, and then any changes that happen due to the layout would be in a separate UndoUnit.
// We want the D&D to be undoable in one step.
CleanupDrag(false);
if (transSource != null) {
transSource.Commit();
transSource = null;
#if PERFORM_AUTO_STUFF
successfulDrag = true;
#endif
}
if (transTarget != null) {
transTarget.Commit();
transTarget = null;
}
}
finally {
if (transSource != null) {
transSource.Cancel();
}
if (transTarget != null) {
transTarget.Cancel();
}
}
}
}
finally {
// If we did a Copy, then restore the old controls to make sure we set state correctly
if (originalControls != null) {
for (int i = 0; i < originalControls.Count; i++) {
dragComponents[i].dragComponent = originalControls[i];
}
}
// Even though we call CleanupDrag(false) twice (see above), this method guards against doing the
// wrong thing.
CleanupDrag(false);
if (statusCommandUITarget != null)
{
// if selSvs is not null, then we either did a copy, or moved between forms, so use it to set the right info
statusCommandUITarget.SetStatusInformation(selSvc == null ? dragComponents[primaryComponentIndex].dragComponent as Component :
selSvc.PrimarySelection as Component);
}
}
#if PERFORM_AUTO_STUFF
if (successfulDrag) {
#if PERFORM_AUTO_MARGINS
//auto adjust margin values of controls if they were
//placed within the recommended UI distances...
AutoAdjustMargins(dragComponents[primaryComponentIndex].dragComponent as Control);
#endif
#if PERFORM_AUTO_ANCHOR
//if we aligned a single control with another that has
//non-default anchoring props, then we will apply those
//values to the control that we just dragged.
if (dragComponents.Length == 1) {
PerformAutoAnchor(dragComponents[0].dragComponent);
}
#endif
}
#endif
// clear the last feedback loc
//
lastFeedbackLocation = new Point(-1, -1);
}
///
///
/// Called by the BehaviorService when the GiveFeedback event is fired.
/// Here, we attempt to render all of our dragging control
/// snapshots. *After, of course, we let the
/// DragAssistanceManager adjust the position due to any SnapLine
/// activity.
///
internal void GiveFeedback(object sender, GiveFeedbackEventArgs e) {
//cache off this last effect so in QueryContinueDrag
//we can identify (if dropped) a valid drop operation
lastEffect = e.Effect;
//if our target is null, we can't drop anywhere, so don't even draw images
if (data.Target == null || e.Effect == DragDropEffects.None) {
if (clearDragImageRect != dragImageRect) {
//To avoid flashing, we only want to clear the drag images if the
//the dragimagerect is different than the last time we got here.
//I.e. if we keep dragging over an area where we are not allowed to
//drop, then we only have to clear the dragimages once.
ClearAllDragImages();
clearDragImageRect = dragImageRect;
}
if (dragAssistanceManager != null) {
dragAssistanceManager.EraseSnapLines();
}
return;
}
bool createNewDragAssistance = false;
Point mouseLoc = Control.MousePosition;
bool altKeyPressed = Control.ModifierKeys == Keys.Alt;
if (altKeyPressed && dragAssistanceManager != null) {
//erase any snaplines (if we had any)
dragAssistanceManager.EraseSnapLines();
}
// I can't get rid of the ole-drag/drop default cursor that show's the
// cross-parent drag indication
if (data.Target.Equals(data.Source) && lastEffect != DragDropEffects.Copy) {
e.UseDefaultCursors = false;
Cursor.Current = Cursors.Default;
}
else {
e.UseDefaultCursors = true;
}
// only do this drawing when the mouse pointer has
// actually moved so we don't continuously redraw and flicker like mad.
//
Control target = data.Target as Control;
if ((mouseLoc != lastFeedbackLocation) || (altKeyPressed && dragAssistanceManager != null)) {
if (!data.Target.Equals(lastDropTarget)) {
serviceProviderTarget = target.Site as IServiceProvider;
if (serviceProviderTarget == null) {
return;
}
IDesignerHost newDestHost = (IDesignerHost)serviceProviderTarget.GetService(typeof(IDesignerHost));
if (newDestHost == null) {
return;
}
targetAllowsSnapLines = true;
//check to see if the current designer participate with SnapLines
ControlDesigner designer = newDestHost.GetDesigner(target) as ControlDesigner;
if (designer != null && !designer.ParticipatesWithSnapLines) {
targetAllowsSnapLines = false;
}
statusCommandUITarget = new StatusCommandUI(serviceProviderTarget);
// Spin up new stuff if the host changes, or if this is the first time through (lastDropTarget will be null in this case)
if ((lastDropTarget == null) || (newDestHost != destHost)) {
if (destHost != null && destHost != srcHost) {
//re-enable all glyphs in the old host...
//need to do this before we get the new behaviorservice
foreach (Adorner a in behaviorServiceTarget.Adorners ) {
a.Enabled = true;
}
}
behaviorServiceTarget = (BehaviorService)serviceProviderTarget.GetService(typeof(BehaviorService));
if (behaviorServiceTarget == null) {
return;
}
GetParentSnapInfo(target, behaviorServiceTarget);
//Disable the adorners in the new host, but only if this is not the
//source host, since that will already have been done
if (newDestHost != srcHost) {
DisableAdorners(serviceProviderTarget, behaviorServiceTarget, true);
}
// clear the old drag images in the old graphicsTarget
ClearAllDragImages();
// Build a new dragImageRegion -- but only if we are changing hosts
if (lastDropTarget != null) {
for (int i = 0; i < dragObjects.Count; i++) {
Control dragControl = (Control) dragObjects[i];
Rectangle controlRect = behaviorServiceSource.ControlRectInAdornerWindow(dragControl);
// Can't call MapPointFromSourceToTarget since we always want to do this
controlRect.Location = behaviorServiceSource.AdornerWindowPointToScreen(controlRect.Location);
controlRect.Location = behaviorServiceTarget.MapAdornerWindowPoint(IntPtr.Zero, controlRect.Location);
if (i == 0) {
if (dragImageRegion != null) {
dragImageRegion.Dispose();
}
dragImageRegion = new Region(controlRect);
}
else {
dragImageRegion.Union(controlRect);
}
}
}
if (graphicsTarget != null) {
graphicsTarget.Dispose();
}
graphicsTarget = behaviorServiceTarget.AdornerWindowGraphics;
// Always force the dragassistance manager to be created in this case.
createNewDragAssistance = true;
destHost = newDestHost;
}
lastDropTarget = data.Target;
}
if (ShowHideDragControls(lastEffect == DragDropEffects.Copy) && !createNewDragAssistance) {
createNewDragAssistance = true;
}
// Create new dragassistancemanager if needed
if (createNewDragAssistance && behaviorServiceTarget.UseSnapLines) {
if (dragAssistanceManager != null) {
//erase any snaplines (if we had any)
dragAssistanceManager.EraseSnapLines();
}
dragAssistanceManager = new DragAssistanceManager(serviceProviderTarget, graphicsTarget, dragObjects, null, lastEffect == DragDropEffects.Copy);
}
//The new position of the primary control, i.e. where did we just drag it to
Point newPosition = new Point(mouseLoc.X - initialMouseLoc.X + dragComponents[primaryComponentIndex].originalControlLocation.X,
mouseLoc.Y -initialMouseLoc.Y + dragComponents[primaryComponentIndex].originalControlLocation.Y);
// Map it to the target's adorner window so that we can snap correctly
newPosition = MapPointFromSourceToTarget(newPosition);
//The new rectangle
Rectangle newRect = new Rectangle(newPosition.X, newPosition.Y,
dragComponents[primaryComponentIndex].dragImage.Width,
dragComponents[primaryComponentIndex].dragImage.Height);
//if we have a valid snapline engine - ask it to offset our drag
if (dragAssistanceManager != null) {
if (targetAllowsSnapLines && !altKeyPressed) {
// Remembering the last snapoffset allows us to correctly erase snaplines,
// if the user subsequently holds down the Alt-Key. Remember that we don't physically move the mouse,
// we move the control (or rather the image of the control). So if we didn't remember the last snapoffset
// and the user then hit the Alt-Key, we would actually redraw the control at the actual mouse location,
// which would make the control "jump" which is not what the user would expect. Why does the control "jump"?
// Because when a control is snapped, we have offset the control relative to where the mouse is, but we
// have not update the physical mouse position.
// When the user hits the Alt-Key they expect the control to be where it was (whether snapped or not).
lastSnapOffset = dragAssistanceManager.OnMouseMove(newRect);
}
else {
dragAssistanceManager.OnMouseMove(new Rectangle(-100,-100,0,0));/*just an invalid rect - so we won't snap*///);
}
}
//if we know our parent is forcing grid sizes
else if (!parentGridSize.IsEmpty) {
lastSnapOffset = AdjustToGrid(newPosition);
}
// Set the new location after the drag (only need to do this for the primary control) adjusted for a snap offset
newPosition.X += lastSnapOffset.X;
newPosition.Y += lastSnapOffset.Y;
// draggedLocation is the coordinates in the source AdornerWindow. Need to do this
// since our original location is in those coordinates
dragComponents[primaryComponentIndex].draggedLocation = MapPointFromTargetToSource(newPosition);
// Now draw the dragImage in the correct location
// FIRST, INVALIDATE THE REGION THAT IS OUTSIDE OF THE DRAGIMAGERECT
// First remember the old rect so that we can invalidate the right thing
Rectangle previousImageRect = dragImageRect;
// This is in Source adorner window coordinates
newPosition = new Point(mouseLoc.X - initialMouseLoc.X + originalDragImageLocation.X,
mouseLoc.Y - initialMouseLoc.Y + originalDragImageLocation.Y);
newPosition.X += lastSnapOffset.X;
newPosition.Y += lastSnapOffset.Y;
// Store this off in Source adornerwindow coordinates
dragImageRect.Location = newPosition;
previousImageRect.Location = MapPointFromSourceToTarget(previousImageRect.Location);
Rectangle newImageRect = dragImageRect;
newImageRect.Location = MapPointFromSourceToTarget(newImageRect.Location);
Rectangle unionRectangle = Rectangle.Union(newImageRect, previousImageRect);
Region invalidRegion = new Region(unionRectangle);
invalidRegion.Exclude(newImageRect);
// SECOND, INVALIDATE THE TRANSPARENT REGION OF THE DRAGIMAGERECT
using(Region invalidDragRegion = dragImageRegion.Clone()) {
invalidDragRegion.Translate(mouseLoc.X - initialMouseLoc.X + lastSnapOffset.X, mouseLoc.Y - initialMouseLoc.Y + lastSnapOffset.Y);
invalidDragRegion.Complement(newImageRect);
invalidDragRegion.Union(invalidRegion);
#if DEBUGDROPSOURCE
System.Threading.Thread.Sleep(750);
graphicsTarget.FillRegion(Brushes.Red, invalidDragRegion);
System.Threading.Thread.Sleep(750);
#endif
behaviorServiceTarget.Invalidate(invalidDragRegion);
}
invalidRegion.Dispose();
if (graphicsTarget != null) {
graphicsTarget.SetClip(newImageRect);
graphicsTarget.DrawImage(dragImage, newImageRect.X, newImageRect.Y);
graphicsTarget.ResetClip();
}
Control c = dragComponents[primaryComponentIndex].dragComponent as Control;
if (c != null) {
// update drag position on the status bar
Point dropPoint = behaviorServiceSource.AdornerWindowPointToScreen(dragComponents[primaryComponentIndex].draggedLocation);
dropPoint = target.PointToClient(dropPoint);
// VSWhidbey 190654: must adjust offsets for the flipped X axis when our container and control are mirrored
if(target.IsMirrored && c.IsMirrored) {
dropPoint.Offset(-c.Width, 0);
}
if (statusCommandUITarget != null)
{
statusCommandUITarget.SetStatusInformation(c as Component, dropPoint);
}
}
//allow any snaplines to be drawn above our drag images as
//long as the alt key is not pressed and the mouse is over the root comp
if (dragAssistanceManager != null && !altKeyPressed && targetAllowsSnapLines) {
dragAssistanceManager.RenderSnapLinesInternal();
}
// save off the current mouse position
//
lastFeedbackLocation = mouseLoc;
}
data.Target = null;
}
///
/// We want to sort the dragComponents in descending z-order. We want to
/// make sure that we draw the control lowest in the z-order first, and drawing
/// the control at the top of the z-order last.
///
/// Remember that z-order indices are in reverse order. I.e. the control
/// that is at the top of the z-order list has the lowest z-order index.
///
int IComparer.Compare(Object x, Object y) {
DragComponent dc1 = (DragComponent)x;
DragComponent dc2 = (DragComponent)y;
if (dc1.zorderIndex > dc2.zorderIndex) {
return -1;
}
else if (dc1.zorderIndex < dc2.zorderIndex) {
return 1;
}
else {
return 0;
}
}
private void GetParentSnapInfo(Control parentControl, BehaviorService bhvSvc) {
// Clear out whatever value we might have had stored off
parentGridSize = Size.Empty;
if (bhvSvc != null && !bhvSvc.UseSnapLines) {
PropertyDescriptor snapProp = TypeDescriptor.GetProperties(parentControl)["SnapToGrid"];
if (snapProp != null && (bool)snapProp.GetValue(parentControl)) {
PropertyDescriptor gridProp = TypeDescriptor.GetProperties(parentControl)["GridSize"];
if (gridProp != null) {
//cache of the gridsize and the location of the parent on the adornerwindow
Control primaryControl = dragComponents[primaryComponentIndex].dragComponent as Control;
if (primaryControl != null) {
this.parentGridSize = (Size)gridProp.GetValue(parentControl);
this.parentLocation = bhvSvc.MapAdornerWindowPoint(parentControl.Handle, Point.Empty);
if (parentControl.Parent != null && parentControl.Parent.IsMirrored) {
this.parentLocation.Offset(-parentControl.Width, 0);
}
}
}
}
}
}
private void DisableAdorners(IServiceProvider serviceProvider, BehaviorService behaviorService, bool hostChange) {
//find our bodyglyph adorner offered by the behavior service
//we don't want to disable the transparent body glyphs
//
Adorner bodyGlyphAdorner = null;
SelectionManager selMgr = (SelectionManager)serviceProvider.GetService(typeof(SelectionManager));
if (selMgr != null) {
bodyGlyphAdorner = selMgr.BodyGlyphAdorner;
}
//disable all adorners except for bodyglyph adorner
//
foreach (Adorner a in behaviorService.Adorners) {
if (bodyGlyphAdorner != null && a.Equals(bodyGlyphAdorner)) {
continue;
}
a.Enabled = false;
}
if (hostChange) {
selMgr.OnBeginDrag(new BehaviorDragDropEventArgs(dragObjects));
}
}
///
/// Called when the ContolDesigner starts a drag operation.
/// Here, all adorners are disabled, screen shots of all
/// related controls are taken, and the DragAssistanceManager
/// (for SnapLines) is created.
///
private void InitiateDrag(Point initialMouseLocation, ICollection dragComps) {
dragObjects = new ArrayList(dragComps);
DisableAdorners(serviceProviderSource, behaviorServiceSource, false);
Control primaryControl = dragObjects[0] as Control;
Control primaryParent = primaryControl != null ? primaryControl.Parent : null;
Color backColor = primaryParent != null ? primaryParent.BackColor : Color.Empty;
dragImageRect = Rectangle.Empty;
clearDragImageRect = Rectangle.Empty;
initialMouseLoc = initialMouseLocation;
//loop through every control we need to drag, calculate the offsets and get a snapshot
for (int i = 0; i < dragObjects.Count; i++) {
Control dragControl = (Control) dragObjects[i];
dragComponents[i].dragComponent = dragObjects[i];
dragComponents[i].positionOffset = new Point(dragControl.Location.X - primaryControl.Location.X,
dragControl.Location.Y - primaryControl.Location.Y);
Rectangle controlRect = behaviorServiceSource.ControlRectInAdornerWindow(dragControl);
if (dragImageRect.IsEmpty) {
dragImageRect = controlRect;
dragImageRegion = new Region(controlRect);
}
else {
dragImageRect = Rectangle.Union(dragImageRect, controlRect);
dragImageRegion.Union(controlRect);
}
//Initialize the dragged location to be the current position of the control
dragComponents[i].draggedLocation = controlRect.Location;
dragComponents[i].originalControlLocation = dragComponents[i].draggedLocation;
//take snapshot of each control
DesignerUtils.GenerateSnapShot(dragControl, ref dragComponents[i].dragImage, i == 0 ? 2 : 1, 1, backColor);
// The dragged components are not in any specific order.
// If they all share the same parent, we will sort them by their index
// in that parent's control's collection to preserve correct Z-order
// VSWhidbey 232946
if (primaryParent != null && shareParent) {
dragComponents[i].zorderIndex = primaryParent.Controls.GetChildIndex(dragControl, false /*throwException*/);
if (dragComponents[i].zorderIndex == -1) {
shareParent = false;
}
}
}
if (shareParent) {
Array.Sort(dragComponents, this);
}
// Now that we are sorted, set the primaryComponentIndex...
for (int i = 0; i < dragComponents.Length; i++) {
if (primaryControl.Equals(dragComponents[i].dragComponent as Control)) {
primaryComponentIndex = i;
break;
}
}
Debug.Assert(primaryComponentIndex != -1, "primaryComponentIndex was not set!");
//suspend layout of the parent
if (primaryParent!= null) {
suspendedParent = primaryParent;
suspendedParent.SuspendLayout();
// Get the parent's grid settings here
GetParentSnapInfo(suspendedParent, behaviorServiceSource);
}
//If the thing that's being dragged is of 0 size, make the image a little
//bigger so that the user can see where they're dragging it.
int imageWidth = dragImageRect.Width;
if (imageWidth == 0) {
imageWidth = 1;
}
int imageHeight = dragImageRect.Height;
if (imageHeight == 0) {
imageHeight = 1;
}
dragImage = new Bitmap(imageWidth, imageHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
using (Graphics g = Graphics.FromImage(dragImage)) {
g.Clear(Color.Chartreuse);
}
((Bitmap)dragImage).MakeTransparent(Color.Chartreuse);
// Gotta use 2 using's here... Too bad.
// Draw each control into the dragimage
using (Graphics g = Graphics.FromImage(dragImage)) {
using (SolidBrush brush = new SolidBrush(primaryControl.BackColor)) {
for (int i = 0; i < dragComponents.Length; i++) {
Rectangle controlRect = new Rectangle(dragComponents[i].draggedLocation.X - dragImageRect.X,
dragComponents[i].draggedLocation.Y - dragImageRect.Y,
dragComponents[i].dragImage.Width, dragComponents[i].dragImage.Height);
// The background
g.FillRectangle(brush, controlRect);
// The foreground
g.DrawImage(dragComponents[i].dragImage, controlRect,
new Rectangle(0, 0, dragComponents[i].dragImage.Width, dragComponents[i].dragImage.Height),
GraphicsUnit.Pixel);
}
}
}
originalDragImageLocation = new Point(dragImageRect.X, dragImageRect.Y);
//hide actual controls - this might cause a brief flicker, we are okay with that.
ShowHideDragControls(false);
cleanedUpDrag = false;
}
internal ArrayList GetSortedDragControls(ref int primaryControlIndex) {
//create our list of controls-to-drag
ArrayList dragControls = new ArrayList();
primaryControlIndex = -1;
if ((dragComponents != null) && (dragComponents.Length > 0)) {
primaryControlIndex = primaryComponentIndex;
for (int i = 0; i < dragComponents.Length; i++) {
dragControls.Add(dragComponents[i].dragComponent);
}
}
return dragControls;
}
///
///
/// Called by the BehaviorService in response to QueryContinueDrag notifications.
///
internal void QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
//Clean up if the action was cancelled, or we had no effect when dropped.
//Otherwise EndDragDrop() will do this after the locations have been properly changed.
if (behaviorServiceSource != null && behaviorServiceSource.CancelDrag) {
e.Action = DragAction.Cancel;
CleanupDrag(true);
return;
}
if (e.Action == DragAction.Continue) {
return;
}
//Clean up if the action was cancelled, or we had no effect when dropped.
//Otherwise EndDragDrop() will do this after the locations have been properly changed.
if (e.Action == DragAction.Cancel || lastEffect == DragDropEffects.None) {
CleanupDrag(true);
// QueryContinueDrag can be called before GiveFeedback in which case we will
// end up here because lastEffect == DragDropEffects.None. If we don't
// set e.Action, the drag will continue, and GiveFeedback will be called. But since
// we have cleaned up the drag, weird things happens (e.g. dragImageRegion has been
// disposed already, so we throw). So if we get here, let's make sure and cancel the drag.
e.Action = DragAction.Cancel;
}
}
///
///
/// Changes the Visible state of the controls we are dragging.
///
/// Returns whether we change state or not.
///
///
internal bool ShowHideDragControls(bool show) {
if (currentShowState == show) {
return false;
}
currentShowState = show;
if (dragComponents != null) {
for (int i = 0; i < dragComponents.Length; i++) {
Control c = dragComponents[i].dragComponent as Control;
if (c != null) {
c.Visible = show;
}
}
}
return true;
}
internal void CleanupDrag() {
CleanupDrag(true);
}
internal void CleanupDrag(bool clearImages) {
if (!cleanedUpDrag) {
if (clearImages) {
ClearAllDragImages();
}
ShowHideDragControls(true);
try {
if (suspendedParent != null) {
suspendedParent.ResumeLayout();
}
}
finally {
suspendedParent = null;
//re-enable all glyphs in all adorners
foreach (Adorner a in behaviorServiceSource.Adorners ) {
a.Enabled = true;
}
if (destHost != srcHost && destHost != null) {
foreach (Adorner a in behaviorServiceTarget.Adorners) {
a.Enabled = true;
}
behaviorServiceTarget.SyncSelection();
}
// Layout may have caused controls to resize, which would mean their BodyGlyphs
// are wrong. We need to sync these.
if (behaviorServiceSource != null) {
behaviorServiceSource.SyncSelection();
}
if (dragImageRegion != null) {
dragImageRegion.Dispose();
dragImageRegion = null;
}
if (dragImage != null) {
dragImage.Dispose();
dragImage = null;
}
if (dragComponents != null) {
for (int i = 0; i < dragComponents.Length; i++) {
if (dragComponents[i].dragImage != null) {
dragComponents[i].dragImage.Dispose();
dragComponents[i].dragImage = null;
}
}
}
if (graphicsTarget != null) {
graphicsTarget.Dispose();
graphicsTarget = null;
}
cleanedUpDrag = true;
}
}
}
///
///
/// This class extends from DataObject and carries additional
/// information such as: the list of Controls currently being
/// dragged and the drag 'Source'.
///
internal class BehaviorDataObject: System.Windows.Forms.DataObject {
private ICollection dragComponents;
private Control source;
private IComponent target;
private DropSourceBehavior sourceBehavior;
public BehaviorDataObject(ICollection dragComponents, Control source, DropSourceBehavior sourceBehavior) : base(){
this.dragComponents = dragComponents;
this.source = source;
this.sourceBehavior = sourceBehavior;
this.target = null;
}
public Control Source {
get {
return source;
}
}
public ICollection DragComponents {
get{
return dragComponents;
}
}
public IComponent Target {
get {
return target;
}
set {
target = value;
}
}
internal void EndDragDrop(bool allowSetChildIndexOnDrop) {
sourceBehavior.EndDragDrop(allowSetChildIndexOnDrop);
}
internal void CleanupDrag() {
sourceBehavior.CleanupDrag();
}
internal ArrayList GetSortedDragControls(ref int primaryControlIndex) {
return sourceBehavior.GetSortedDragControls(ref primaryControlIndex);
}
}
}
}
// 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
- DataKeyPropertyAttribute.cs
- RestHandler.cs
- ViewCellRelation.cs
- Stack.cs
- DBConnection.cs
- MultilineStringConverter.cs
- Script.cs
- GeometryCollection.cs
- RowVisual.cs
- DataServiceKeyAttribute.cs
- EmptyElement.cs
- ArrayElementGridEntry.cs
- HttpRequestTraceRecord.cs
- EdmItemError.cs
- CompilerResults.cs
- TransformerConfigurationWizardBase.cs
- CultureMapper.cs
- HwndSourceParameters.cs
- BitmapEffect.cs
- Matrix.cs
- Assert.cs
- MatrixCamera.cs
- WebHttpElement.cs
- DataBindingCollection.cs
- ProviderConnectionPointCollection.cs
- TextProperties.cs
- GetPageNumberCompletedEventArgs.cs
- EventsTab.cs
- DataSourceHelper.cs
- PkcsUtils.cs
- HtmlTableCell.cs
- TransformerConfigurationWizardBase.cs
- PipelineModuleStepContainer.cs
- XmlSignatureProperties.cs
- CodeNamespaceCollection.cs
- PersonalizationProviderCollection.cs
- EventTrigger.cs
- AjaxFrameworkAssemblyAttribute.cs
- safesecurityhelperavalon.cs
- FormParameter.cs
- EntityCommandExecutionException.cs
- ListenerTraceUtility.cs
- UrlEncodedParameterWriter.cs
- ClientFormsAuthenticationCredentials.cs
- XPathParser.cs
- FrameworkRichTextComposition.cs
- CodeIterationStatement.cs
- XmlUnspecifiedAttribute.cs
- SamlAttribute.cs
- URLString.cs
- ParameterModifier.cs
- SessionPageStatePersister.cs
- PolyBezierSegment.cs
- Int64Storage.cs
- NavigationPropertyEmitter.cs
- TraceContext.cs
- ExtensionFile.cs
- XPathSingletonIterator.cs
- FunctionImportMapping.cs
- WebPartTransformerAttribute.cs
- ContainerSelectorActiveEvent.cs
- MetadataItem_Static.cs
- CompiledAction.cs
- PopupRoot.cs
- ToolboxComponentsCreatingEventArgs.cs
- XsdBuilder.cs
- ManagementOperationWatcher.cs
- TableDetailsRow.cs
- DataBinder.cs
- ProvidePropertyAttribute.cs
- Utilities.cs
- DirectoryNotFoundException.cs
- SubMenuStyle.cs
- DatagridviewDisplayedBandsData.cs
- SystemBrushes.cs
- HwndStylusInputProvider.cs
- SafeSerializationManager.cs
- MimePart.cs
- EventProviderWriter.cs
- CurrentChangingEventArgs.cs
- LabelEditEvent.cs
- TagPrefixInfo.cs
- WorkflowApplicationEventArgs.cs
- StylusPointPropertyId.cs
- XmlSchemaInclude.cs
- SmtpSection.cs
- translator.cs
- TrackingConditionCollection.cs
- SHA384Managed.cs
- PassportPrincipal.cs
- DateTimeParse.cs
- FlowDocumentView.cs
- WorkflowMessageEventHandler.cs
- ProviderConnectionPointCollection.cs
- Lookup.cs
- PathFigureCollection.cs
- WindowsFont.cs
- FunctionImportElement.cs
- ComponentManagerBroker.cs
- DrawingGroup.cs