Results 1 to 11 of 11

Thread: TabControl with DragDrop not raising MouseClick events on tabs

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    TabControl with DragDrop not raising MouseClick events on tabs

    Hi,

    I have a custom (inherited) TabControl which adds Drag/Drop functionality to it, so that one can drag the tabs around, either within the same control (to re-order them) or to and from other TabControls.

    I've noticed some time ago that my TabControl however was not raising its MouseClick and MouseUp events (or actually: it is not calling its OnMouseClick and OnMouseUp methods, which comes down to the same thing).
    I've been struggling with this problem for a long while and I finally figured out what is happening. I'm no closer to figuring out what to do about it though...


    The problem seems related to the drag drop functionality. I have this code in the OnMouseDown method (which is raised as usual):
    vb.net Code:
    1. Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
    2.         MyBase.OnMouseDown(e)
    3.  
    4.         If e.Button = Windows.Forms.MouseButtons.Left Then
    5.             Dim pt As Point = New Point(e.X, e.Y)
    6.             Dim tp As Tab = Me.GetTabFromPoint(pt)
    7.  
    8.             If tp IsNot Nothing Then
    9.                 Me.DoDragDrop(tp, DragDropEffects.All)
    10.             End If
    11.         End If
    12.     End Sub
    To summarize, if the Left button is clicked, I get the TabPage under the mouse (if any) and start a DragDrop operation with the TabPage as the first argument. This causes some other code in the OnDragOver method to run which handles the re-ordering of the tabs (irrelevant code).

    If I use this code, the OnMouseClick and OnMouseUp methods are never called.

    If I remove the Me.DoDragDrop call, they are called as usual.


    What can I do about this? I definitely want the drag drop functionality, but I also definitely want to handle the MouseClick and MouseUp events since I'm drawing close buttons on my TabPages, and without these events you can't click them...

  2. #2

  3. #3
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    The mouse events are not called when a drag operation is in progress.

    There are OnDragOver - which you have found - and OnDragDrop (I think, as well as OnDragEnter and OnDragLeave) that should contain information about the drag operation.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Yes, but I don't need information about the drag operation. I just need to be able to handle the OnMouseClick method to determine if the click is inside the close button rectangle (and if it is, the tab is sent a close request), and possibly the OnMouseUp event to invalidate the tab header.

    I can't see any way around this at all... The MouseClick event works in such a way that it is only raised when you release the mouse, so clicking it down and holding it will not raise it (yet). Even if you move the mouse around a little before releasing it, the event is still fired only later. That is exactly the behavior I want, and it is why I can't use the MouseDown event: that will be raised as soon as the button is pressed, which is too early. The user could choose to click the close button while holding the mouse, then move the mouse back out and release it outside of the close button. In that case, the tab should not close. If I use the MouseDown event, the tab will close as soon as you press.

    But this is a problem: if you press the mouse and then move it even slightly, the drag drop operation will begin... So how can I do what I want and still have the drag drop functionality?

  5. #5
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Nick, as SJ said, it seems the framework swallows mouse events during a drag operation. So... from what I can tell there is no managed way to do this. Try this implementation and let me know if that works:

    vb.net Code:
    1. Public Class OrderedTabControl
    2.     Inherits TabControl
    3.  
    4.     '//fields
    5.     Private draggingTab As TabPage = Nothing
    6.  
    7.     '//methods
    8.     Protected Overrides Sub OnDragOver(ByVal drgevent As  _
    9.                                        DragEventArgs)
    10.         MyBase.OnDragOver(drgevent)
    11.  
    12.         drgevent.Effect = DragDropEffects.Move
    13.  
    14.     End Sub
    15.  
    16.     Protected Overrides Sub OnQueryContinueDrag(ByVal e As  _
    17.                                                 QueryContinueDragEventArgs)
    18.         MyBase.OnQueryContinueDrag(e)
    19.  
    20.         If Me.draggingTab IsNot Nothing Then
    21.  
    22.             Dim raiseMouse = False
    23.             Dim pt = Me.PointToClient(Control.MousePosition)
    24.             Dim startTab = Me.GetTabRect(Me.TabPages.IndexOf(Me.draggingTab)) _
    25.                              .Contains(pt)
    26.             Dim otherTab = Me.GetRectangles().Any(Function(r) r.Contains(pt))
    27.             Dim leftButton = Control.MouseButtons.Equals(MouseButtons.Left)
    28.             Dim mouseArgs = New MouseEventArgs(Windows.Forms.MouseButtons.Left, _
    29.                                                1, pt.X, pt.Y, 0)
    30.  
    31.             If Not leftButton AndAlso Not otherTab Then
    32.                 '//mouse let go outside of draggable area
    33.                 e.Action = DragAction.Cancel
    34.                 raiseMouse = True
    35.             ElseIf Not leftButton AndAlso otherTab AndAlso Not startTab Then
    36.                 '//mouse let go in allowable area
    37.                 e.Action = DragAction.Drop
    38.                 raiseMouse = True
    39.             ElseIf Not leftButton AndAlso startTab Then
    40.                 '//mouse let go in rectangle that it started from, cancel drag
    41.                 e.Action = DragAction.Cancel
    42.                 raiseMouse = True
    43.             Else
    44.                 '//anything else can continue
    45.                 e.Action = DragAction.Continue
    46.             End If
    47.  
    48.             If raiseMouse Then
    49.                 Me.OnMouseClick(mouseArgs)
    50.                 Me.OnMouseUp(mouseArgs)
    51.             End If
    52.  
    53.         End If
    54.  
    55.     End Sub
    56.  
    57.     Protected Overrides Sub OnMouseDown(ByVal e As  _
    58.                                         MouseEventArgs)
    59.         MyBase.OnMouseDown(e)
    60.         If e.Button = Windows.Forms.MouseButtons.Left Then
    61.             Dim pt = New Point(e.X, e.Y)
    62.             Dim tp = Me.GetTabFromPoint(pt)
    63.  
    64.             If tp IsNot Nothing Then
    65.                 Me.draggingTab = tp
    66.                 Me.DoDragDrop(tp, DragDropEffects.Move)
    67.             End If
    68.  
    69.         End If
    70.     End Sub
    71.  
    72.     Protected Overrides Sub OnMouseUp(ByVal e As  _
    73.                                       MouseEventArgs)
    74.         MyBase.OnMouseUp(e)
    75.     End Sub
    76.  
    77.     Protected Overrides Sub OnMouseClick(ByVal e As  _
    78.                                          MouseEventArgs)
    79.         MyBase.OnMouseClick(e)
    80.     End Sub
    81.  
    82.     '//methods
    83.     Private Function GetRectangles() As IEnumerable(Of Rectangle)
    84.         Return Me.TabPages.Cast(Of TabPage)() _
    85.                           .Select(Function(t, i) Me.GetTabRect(i))
    86.     End Function
    87.  
    88.     Private Function GetTabFromPoint(ByVal pt As Point) As TabPage
    89.         Return Me.GetTabFromPoint(pt.X, pt.Y)
    90.     End Function
    91.  
    92.     Private Function GetTabFromPoint(ByVal x As Integer, _
    93.                                      ByVal y As Integer) As TabPage
    94.  
    95.         For i = 0 To Me.TabCount - 1
    96.             If Me.GetTabRect(i).Contains(x, y) Then
    97.                 Return Me.TabPages(i)
    98.             End If
    99.         Next
    100.  
    101.         Return Nothing
    102.  
    103.     End Function
    104.  
    105. End Class

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    That looks promising. So basically you call the methods yourself. I thought of that but had no clue when to do it. I never knew about that OnQueryContinueDrag method, and now I think you have also answered a question that I hadn't even asked yet*.

    I've no time to try it right now but I'll get back to you.


    * The question I mean is "how do I react when a tab is dropped outside of a tabcontrol". I have been implementing the 'tab groups' feature of visual studio, where you can arrange the tabs in multiple groups (horizontally or vertically) and drag them between groups. You can create a new group by rightclicking a tab and selecting the appropriate contextmenu item, but in visual studio you can also simply drag a tab outside of any group and it will give you the option of creating a new (horizontal or vertical) group, or if a group already exists it will automatically create a new one (I think). I had no way to do that previously but this OnQueryContinueDrag seems to be the missing link!

  7. #7
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Nick always asks the questions that are the most fun to answer.

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Oh well, that's what I do
    And you always answer them quite satisfyingly. I must say I am a little scared now that you have started answering questions I haven't asked yet

  9. #9
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Yeah, I built an app that reads the mind of any selected VBForums user... I could sell it to you. Right now John is thinking about... eating a Big Mac??!

  10. #10
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Ah, I see your problem, now.

    Here's how I do it: whatever you 'drag' you have to move a certain amount before a drag operation begins. It seems that's how other draggable objects operate, so I've just mimicked that.

    However, in your case, I wouldn't initiate a drag from the close button.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: TabControl with DragDrop not raising MouseClick events on tabs

    Quote Originally Posted by SJWhiteley View Post
    However, in your case, I wouldn't initiate a drag from the close button.


    Why didn't I think of that lol. That's brilliant. Of course I shouldn't initiate a drag from the close button, and if I don't then the mouse events are raised as usual and the whole problem doesn't exist... I haven't tried it yet but I'm sure it will work... You're a genius

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width