Handle double click event for no shape

Started by Hey Ken, April 21, 2016, 01:07:14 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Hey Ken


   Okay, folks, here's another one.

   As I've mentioned before, I'm all about reducing keystrokes, and my target today is the "back" button.  My Visio solutions tend to be intricately cross-hyperlinked, necessitating a lot of back button clicks, so I'd like to try to somehow reduce the effort required to go back.  The question is how.

   My first solution was a right-click action on the page's shapesheet, but that required three steps: right click on the background (pretty easy), hunt for the option (not as easy – requires reading the options), then right click on it (not so easy at all – I occasionally misclick and hit a neighboring right-click option).  The native Visio back button on the toolbar has the same drawbacks.  But why not, I ask myself, just double click on the empty background and call that my back button?  Pretty easy, no hunting necessary, and misclicking becomes virtually impossible.  The question is how.

   The only double click event I could find in Visio is the EventDblClick event on every shape.  But what if there's NO shape?  The page shapesheet has no equivalent cell; and although you can add a hyperlink section, it does not respond to double clicking. 

   One solution I tried was putting one giant, page-sized shape behind everything and using its EventDblClick, but it kept getting in the way and became more trouble than the click-hunt-misclick solutions I already had.

   The best I've come up with so far is to handle a simulated double click using the application's Mouse Down event.  Click it once, and it saves the current time in a static variable.  Click it again, and if it's within a second of the first click, do my back processing.  Here's how:



Private Sub X_MouseDown(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal Y As Double, CancelDefault As Boolean)

Dim Selections As Integer
Static StartTime As Date

Selections = ActiveWindow.Selection.Count
If DateDiff("s", StartTime, Time) < 1 Then
    If Selections = 0 Then   ' you know you're on the background and not on a shape
        DoMyBackProcessing
        End If
    End If
StartTime = Time

End Sub



   Yes, it works; but I was looking for something a little more elegant.  Any suggestions?

   Thanks in advance,

   - Ken


   


Ken V. Krawchuk
Author
No Dogs on Mars - A Starship Story
http://astarshipstory.com

AndyW

Rather than double-click, why not do something shift (or ctrl) and click, that way no messing with timers. It is quite easy to hold a key while clicking.
Live life with an open mind

Hey Ken


   Thanks for the suggestion, Andy.  Sometimes the obvious eludes us.

   So I had to run right home and try it, of course, but soon came up with a minor annoyance.  I was sitting there at my keyboard, elbow on the desk and chin in my hand, my other hand on the mouse, drilling down the hyperlinks.  But when I needed to navigate back up the chain, I had to lift my head, get my elbow off the desk, and reach for the keyboard to hold down the <expletive deleted> ctrl key.  Ugh.

   Still, the idea has merit; just not with the ctrl key.  Instead, I tried using the scroll wheel button as the back button, and that worked well—except when I'd accidentally scroll while clicking the button.  Something that worked better was holding down the left and right buttons simultaneously to trigger the back function, except it's not intuitive.  How many times have you ever done that maneuver?  I can't think of any.

   So that brings me back to the easiest, most intuitive option: double clicking. 

   I've improved the code somewhat: I swapped out DateDiff and put in a GetTickCount API call to get millisecond resolution on the timing, then used the GetDoubleClickTime API call to make sure the double click duration matched the rest of my system.  And the code is working well, even when I'm leaning on my elbow.  At least it working well so far...

   Here's the latest:



Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function GetDoubleClickTime Lib "user32.dll" () As Long

Private Sub X_MouseDown(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal Y As Double, CancelDefault As Boolean)

Static WaitingForSecondClick As Boolean
Static Milliseconds As Long

If ActiveWindow.Selection.Count = 0 Then
    If GetTickCount - Milliseconds < GetDoubleClickTime Then
        If WaitingForSecondClick Then
            DoMyBackProcessing
            WaitingForSecondClick = False
            Milliseconds = 0
        Else
            WaitingForSecondClick = True
            Milliseconds = GetTickCount
            End If
    Else
        WaitingForSecondClick = True
        Milliseconds = GetTickCount
        End If
Else
    WaitingForSecondClick = False
    Milliseconds = 0
    End If

End Sub


   Thanks again,

   - Ken

Ken V. Krawchuk
Author
No Dogs on Mars - A Starship Story
http://astarshipstory.com

Hey Ken


   Seems nothing is simple sometimes.

   Turns out there's an odd glitch in my double click code.  It works fine, except in one case: If I'm on Page 1 and I double click on empty space, it properly goes to Page 2.  BUT... if that exact spot on Page 2 is occupied by a shape with an EventDblClick formula, the event fires even though I didn't click on it.  It seems that Visio buffers the double click from Page 1, changes to Page 2, then processes the double click on Page 2.  Even worse, it looks like there's nothing I can do to stand in between the page change and the EventDblClick firing to intercept the problem.

   At first I thought it might be some effect introduced by my Back processing, but I put together a very simple case (attached) and it still shows the funny behavior. 

   Thoughts?  Suggestions?

   - Ken
Ken V. Krawchuk
Author
No Dogs on Mars - A Starship Story
http://astarshipstory.com

AndyW

Live life with an open mind

AndyW

Seems to work if you send cancelDefault true on the mouseup just before you change the pages
Live life with an open mind

Hey Ken


   That did it, Andy!  Never used the option before; never knew just what it did.  Now I know.  And it's looking solid.  So far, that is...  ;-) 

   It's funny how a couple hours' work was required to figure out how to save so little effort.  But the best part is that going forward it'll save me about a second each time I need to go Back—and I use Back a lot, often a dozen or more at a time, especially with my recently-built huge screenflow.  It all adds up, though.  Call it a minute a day savings, 5 minutes a week, and 4+ hours a year, yielding an expected 100% ROI long before autumn is over—and the project is scheduled to run well into next year.  Nice.  And there are always future projects.  Goes to show once again how laziness can be a virtue.

   Thanks!!!

   - Ken
Ken V. Krawchuk
Author
No Dogs on Mars - A Starship Story
http://astarshipstory.com

Hey Ken

Folks:

   Well, I can tell no one's been using my suggested code for using a double-click to trigger Back button functionality, or else they'd be throwing rocks at me.  To sum up briefly, the code sometimes gets confused—it does a Back when you didn't mean it, or doesn't do a Back when you did.  Annoying, especially when you're doing a demo for top brass.  I've fiddled and fiddled and fiddled with the code for almost a year now, but to no avail.

   So I've given up, bit the bullet, and went to Plan B, which is pressing both mouse buttons at once to trigger my Back functionality.  It's been there for a few weeks now, and has shown absolutely no unpredictable behavior.  It did take a little bit of legerdemain to allow/prevent the right click menus from appearing/not appearing at inappropriate times, but it was easily solved.  And I will admit it took a little time to get used to pressing both buttons at once, but now it's become routine.

   Bottom line: Ignore all the code I mentioned earlier in this thread and use the following.  Rocks no longer necessary.

   - Ken




Dim TwoButtonClickInProgress As Boolean

Private Sub EventWindow_MouseDown(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)

If (Button = 1 And KeyButtonState = 3) _
Or (Button = 2 And KeyButtonState = 3) Then
    DoBackProcessing
    CancelDefault = True
    TwoButtonClickInProgress = True
Else
    TwoButtonClickInProgress = False
    End If

End Sub


Private Sub EventWindow_MouseUp(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)

If (Button = 1 And KeyButtonState = 3) _
Or (Button = 2 And KeyButtonState = 3) Then
    DoBackProcessing
    TwoButtonClickInProgress = True
    CancelDefault = True
Else
    If TwoButtonClickInProgress Then
        CancelDefault = True
        End If
    End If

End Sub



Ken V. Krawchuk
Author
No Dogs on Mars - A Starship Story
http://astarshipstory.com