|
-
Aug 29th, 2010, 02:15 PM
#1
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:
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseDown(e)
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim pt As Point = New Point(e.X, e.Y)
Dim tp As Tab = Me.GetTabFromPoint(pt)
If tp IsNot Nothing Then
Me.DoDragDrop(tp, DragDropEffects.All)
End If
End If
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...
-
Aug 30th, 2010, 07:50 AM
#2
Re: TabControl with DragDrop not raising MouseClick events on tabs
Nobody..?
-
Aug 30th, 2010, 12:19 PM
#3
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."
-
Aug 30th, 2010, 12:25 PM
#4
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?
-
Aug 30th, 2010, 12:52 PM
#5
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:
Public Class OrderedTabControl Inherits TabControl '//fields Private draggingTab As TabPage = Nothing '//methods Protected Overrides Sub OnDragOver(ByVal drgevent As _ DragEventArgs) MyBase.OnDragOver(drgevent) drgevent.Effect = DragDropEffects.Move End Sub Protected Overrides Sub OnQueryContinueDrag(ByVal e As _ QueryContinueDragEventArgs) MyBase.OnQueryContinueDrag(e) If Me.draggingTab IsNot Nothing Then Dim raiseMouse = False Dim pt = Me.PointToClient(Control.MousePosition) Dim startTab = Me.GetTabRect(Me.TabPages.IndexOf(Me.draggingTab)) _ .Contains(pt) Dim otherTab = Me.GetRectangles().Any(Function(r) r.Contains(pt)) Dim leftButton = Control.MouseButtons.Equals(MouseButtons.Left) Dim mouseArgs = New MouseEventArgs(Windows.Forms.MouseButtons.Left, _ 1, pt.X, pt.Y, 0) If Not leftButton AndAlso Not otherTab Then '//mouse let go outside of draggable area e.Action = DragAction.Cancel raiseMouse = True ElseIf Not leftButton AndAlso otherTab AndAlso Not startTab Then '//mouse let go in allowable area e.Action = DragAction.Drop raiseMouse = True ElseIf Not leftButton AndAlso startTab Then '//mouse let go in rectangle that it started from, cancel drag e.Action = DragAction.Cancel raiseMouse = True Else '//anything else can continue e.Action = DragAction.Continue End If If raiseMouse Then Me.OnMouseClick(mouseArgs) Me.OnMouseUp(mouseArgs) End If End If End Sub Protected Overrides Sub OnMouseDown(ByVal e As _ MouseEventArgs) MyBase.OnMouseDown(e) If e.Button = Windows.Forms.MouseButtons.Left Then Dim pt = New Point(e.X, e.Y) Dim tp = Me.GetTabFromPoint(pt) If tp IsNot Nothing Then Me.draggingTab = tp Me.DoDragDrop(tp, DragDropEffects.Move) End If End If End Sub Protected Overrides Sub OnMouseUp(ByVal e As _ MouseEventArgs) MyBase.OnMouseUp(e) End Sub Protected Overrides Sub OnMouseClick(ByVal e As _ MouseEventArgs) MyBase.OnMouseClick(e) End Sub '//methods Private Function GetRectangles() As IEnumerable(Of Rectangle) Return Me.TabPages.Cast(Of TabPage)() _ .Select(Function(t, i) Me.GetTabRect(i)) End Function Private Function GetTabFromPoint(ByVal pt As Point) As TabPage Return Me.GetTabFromPoint(pt.X, pt.Y) End Function Private Function GetTabFromPoint(ByVal x As Integer, _ ByVal y As Integer) As TabPage For i = 0 To Me.TabCount - 1 If Me.GetTabRect(i).Contains(x, y) Then Return Me.TabPages(i) End If Next Return Nothing End Function End Class
-
Aug 30th, 2010, 01:22 PM
#6
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!
-
Aug 30th, 2010, 01:27 PM
#7
Re: TabControl with DragDrop not raising MouseClick events on tabs
Nick always asks the questions that are the most fun to answer.
-
Aug 30th, 2010, 01:34 PM
#8
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
-
Aug 30th, 2010, 01:43 PM
#9
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??!
-
Aug 30th, 2010, 03:04 PM
#10
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."
-
Aug 30th, 2010, 03:24 PM
#11
Re: TabControl with DragDrop not raising MouseClick events on tabs
 Originally Posted by SJWhiteley
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|