Extend Constituent Control Drag Events


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 4 of 4

Thread: Extend Constituent Control Drag Events

  1. #1
    Todd Mitchell Guest

    Extend Constituent Control Drag Events


    I have created a user control with one constituent control: a treeview. I
    can drag and drop nodes just fine within the treeview, but once I leave the
    bounds of the user control, the mouse icon changes to a no-drop and I can't
    raise any dragover or dragdrop events on any other object.

    The same treeview works fine if I put it on a form without being contained
    in a user control. I can instantiate multiple instances of said form and
    drag/drop between the treeviews on the different form instances without any
    problem.

    How do I extend the treeveiw drag events beyond the bounds of its container?

    Incidentally I am controlling drag/drop manually and I am not using OLEDrag.

  2. #2
    Mark Alexander Bertenshaw Guest

    Re: Extend Constituent Control Drag Events

    Todd -

    We have come up against this problem, and I hope that it isn't too late to
    change your design.

    Basically, this behaviour, as Microsoft often says, is by design. "Standard
    VB" drag drop will only work for controls on a VB container, such as a Form,
    UserDocument, UserControl, etc. Another thing you must realise it that
    within drag drop, VB only sees the "Extender" object that wraps up each
    control - it cannot see "into" the control, because else this would break
    COM encapsulation. COM is supposed to be language independent, so we cannot
    assume that the code inside the control understands VB drag drop.

    So there are two ways that you can solve this problem: one ideal, one hacky.
    Guess which one we chose <g>.

    The "ideal" way is to use the COM standard way to do drag drop. Since every
    language or library implements and interfaces drag drop in different ways,
    Microsoft decided to create a standard way to do this - called OLEDragDrop,
    in Visual Basic. Luckily, all intrinsic VB controls support this, as do the
    Common Controls OCXs supplied by Microsoft. The majority of modern 3rd
    party controls do as well, although you ought to check this out to be sure.
    Behind the scenes, this magic is enacted by requiring a control to implement
    one or more of the COM interfaces, such as IDragDrop. You won't have to
    know about these interfaces; however, you ought to know that the mechanism
    of drag drop is quite different from the VB drag drop mechanism. The latter
    is based around the concept of dragging controls over and onto other
    controls. However, OLE drag drop is far more sophisticated, involving a
    number of conversations (represented by one of 6 possible events as opposed
    to VB's two events) between a data source and a data destination. Data
    sources and destinations can supply data in any of a multitude of formats,
    which are based on the clipboard formats (and can potentially be extended ad
    finitum). More than one data format can be made available, and the
    destination can choose one or more of these formats). Many of the VB
    controls already have automatic support for particular formats. For
    instance, if you set the textbox's OLEDragMode to Automatic, you can select
    its text, and drag it. Likewise, a textbox's OLEDropMode at Automatic
    allows you to drag text into it, and it is automatically inserted.

    Now this is all well and cool, but what is important for you is that OLE
    Drag Drop doesn't care about your application's structure. All it knows is
    that if you OLE drag something over a window, regardless of its position in
    a hierarchy of windows, a conversation will be attempted with that window,
    and so you have a chance to drag stuff into it. So set your TreeView
    control's OLEDrag to Manual, and get reading the manual!!

    Of course, it may be too late for that - you have already written tons of
    drag drop code. Even so, consider junking it, because despite your loss,
    you will gain a wonderful flexibility. But, just in case, I should tell you
    how we got round this: The Mouse_Down and Mouse_Move <within> the
    UserControl code gives the signal to start the drag. However, we don't drag
    the internal tree. Instead, we raise an event, StartDrag, and in the
    external form's event procedure, we do <TreeUserControl1.Drag 1>. Now, all
    the drag drop is happening on the form. Whenever the
    <TreeUserControl1_DragOver> and <TreeUserControl1_DragDrop> events fire, the
    DragOver and DragDrop method that we have created on the UserControl are
    called, thus providing us feedback.

    Personally, this set-up definitely sucks big time, and the more I think of
    it, the more angry I get. If you do it this way, you code becomes very
    non-portable. It also only works for one level of drag drop. If, for
    instance, you wanted to further encapsulate <TreeUserControl1> into another
    UserControl, you would have to write yet more delegation code.


    Anyway, I hope that this helps.
    --

    ---------------------------------------
    Mark Alexander Bertenshaw
    Programmer/Analyst
    Prime Response
    Brentford
    UK
    "Todd Mitchell" <Todd.Mitchell@RuckusInteractive.com> wrote in message
    news:38e7fd15$1@news.devx.com...
    >
    > I have created a user control with one constituent control: a treeview. I
    > can drag and drop nodes just fine within the treeview, but once I leave

    the
    > bounds of the user control, the mouse icon changes to a no-drop and I

    can't
    > raise any dragover or dragdrop events on any other object.
    >
    > The same treeview works fine if I put it on a form without being contained
    > in a user control. I can instantiate multiple instances of said form and
    > drag/drop between the treeviews on the different form instances without

    any
    > problem.
    >
    > How do I extend the treeveiw drag events beyond the bounds of its

    container?
    >
    > Incidentally I am controlling drag/drop manually and I am not using

    OLEDrag.



  3. #3
    Todd Mitchell Guest

    Re: Extend Constituent Control Drag Events


    Mark -

    Thanks for the response! I sincerely appreciate the time you took to write
    this. It is helpful to see how others have tackled these issues.

    What I wound up doing was to create a Class Object that wraps up a TreeView
    object. I exposed this TreeView object as a property of the Class Object,
    and replicated all the TreeView events as methods of the Class Object.

    Each form that needs the TreeView sets the Class Object's TreeView object
    property equal to the TreeView on the form. By setting the form's TreeView
    BYREF equal to the Class Object's TreeView object, anything done to the TreeView
    in the Class Object is, naturally, done to the TreeView on the form. (I
    actually found a great example of how ByRef should be used!)

    This does require you to trap each of the Form TreeView's events and pass
    the event arguments directly to the corresponding methods of the Class Object,
    like this:

    Private Sub tvwExposure_DragDrop(Source As Control, X As Single, Y As Single)
    ' moTreeview is a module level instance of clsTreeView
    moTreeview.ClassTreeview_DragDrop Source, X, Y
    End Sub

    On the surface, this sounds like a bit of a hack, but it is operating quite
    well and the code is pretty easy to read since it is close to what would
    otherwise be expected.

    I'll keep sloggin' away,

    Todd
    http://webpages.mr.net/mitcht/


    "Mark Alexander Bertenshaw" <Mark.Bertenshaw@virgin.net> wrote:
    >Todd -
    >
    >We have come up against this problem, and I hope that it isn't too late

    to
    >change your design.
    >
    >Basically, this behaviour, as Microsoft often says, is by design. "Standard
    >VB" drag drop will only work for controls on a VB container, such as a Form,
    >UserDocument, UserControl, etc. Another thing you must realise it that
    >within drag drop, VB only sees the "Extender" object that wraps up each
    >control - it cannot see "into" the control, because else this would break
    >COM encapsulation. COM is supposed to be language independent, so we cannot
    >assume that the code inside the control understands VB drag drop.
    >
    >So there are two ways that you can solve this problem: one ideal, one hacky.
    >Guess which one we chose <g>.
    >
    >The "ideal" way is to use the COM standard way to do drag drop. Since every
    >language or library implements and interfaces drag drop in different ways,
    >Microsoft decided to create a standard way to do this - called OLEDragDrop,
    >in Visual Basic. Luckily, all intrinsic VB controls support this, as do

    the
    >Common Controls OCXs supplied by Microsoft. The majority of modern 3rd
    >party controls do as well, although you ought to check this out to be sure.
    >Behind the scenes, this magic is enacted by requiring a control to implement
    >one or more of the COM interfaces, such as IDragDrop. You won't have to
    >know about these interfaces; however, you ought to know that the mechanism
    >of drag drop is quite different from the VB drag drop mechanism. The latter
    >is based around the concept of dragging controls over and onto other
    >controls. However, OLE drag drop is far more sophisticated, involving a
    >number of conversations (represented by one of 6 possible events as opposed
    >to VB's two events) between a data source and a data destination. Data
    >sources and destinations can supply data in any of a multitude of formats,
    >which are based on the clipboard formats (and can potentially be extended

    ad
    >finitum). More than one data format can be made available, and the
    >destination can choose one or more of these formats). Many of the VB
    >controls already have automatic support for particular formats. For
    >instance, if you set the textbox's OLEDragMode to Automatic, you can select
    >its text, and drag it. Likewise, a textbox's OLEDropMode at Automatic
    >allows you to drag text into it, and it is automatically inserted.
    >
    >Now this is all well and cool, but what is important for you is that OLE
    >Drag Drop doesn't care about your application's structure. All it knows

    is
    >that if you OLE drag something over a window, regardless of its position

    in
    >a hierarchy of windows, a conversation will be attempted with that window,
    >and so you have a chance to drag stuff into it. So set your TreeView
    >control's OLEDrag to Manual, and get reading the manual!!
    >
    >Of course, it may be too late for that - you have already written tons of
    >drag drop code. Even so, consider junking it, because despite your loss,
    >you will gain a wonderful flexibility. But, just in case, I should tell

    you
    >how we got round this: The Mouse_Down and Mouse_Move <within> the
    >UserControl code gives the signal to start the drag. However, we don't

    drag
    >the internal tree. Instead, we raise an event, StartDrag, and in the
    >external form's event procedure, we do <TreeUserControl1.Drag 1>. Now,

    all
    >the drag drop is happening on the form. Whenever the
    ><TreeUserControl1_DragOver> and <TreeUserControl1_DragDrop> events fire,

    the
    >DragOver and DragDrop method that we have created on the UserControl are
    >called, thus providing us feedback.
    >
    >Personally, this set-up definitely sucks big time, and the more I think

    of
    >it, the more angry I get. If you do it this way, you code becomes very
    >non-portable. It also only works for one level of drag drop. If, for
    >instance, you wanted to further encapsulate <TreeUserControl1> into another
    >UserControl, you would have to write yet more delegation code.
    >
    >
    >Anyway, I hope that this helps.
    >--
    >
    >---------------------------------------
    >Mark Alexander Bertenshaw
    >Programmer/Analyst
    >Prime Response
    >Brentford
    >UK
    >"Todd Mitchell" <Todd.Mitchell@RuckusInteractive.com> wrote in message
    >news:38e7fd15$1@news.devx.com...
    >>
    >> I have created a user control with one constituent control: a treeview.

    I
    >> can drag and drop nodes just fine within the treeview, but once I leave

    >the
    >> bounds of the user control, the mouse icon changes to a no-drop and I

    >can't
    >> raise any dragover or dragdrop events on any other object.
    >>
    >> The same treeview works fine if I put it on a form without being contained
    >> in a user control. I can instantiate multiple instances of said form

    and
    >> drag/drop between the treeviews on the different form instances without

    >any
    >> problem.
    >>
    >> How do I extend the treeveiw drag events beyond the bounds of its

    >container?
    >>
    >> Incidentally I am controlling drag/drop manually and I am not using

    >OLEDrag.
    >
    >



  4. #4
    Mike Guest

    Re: Extend Constituent Control Drag Events


    Mark,

    There is a far better way to do this that VB 6 (and 5?) has given us. In
    your class module, dim the treeview as withevents. eg (at top of class)

    Private Withevents mtvwMain as TreeView

    Then, as you already had done:

    Public Property Set Treeview(ByVal NewVal as TreeView)
    set mtvwMain=NewVal
    End Property

    Now your class will automatically get all treeview events without you writing
    any extra code (in fact, you write MUCH less code). Note that mtvwMain is
    an item in the top left combo box, and the events are in the combobox on
    the right - exactely as they were when you where writing your usercontrol.

    You could even do this with a usercontrol, instead of a class, then it could
    have persistant properties. Make it windowless and 'invisibleAtRuntime' to
    save resources.

    Also, make sure you set it to nothing in class_terminate.

    Both these methods have an advantage over putting a control on a usercontrol
    - they both only use one window handle, were a control on a usercontrol uses
    2. This doesn't sound that bad, but make a big form full of these usercontrols
    and you will have alot of windows.

    Also, passing in the treeview by ref makes no difference. The object (treeview)
    sits in memory somewhere. You get a pointer to it. If you pass it in byVal,
    you duplicate the pointer. But if you pass it in byRef, you get the same
    pointer (or maybe a pointer to the pointer, i'm not sure which). But the
    point is (hehe) they all point to the one object in memory, hence all do
    the same thing.

    Mike



    "Todd Mitchell" <Todd.Mitchell@RuckusInteractive.com> wrote:
    >
    >Mark -
    >
    >Thanks for the response! I sincerely appreciate the time you took to write
    >this. It is helpful to see how others have tackled these issues.
    >
    >What I wound up doing was to create a Class Object that wraps up a TreeView
    >object. I exposed this TreeView object as a property of the Class Object,
    >and replicated all the TreeView events as methods of the Class Object.
    >
    >Each form that needs the TreeView sets the Class Object's TreeView object
    >property equal to the TreeView on the form. By setting the form's TreeView
    >BYREF equal to the Class Object's TreeView object, anything done to the

    TreeView
    >in the Class Object is, naturally, done to the TreeView on the form. (I
    >actually found a great example of how ByRef should be used!)
    >
    >This does require you to trap each of the Form TreeView's events and pass
    >the event arguments directly to the corresponding methods of the Class Object,
    >like this:
    >
    >Private Sub tvwExposure_DragDrop(Source As Control, X As Single, Y As Single)
    > ' moTreeview is a module level instance of clsTreeView
    > moTreeview.ClassTreeview_DragDrop Source, X, Y
    >End Sub
    >
    >On the surface, this sounds like a bit of a hack, but it is operating quite
    >well and the code is pretty easy to read since it is close to what would
    >otherwise be expected.
    >
    >I'll keep sloggin' away,
    >
    >Todd
    >http://webpages.mr.net/mitcht/
    >
    >
    >"Mark Alexander Bertenshaw" <Mark.Bertenshaw@virgin.net> wrote:
    >>Todd -
    >>
    >>We have come up against this problem, and I hope that it isn't too late

    >to
    >>change your design.
    >>
    >>Basically, this behaviour, as Microsoft often says, is by design. "Standard
    >>VB" drag drop will only work for controls on a VB container, such as a

    Form,
    >>UserDocument, UserControl, etc. Another thing you must realise it that
    >>within drag drop, VB only sees the "Extender" object that wraps up each
    >>control - it cannot see "into" the control, because else this would break
    >>COM encapsulation. COM is supposed to be language independent, so we cannot
    >>assume that the code inside the control understands VB drag drop.
    >>
    >>So there are two ways that you can solve this problem: one ideal, one hacky.
    >>Guess which one we chose <g>.
    >>
    >>The "ideal" way is to use the COM standard way to do drag drop. Since

    every
    >>language or library implements and interfaces drag drop in different ways,
    >>Microsoft decided to create a standard way to do this - called OLEDragDrop,
    >>in Visual Basic. Luckily, all intrinsic VB controls support this, as do

    >the
    >>Common Controls OCXs supplied by Microsoft. The majority of modern 3rd
    >>party controls do as well, although you ought to check this out to be sure.
    >>Behind the scenes, this magic is enacted by requiring a control to implement
    >>one or more of the COM interfaces, such as IDragDrop. You won't have to
    >>know about these interfaces; however, you ought to know that the mechanism
    >>of drag drop is quite different from the VB drag drop mechanism. The latter
    >>is based around the concept of dragging controls over and onto other
    >>controls. However, OLE drag drop is far more sophisticated, involving

    a
    >>number of conversations (represented by one of 6 possible events as opposed
    >>to VB's two events) between a data source and a data destination. Data
    >>sources and destinations can supply data in any of a multitude of formats,
    >>which are based on the clipboard formats (and can potentially be extended

    >ad
    >>finitum). More than one data format can be made available, and the
    >>destination can choose one or more of these formats). Many of the VB
    >>controls already have automatic support for particular formats. For
    >>instance, if you set the textbox's OLEDragMode to Automatic, you can select
    >>its text, and drag it. Likewise, a textbox's OLEDropMode at Automatic
    >>allows you to drag text into it, and it is automatically inserted.
    >>
    >>Now this is all well and cool, but what is important for you is that OLE
    >>Drag Drop doesn't care about your application's structure. All it knows

    >is
    >>that if you OLE drag something over a window, regardless of its position

    >in
    >>a hierarchy of windows, a conversation will be attempted with that window,
    >>and so you have a chance to drag stuff into it. So set your TreeView
    >>control's OLEDrag to Manual, and get reading the manual!!
    >>
    >>Of course, it may be too late for that - you have already written tons

    of
    >>drag drop code. Even so, consider junking it, because despite your loss,
    >>you will gain a wonderful flexibility. But, just in case, I should tell

    >you
    >>how we got round this: The Mouse_Down and Mouse_Move <within> the
    >>UserControl code gives the signal to start the drag. However, we don't

    >drag
    >>the internal tree. Instead, we raise an event, StartDrag, and in the
    >>external form's event procedure, we do <TreeUserControl1.Drag 1>. Now,

    >all
    >>the drag drop is happening on the form. Whenever the
    >><TreeUserControl1_DragOver> and <TreeUserControl1_DragDrop> events fire,

    >the
    >>DragOver and DragDrop method that we have created on the UserControl are
    >>called, thus providing us feedback.
    >>
    >>Personally, this set-up definitely sucks big time, and the more I think

    >of
    >>it, the more angry I get. If you do it this way, you code becomes very
    >>non-portable. It also only works for one level of drag drop. If, for
    >>instance, you wanted to further encapsulate <TreeUserControl1> into another
    >>UserControl, you would have to write yet more delegation code.
    >>
    >>
    >>Anyway, I hope that this helps.
    >>--
    >>
    >>---------------------------------------
    >>Mark Alexander Bertenshaw
    >>Programmer/Analyst
    >>Prime Response
    >>Brentford
    >>UK
    >>"Todd Mitchell" <Todd.Mitchell@RuckusInteractive.com> wrote in message
    >>news:38e7fd15$1@news.devx.com...
    >>>
    >>> I have created a user control with one constituent control: a treeview.

    > I
    >>> can drag and drop nodes just fine within the treeview, but once I leave

    >>the
    >>> bounds of the user control, the mouse icon changes to a no-drop and I

    >>can't
    >>> raise any dragover or dragdrop events on any other object.
    >>>
    >>> The same treeview works fine if I put it on a form without being contained
    >>> in a user control. I can instantiate multiple instances of said form

    >and
    >>> drag/drop between the treeviews on the different form instances without

    >>any
    >>> problem.
    >>>
    >>> How do I extend the treeveiw drag events beyond the bounds of its

    >>container?
    >>>
    >>> Incidentally I am controlling drag/drop manually and I am not using

    >>OLEDrag.
    >>
    >>

    >



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center