3. Conversion of manual OLE Drag and Drop

    VB6 OLE Drag and Drop is very different to VB6 Standard Drag and Drop. OLE Drag and Drop has more events and handlers to enhance the functionality, so its conversion to .NET will be very different as well.

    3.1. OLEDrag method

    VB6 manual OLE Drag and Drop starts with the object.OLEDrag method. However, this Drag and Drop variant requires to set the Drag data and the allowed drag methods inside the OLEStartDrag event handler. To convert the original OLE Drag and Drop behavior to .NET, the OLEDrag and OLEStartDrag members will be converted together.

    3.1.1. Source code

    theControl.OLEDrag

    3.1.2. Expected code

    The call to OLEDrag method will be replaced to the converted OLEStartDrag member. The settings for the drag and drop action will be defined inside that method.

    Visual Basic .NET

    'UPGRADE_WARNING: The following statement was inserted to allow conversion of drag start event
    theControl_OLEStartDrag()
    

    C#

    //UPGRADE_WARNING: The following statement was inserted to allow conversion of drag start event
    theControl_OLEStartDrag();
    

    3.2. OLEStartDrag

    This event was raised in the source control at the start of the drag and drop operation caused by a call to the OLEDrag method of the control. (See 3.1.)

    3.2.1. Source code

    Private Sub theControl_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
         Data.SetData theControl.SelText, vbCFText
         AllowedEffects = vbDropEffectCopy 
    End Sub
    

    3.2.2. Expected code

    Data and AllowedEffects parameters are no longer necessary in the converted method header, since the data and the allowed modes are passed in the call to the control’s DoDragDrop method.

    Convert the Data.SetData and AllowedEffects assignations into one call to DoDragDrop method.

    The call to DoDragDrop method returns the drag and drop effect accepted when the operation ends. It will be stored to support the conversion of other VB6 OLE drag and drop events.

    Visual Basic .NET

    Private Sub theControl_OLEStartDrag()
       Dim Effect As DragDropEffects
       Effect = theControl.DoDragDrop(theControl.SelectedText, DragDropEffects.Copy)
    End Sub
    

    C#

    private void theControl_OLEStartDrag( )
    { 
       DragDropEffects effect;
       effect = theControl.DoDragDrop(theControl.SelectedText, DragDropEffects.Copy);
    }
    

    3.3. OLEDragOver event

    The DragOver event is received by a target control when the mouse pointer passes over the control during a drag and drop operation.

    .NET controls require to have the AllowDrop property set to True in the designer code section to be capable of handling of DragDrop and DragOver events.

    It’s also very important to note that every control which receives DragDrop actions has to allow the drag and drop operation first. The types of allowed drag and drop operations are set with a DragDropEffect value in the drag over or drag enter event handlers. As a default for this spec, the DragDropEffect value will be set in the DragEnter event handler.

    If the original code didn’t had code to handle the drag over events, the conversion process has to insert a DragEnter event handler to allow the drag and drop.

    3.3.1. Source code

    Private Sub theControl_OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer)
        'User's code
        If Data.GetFormat(vbCFText) Then
            Effect = vbDropEffectCopy 
        Else
            Effect = vbDropEffectNone
    End If
    'End of user's code
    End Sub
    

    3.3.2. Expected code

    First of all, add the following line of code to the designer code for the control. This allows the control to receive drag and drop events.

    Visual Basic .NET

    theControl.AllowDrop = True

    C#

    theControl.AllowDrop = true;

    Remove all the original parameters but State. Insert a new DragEventArgs parameter as first parameter. Rename the event handler to control_DragOverEvent to avoid name conflicts with control’s .NET event handlers.

    Note the required conversion of .NET event’s screen coordinates to client control coordinates, using the ConvertCoordinatesToClient support method.

    Visual Basic .NET

    Private Sub theControl_OLEDragOverEvent(ByRef e As DragEventArgs, ByRef State As Short)
       Dim x As Integer = e.X
       Dim y As Integer = e.Y
       Dim Button As Integer = e.KeyState \ &H100000
       Dim Shift As Integer = Control.ModifierKeys \ &H10000
       Support.ConvertCoordinatesToClient(theControl, x, y)
       'User's code
       If e.Data.GetDataPresent(DataFormats.Text) Then
          e.Effect = DragDropEffects.Copy
       Else
          e.Effect = DragDropEffects.None
       End If
       'End of user's code
    End Sub
    

    C#

    private void  theControl_OLEDragOverEvent( DragEventArgs e,  short State)
    {
       int X = e.X;
       int Y = e.Y;
       int Button = e.KeyState | 0x100000;
       int Shift = (int)Control.ModifierKeys | 0x10000;
       Support.ConvertCoordinatesToClient(Text1, ref X, ref Y);
    
      //User's code
       if (e.Data.GetDataPresent(DataFormats.Text))
       {
          e.Effect = DragDropEffects.Copy;
       }
      else
       {
          e.Effect = DragDropEffects.None;
       }
       //End of user's code
    }
    

    Generate the drag enter, over and leave event handlers for the Control which is receiving the drag and drop event. Insert calls to the above method in the generated event handlers, adding the expected parameters.

    Also, add the line required to allow the Drag and Drop operations in the DragEnter event handler.

    Visual Basic .NET

    Private Sub theControl_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles theControl.DragEnter
       e.Effect = DragDropEffects.All
       theControl_OLEDragOverEvent(e, 0)
    End Sub
    
    Private Sub theControl_DragLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles theControl.DragLeave
       theControl_OLEDragOverEvent(New DragEventArgs(Nothing, 0, 0, 0, DragDropEffects.All, DragDropEffects.All), 1)
    End Sub
    
    Private Sub theControl_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles theControl.DragOver
       theControl_OLEDragOverEvent(e, 2)
    End Sub
    

    C#

    private void theControl_DragEnter(object sender, DragEventArgs e)
    {
       e.Effect = DragDropEffects.All;
       theControl_OLEDragOverEvent(e, 0);
    }
    
    private void theControl_DragLeave(object sender, EventArgs e)
    {
       theControl_OLEDragOverEvent(new DragEventArgs(null,0,0,0,DragDropEffects.All,DragDropEffects.All), 1);
    }
    
    private void theControl_DragOver(object sender, DragEventArgs e)
    {
       theControl_OLEDragOverEvent(e, 2);
    }
    

    3.3.4. Required support methods

    Add the following support methods to the project’s Support class. GetSourceObject method is used to extract the instance of the source control of the drag and drop process. ConvertCoordinatesToClient method is used to convert the screen coordinates produced by .NET events to coordinates inside the control which is receiving the event

    Visual Basic .NET

    'Convert .NET event's screen coordinates to client control coordinates to be used by converted drag and drop members
    Public Sub ConvertCoordinatesToClient(ByVal clientControl As Control, ByRef x As Integer, ByRef y As Integer)
       Dim convertedCoordinates As Point = clientControl.PointToClient(New Point(x, y))
       x = convertedCoordinates.X
       y = convertedCoordinates.Y
    End Sub
    

    C#

    class Support
    {
    
       /// <summary>
       /// Convert .NET event's screen coordinates to client control 
       /// coordinates to be used by converted drag and drop members
       /// </summary>
       /// <param name="clientControl">Control to where the coordinates will be traslated</param>
       /// <param name="x">X Coordinate</param>
       /// <param name="y">Y Coordinate</param>
       public void ConvertCoordinatesToClient(Control clientControl, 
    ref int x, ref int y)
       { 
          Point  convertedCoordinates = clientControl.PointToClient
    (new Point(x,y));
          x = convertedCoordinates.X;
          y = convertedCoordinates.Y;
       }
    }
    

    3.3.5. Additional code for controls with no DragOver handlers in source

    Add a .NET DragEnter event handler and add the following line of code

    Visual Basic .NET

    Private Sub theControl_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles theControl.DragEnter
    
       'UPGRADE_WARNING: The following statemente was inserted to allow this control to receive drag and drop actions 
       e.Effect = DragDropEffects.All
    
    End Sub
    

    C#

    private void theControl_DragEnter(object sender, DragEventArgs e)
    {
       //UPGRADE_WARNING: The following statement was inserted to allow this control to receive drag and drop actions
       e.Effect = DragDropEffects.All;
    }
    

    C# requires to register the event in the designer code

    C#

    this.theControl.DragEnter += new DragEventHandler(this.theControl_DragEnter);

    3.4. OLEDragDrop event

    This event is raised at the time the user releases the mouse button over a target, after a drag and drop operation.

    3.4.1. Source code

    Private Sub theControl_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
       'User's code
       If Data.GetFormat(vbCFText) Then
          theControl.Text = Data.GetData(vbCFText)
       End If
       'End of user's code
    End Sub
    

    3.4.2. Expected code

    The DataObject, Effect, Button, X and Y coordinates parameters are now contained by the DragEventArgs parameter. The conversion process should insert additional code inside the event handler to extract the required values being used by the user’s code. Conversion code for parameters not used in user’s code can be omitted.

    Visual Basic .NET

    Private Sub theControl _DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles theControl.DragDrop
       Dim X As Single = e.X
       Dim Y As Single = e.Y
       Dim Button As Integer = e.KeyState \ &H100000
       Dim Shift As Integer = Control.ModifierKeys \ &H10000
       ConvertCoordinatesToClient(theControl, X, Y)
       'User's code
       If e.Data.GetDataPresent(DataFormats.Text) Then
          theControl.Text = CStr(e.Data.GetData(DataFormats.Text))
       End If
       'End of user's code
    
    End Sub
    

    C#

    private void Text1_DragDrop(object sender, DragEventArgs e)
    {   
       int X = e.X;
       int Y = e.Y;
       int Button = e.KeyState | 0x100000;
       int Shift = (int)Control.ModifierKeys | 0x10000;
       Support.ConvertCoordinatesToClient(Text1, ref X, ref Y);
       //User's code                    
       if (e.Data.GetDataPresent(DataFormats.Text))
       {
          Text1.Text = Convert.ToString(e.Data.GetData(DataFormats.Text));
       } 
       //End of user's code
    }
    

    Parameters mappings:

    VB6 Reference .NET Reference
    Data (DataObject) e.Data (DataObject inside e event arguments)
    Effect (Long) e.Effect (DragDropEffects)
    Button e.KeyState masked with hex 100000
    Shift Control.ModifierKeys masked with hex 10000
    X e.X (needs to be converted to control coordinates)
    Y e.Y (needs to be converted to control coordinates)

    3.5. OLECompleteDrag

    This event was raised to notify the source control when the drag-and-drop operation was complete. This was typically used to remove the data from the source for a cut and paste operation.

    3.5.1 Source code

    Private Sub theControl_OLECompleteDrag(Effect As Long)
      'Code to process the event
    End Sub
    

    3.5.2. Expected code

    Visual Basic .NET

    Private Sub theControl_OLECompleteDrag(ByVal Effect As Long)
      'Code to process the event
    End Sub
    

    C#

    private void theControl_OLECompleteDrag(int Effect)
    {
      //Code to process the event
    }
    

    Insert a call to the OLECompleteDrag method inside the OLEStartDrag method, just after the call to DoDragDrop method. Pass the Drag and Drop effect value returned by the DoDragDrop call.

    Visual Basic .NET

    Private Sub theControl_OLEStartDrag()
       Dim Effect As DragDropEffects
       Effect = theControl.DoDragDrop(theControl.SelectedText, DragDropEffects.Copy)
       
       'UPGRADE_WARNING: The following statement was inserted to support conversion of Drag and Drop
       theControl_OLECompleteDrag(Effect)
    
    End Sub
    

    C#

    private void  theControl_OLEStartDrag( )
    {
       DragDropEffects effect;
       effect = theControl.DoDragDrop(theControl.SelectedText, DragDropEffects.Copy);
    
       //UPGRADE_WARNING: The following statement was inserted to support conversion of Drag and Drop
       theControl_OLECompleteDrag((int)effect);
    }
    

    3.6. OLEGiveFeedback

    This event is raised whenever the mouse passes over a possible target, during a drag and drop operation.

    3.6.1. Source code

    Private Sub theControl_OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean)
        
       'User's code
        If Effect = vbDropEffectNone Then
            theControl.ForeColor = RGB(255, 0, 0)
        Else
            theControl.ForeColor = RGB(0, 0, 0)
        End If
        
        Dim defCursors As Boolean
        defCursors = DefaultCursors
       'End of user's code
    
    End Sub
    

    3.6.2. Expected code

    To convert the GiveFeedback event handler, generate a .NET GiveFeedback event handler. References to Effect parameter must be changed to e.Effect and references to DefaultCursors parameter to e.UseDefaultCursors, with ‘e’ being the GiveFeedbackEventArgs parameter.

    Visual Basic .NET

    Private Sub theControl_GiveFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs) Handles Text1.GiveFeedback
    
       'User's code 
       If e.Effect = DragDropEffects.None Then
          theControl.ForeColor = Color.FromArgb(255, 0, 0)
       Else
          theControl.ForeColor = Color.FromArgb(0, 0, 0)
       End If
    
       Dim defCursors As Boolean
       defCursors = e.UseDefaultCursors
       'End of user's code
    
    End Sub
    

    C#

    private void theControl_GiveFeedback(object sender, GiveFeedbackEventArgs e)
    {
       //User's code
       if (e.Effect == ((int)DragDropEffects.None))
       {
          theControl.ForeColor = Color.FromArgb(255, 0, 0);
       }
       else
       {
          theControl.ForeColor = Color.FromArgb(0, 0, 0);
       }
    
       bool defCursors;
       defCursors = e.UseDefaultCursors;
       //End of user's code
    }
    

    3.7. OLESetData

    OLESetData event is fired when the drag and drop operation ends and the Data was not set in the OLEStartDrag event at the start of the drag and drop operation. This helps to delay the setting of the Data to whenever the programmer considers more appropiate.

    Conversion and support for this event requires modifing the code inside the OLEStartDrag converted event, in order to pass some indicator of data not set yet to the target control’s DragDrop event handler.

    3.7.1. Source code

    Note the empty parameter in the SetData method inside OLEStartDrag event handler. It indicates that the Data will be set inside OLESetData event handler when another control asks for it calling the DataObject GetData method.

    Private Sub theControl_OLESetData(Data As DataObject, DataFormat As Integer)
       If DataFormat = vbCFText Then
          Data.SetData "Text", vbCFText
       Else
          Data.SetData "RTF", vbCFRTF
       End If 
    End Sub
    

    Note the empty value parameter in the Data.SetData method call.

    Private Sub theControl_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
            Data.SetData , vbCFText
            AllowedEffects = vbDropEffectCopy
    End Sub
    

    3.7.2. Expected code

    Asumming that the delayed data setting is not widely used, conversion process can use a simpler method to recover the functionality. Basically, the delayed setting feature will be removed and the data will be set since the start of the Drag and Drop operation.

    It’s possible that in the OLESetData event handler, the Data to be set can change depending on the DataFormat value. This DataFormat is set in the GetData method at the end of the drag and drop operation, by the target control.

    The best compromise is to assign the value corresponding to the same format set to the data object inside the OLEStartDrag event handler.

    I.e., in the source code the data format set at the beginning (OLEStartDrag) is vbCFText, and the data parameter is empty. Later (in OLESetData), the data assignation will depend in the DataFormat parameter that could be vbCFText or vbCFRTF. Conversion process will choose the assignation corresponding to vbCFText (from OLEStartDrag) which is “SetData Text, vbCFText”, so the value to be set to the data object will be “Text”

    The OLESetData method should be commented out, in case that the programmer needs to check anything of the original behavior of the code.

    Visual Basic .NET

    Private Sub Text1_OLEStartDrag()
       Dim Effect As DragDropEffects
       'Data.SetData(, vbCFText)
       'UPGRADE_WARNING: Drag and Drop delayed data setting behavior was removed.
       Effect = Text1.DoDragDrop("Text", DragDropEffects.Copy)
    End Sub
    
    
    'UPGRADE_WARNING: Drag and Drop delayed data setting behavior was removed.
    'Private Sub Text1_OLESetData(ByRef Data As DataObject, ByRef DataFormat As Short)
    '    If DataFormat = vbCFText Then
    '           Data.SetData("Text", vbCFText)
    '       Else
    '           Data.SetData("RTF", vbCFRTF)
    '       End If
    'End Sub
    

    C#

    private void Text2_OLEStartDrag()
    {
       DragDropEffects effect;
       //Data.SetData( , vbCFText);
       //AllowedEffects = (int) DragDropEffects.Copy;
                    
       //UPGRADE_WARNING: Drag and Drop delayed data setting behavior was removed.    
       effect = Text2.DoDragDrop("Text", DragDropEffects.Copy);
       Text2_OLECompleteDrag((int)effect);
    }
    
    //UPGRADE_WARNING: Drag and Drop delayed data setting behavior was removed.            
    //private void  Text2_OLESetData( DataObject Data,  short DataFormat)
    //{
    //    if ( DataFormat = vbCFText ) 
    //    {
    //        Data.SetData("Text", vbCFText);
    //    }
    //    else
    //    {
    //        Data.SetData("RTF", vbCFRTF);
    //    }
    //}
    

    3.8. Conversion of constants for OLE drag and drop

    VB6 format constants can be converted to System.Windows.Forms.DataFormats constants.

    Table 1. Equivalences of format constants.

    VB6 Constant .NET Constant
    vbCFText DataFormats.Text
    vbCFBitmap DataFormats.Bitmap
    vbCFMetafile DataFormats.MetafilePict
    vbCFEMetafile DataFormats.EnhancedMetafile
    vbCFDIB DataFormats.Dib
    vbCFPalette DataFormats.Palette
    vbCFFiles DataFormats.FileDrop
    vbCFRTF DataFormats.Rtf

    VB6 drag and drop constants can be converted to System.Windows.Forms.DragDropEffects constants.

    Table2. Equivalences for allowed drag and drop effects constants

    VB6 Constant .NET Constant
    vbDropEffectNone DragDropEffects.None
    vbDropEffectCopy DragDropEffects.Copy
    vbDropEffectMove DragDropEffects.Move
    vbDropEffectScroll DragDropEffects.Scroll

    3.9. Additional mappings to support conversion

    VB6 drag and drop uses a DataObject object to pass all the data and information used by the drag and drop operation as a parameter to all events. .NET uses a similar approach but the DataObject object is encapsulated inside the DragEventArgs parameter of the events.

    VB6 Member .NET Member
    DataObject.GetFormat(int) DataObject.GetDataPresent(DataFormats)
    DataObject.SetData(p1:object,p2:int) DataObject.SetData(p2:DataFormats, p1:object)*
    DataObject.GetData(int) DataObject.GetData(DataFormats)

    * Conversion of DataObject.SetData needs a special conversion when starting a drag and drop action as described in sections 3.2.1.

    3.10. DragMode property

    3.10.1. Source code

    Automatic drag mode allows the whole control or its contents to be dragged. This feature is not supported in .NET.

    theControl.OLEDragMode = vbAutomatic

    VB6 Manual drag mode requires to code all the drag and drop handling. This is the same as .NET drag and drop.

    theControl.OLEDragMode = vbManual

    3.10.2. Expected code

    Automatic drag and drop is not supported in .NET

    Visual Basic .NET

    'UPGRADE_WARNING: Control.DragMode was not upgraded.
    'theControl.OLEDragMode = vbAutomatic
    

    C#

    //UPGRADE_WARNING: Control.DragMode was not upgraded.
    //theControl.OLEDragMode = vbAutomatic
    

    Manual drag and mode is the default behavior of .NET drag and drop. All drag and drop handling must be coded.

    Visual Basic .NET

    'UPGRADE_WARNING: Control.DragMode was not upgraded.
    'theControl.OLEDragMode = vbManual
    

    C#

    //UPGRADE_WARNING: Control.DragMode was not upgraded.
    //theControl.OLEDragMode = vbManual
    


    See also:


    Download VBUC Free Trial
    Download VBUC Now

    It's time to eradicate VB6
    ROI of eradicating VB6

    8 Proven Tips for
    Planning a Successful Migration

    8 Tips for migration