Link to home
Start Free TrialLog in
Avatar of AIBMass
AIBMass

asked on

Can I stop DoubleClick from firing an event in another Window?

This is driving me crazy.

I have a number of labels in Window1. Clicking a specific label correctly causes Window2, which has some buttons on it,  to be brought to the front.

If my user double-clicks on the label in Window1 and the ultimate position of one of the buttons in Window2 is in the same location as the label in Window1, the button fires. This is not desirable!

I can't just handle the double-click event in Window1, because that's not where the event shows up. I get the MouseClick event in Window1 which puts Window2 in place and then the event in Window2 fires.

Does anyone know how to control this?
SOLUTION
Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of AIBMass
AIBMass

ASKER

Thanks for the thought. This doesn't help because the second event of the double-click is in the second window - having disabled the label in Window1 is no longer relevant.
I realized that hence you need to reread the comment!
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Below is an example of #3:
Public Class Form1

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Application.AddMessageFilter(New DoubleClickKiller)
    End Sub

    Private Sub Label1_Click(sender As System.Object, e As System.EventArgs) Handles Label1.Click
        Dim f2 As New Form2
        f2.StartPosition = FormStartPosition.Manual
        f2.Location = Me.Location
        f2.Show()
    End Sub

End Class

Public Class DoubleClickKiller
    Implements IMessageFilter

    Private Const WM_LBUTTONDOWN = &H201
    Private IgnoreWindowInMilliseconds As Integer = SystemInformation.DoubleClickTime ' <-- use the default, or specify your own time
    Private Last_WM_LBUTTONDOWN As DateTime = DateTime.MinValue

    Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
        Select Case m.Msg
            Case WM_LBUTTONDOWN
                Dim CurrentDateTime = DateTime.Now
                If Last_WM_LBUTTONDOWN <> DateTime.MinValue Then
                    If CurrentDateTime.Subtract(Last_WM_LBUTTONDOWN).TotalMilliseconds <= IgnoreWindowInMilliseconds Then
                        Return True ' Consume the click so it doesn't propagate to the application
                    End If
                End If
                Last_WM_LBUTTONDOWN = CurrentDateTime
        End Select
        Return False ' Allow valid messages to be processed normally
    End Function

End Class

Open in new window


*If you need double clicks to be valid elsewhere in the application then you'll need to modify the filter so you can notify it when to ignore clicks; and also allow it to reset itself after the lockout period.
Avatar of AIBMass

ASKER

Let me see. First, an apology to CodeCruiser. Indeed I was responding to some other message rather than the one that was written.

CodeCruiser's suggestion to locate Window2 away from the MouseClick would certainly work. I see the following problems: 1. Because any of the windows in the application can be moved around the placement logic is not simple and 2. We are permanently subjecting some components of the application (Window1) to know about the UI of other components (Window2) and this is highly undesirable. Still, it will have merit in some simple cases.

Idle_Mind has two excellent suggestions. The DoubleClickKiller class works perfectly as supplied. I am strongly considering this method as I don't think the application has any actual call for a DoubleClick. However, this is a bit esoteric for many and that's a disadvantage.

Finally, I am considering a variation of Idle_Mind's second suggestion. I set a variable to the current time when the form is loaded and then provider a function for the Click events to call to verify that the difference between the form load time and the click time exceeds the double click time. This code should be easily understandable even if the motivation for having it is not.

Thanks to both CodeCruiser and Idle_Mind.
There's no good solution to this problem.  =\

While definitely esoteric, the DoubleClickKiller() solution doesn't require changes to every button handler in the application.  You just load it with the one line and you're done!

       Application.AddMessageFilter(New DoubleClickKiller)

The other route will require changes all over the place and increases the chances that you'll make a mistake, or forget to add that additional code down the line if the UI changes.

Good luck!
Avatar of AIBMass

ASKER

Post Mortem: Before implementing the DoubleClickKiller, I am anticipating a problem. Think of the label(s) on Form1 as being Order Numbers and that Form2 is the detail window for orders.

Depending on the size of the order and other issues, it may take anywhere from .25 second to 4 or 5 seconds for Form2 to appear. Thus I fear the second mousedown may be a few seconds, rather than some milliseconds, after the first and thus blow the whole scheme.

I guess I'll have to find out.
Keep us posted...I'm curious.
Avatar of AIBMass

ASKER

Real life experience with DoubleClickKiller.

Setting the interval between the MouseButtonDown events to 1 second is too fast for Form2 to load. Setting it to 3 seconds works fine in this specific regard, but I am concerned that this is way too long for other parts of the application.

I will turn now to some variation of the timers.
I would look at the loading code in Form2.  Can that be threaded with the BackgroundWorker()?...
Avatar of AIBMass

ASKER

I am going with setting a timestamp when the form has been loaded and filled with data and insisting that the button click be more than 250 milliseconds from that time.

This was way too difficult.

It seems like an underlying Windows flaw that a UI event from one Window can show up in another Window.  It just shouldn't be so :(
Well...part of the problem is that all user interaction gets processed in the main UI thread.  If you thread the length record loading work, then the main UI thread can be free to process that second pending click, and consequently discard it.  If all the work remains in the main UI thread and takes longer than one second to load, then the pending messages also sit there for one second waiting to be processed.  If the loading takes even longer then can end up with an un-responsive UI, or a "white out" where the main form being displayed doesn't repaint while the secondary form is still loading.