Fixing mouse double click bug with autohotkey - mouseevent

My mouse is a little old and started annoying me with double click when I just press one click, then I coded this snippet to block clicks that happens to fast, which works:
lastClick := A_TickCount
LButton::
ElapsedTime := A_TickCount - lastClick
If ElapsedTime > 50
send {LButton}
Else
lastClick := A_TickCount
Return
However, now I am unable to drag anything with my mouse.
I'm out of ideas to handle it, I appreciate any ideas. Thanks for your time.

You're performing your event when the left button is pressed down and when it's released, rather than just when it's released. LButton fires off twice.
When you click and hold, your function detects the downclick and sends off an entire click event, including the release. You want the behaviour to change based on when you are clicking the button down versus releasing it.
This post has more information. Here's their solution:
LButton::
If (A_TimeSincePriorHotkey < 100)
Return
Send {LButton Down}
KeyWait LButton ;physical state
Send {LButton Up}
Return
You can adjust the wait time as you like.

Related

VBA loses flow of control when button calls new window using user32 libraries

I am using VBA with user32 libraries to manipulate windows. In the application I am making, when I click on a certain button for which I already have the handle, a new window appropriately pops up. I need to then press a button on that new window. But after the code clicks the first button, the code doesn't move forward anymore.
If I had originally initiated the code by pressing F8 to step through, then I can manually close the new window, manually reopen it, and then continue stepping through my code and it works just fine to finish the program. If I initially pressed F5 to just run the program without ever having stepped through, then I still have to manually close the window and code just gets stuck after opening the new window so no progress is made.
How do I ensure that the program doesnt lose control after the button is clicked and the new window pops up?
'assume the objects are declared already and the functions are correctly imported.
printDialogWindow = FindWindow(vbNullString, "Print")
preferencesButton = findwindowEx(printDialogWindow, 0&, "Button", "P&references")
Call SendMessage(PreferencesButton, BY_CLICK, 0, ByVal 0&)
'code stalls here
printPreferencesWindow = FindWindow(vbNullString,"Printing Preferences")
Ok, so the solution I found in simple terms was to use the Win32 "PostMessage" function instead of the "SendMessage". SendMessage will wait for a response before it returns control back to the calling program. PostMessage puts the message in a queue and then gives control back to the calling program right away. In my case, because there are no other messages in the queue for that window, it processes the message right away, so there are no issues.

Slow Response After Clicking Button in VB.NET

I have created a windows form on a Windows Mobile 6.5 application. This screen has a username and password field and a login menu button. After clicking the button, it takes my click event for the login button 6 or 7 seconds to reach the first line of code (an alert). It takes that long to reach the breakpoint as well.
I've tried:
changing the menu button to a login button
using AddHandler in my formLoad event
...and have still not gotten a fast response. What else could be slowing this down?
This delay seemed to happen the first time any button was clicked on the application. The only way I could get this delay to not occur was to force a dummy button click of the login button on load of the application. The delay causes the application to load a little bit longer, but at least that delay won't occur when the user clicks the button.

how to make a program wait until a button is clicked

How to make a program wait until a button is clicked by the user.
I want to stop my sequence of codes (statements) until a button is clicked by the user.
how can I go this ?
Whatever it is that you want to happen after the button is clicked, just put that code in the handler for the button-click event. To get to that handler, double click on the button in the designer.

Strange behaviour when posting CGEvent to PSN

EDIT - not getting much input on this so here's the skinny. I'm posting keyboard events to a PSN. I then switch to another window, post some more events (this time tat session level) and switch back to the first window. When I start posting to the PSN again, nothing happens. Until I move the mouse or scroll wheel. Why would this be the case and how can I work around it (if not fix it)?
ORIGINAL -
If I set up a loop that posts some keyboard events to a PSN, I find that it works fine except for when first launched. The event only seems to post when i do something with the mouse manually - even just moving it slightly. Here's the details, if they help.
An external application has a list box of text lines, which I am reading by posting copy commands (and checking the pasteboard). Unfortunately this is my only way to get this text.
Sometimes, the application pulls focus away from the list, which I can detect. When this happens, the most reliable way to return focus is by sending a mouse event to click on a text field directly above the list, then send a 'tab' keyboard event to shift the focus onto the list.
So at launch, the loop runs fine, scrolling down the list and copying the text. When focus is shifted away, its is detected fine, and the events are sent to move focus back to the list. But nothing seems to happen. The loop continues detecting that focus has changed, but the events only work once I move the mouse. Or even just use the scroll wheel. Strange.
Once this has happened the first time, it works fine - each time focus moves, the PSN events switch it back without me having to do anything at all.
Here's the code that runs in the loop - verified as working:
//copy to pasteboard - CMD-V
e3 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, true);
CGEventSetFlags(e3, kCGEventFlagMaskCommand);
CGEventPostToPSN(&psn, e3);
CFRelease(e3);
e4 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, false);
CGEventPostToPSN(&psn, e4);
CFRelease(e4);
//move cursor down
e1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)125, true);
CGEventPostToPSN(&psn, e1);
CFRelease(e1);
e2 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)125, false);
CGEventPostToPSN(&psn, e2);
CFRelease(e2);
And here's where I switch focus, also working (except when first required):
//click in text input box - point is derived earlier
e6 = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, 0);
CGEventPostToPSN(&psn, e6);
CFRelease(e6);
e7 = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, point, 0);
CGEventPostToPSN(&psn, e7);
CFRelease(e7);
//press tab key to move to chat log table
CGEventRef e = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)48, true);
//CGEventPost(kCGSessionEventTap, e);
CGEventPostToPSN(&psn, e);
CFRelease(e);
CGEventRef e11 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)48, false);
CGEventPostToPSN(&psn, e11);
CFRelease(e11);
Hey, i know it's not what you want to hear but applescript works much better for this kind of thing - reading textfields by posting copy commands, setting focused by sending click events to nearby items then sending tab events - it really isn't the best way to do it.
The problem with simulating events is that generating them isn't the whole story. They only become 'Events' if the target app interprets them correctly. Do you know if the target app is even a cocoa app?
For example, in your second bit of code you create 4 events. The target app needs to run it's event processing loop, which you don't have much control over, and check for queued events. If it did this it would find a simultaneous mouse down, mouse up, key down, key up. You want it to interpret these simultaenious events as a mouse click and THEN a keypress.. but who is to say it will?
You may be able to get this to work by adding into the mix a combination of flushing event queues, getting the target app to run it's runloop, throw in some pauses between the simulated events, and fiddling with event timestamps - but it probably won't be that reliable.
In Applescript you could get the text of row 3 of a table in another app by
tell application "System Events"
tell process targetAppName
set frontmost to true
tell window named windowTitle
tell table 1
set value of attribute "AXFocused" to true
set txtField to first text field of row 3
return value of txtField
end tell
end tell
end tell
end tell
From a cocoa App you can execute a String as an Applescript, you can call functions in different scripts, pass variables, return values, etc.
Instead of creating the event with a null CGEventSourceRef try creating an input source this way:
CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
Based on this mailing list message, this seems to be the secret for success in posting events with CGEventCreateXXXEvent. A Google search shows that lots of devs are having problems with this, but this is the one success post I've found, and a proper CGEventSourceRef (instead of NULL) seems to be the one difference in this example vs. all the others I've found. It solved my problems with posting keyboard events.

How can I tell if a Balloon tip in the system tray has closed?

I have an application that uses a NotifyIcon in the tray to hide/restore the application, as well as pop up notices to the user of application events. My application has a notification queue, and I use the NotificationIcon.BalloonTipClosed event to determine when to reset the balloon and show the next notification (if there's one in the queue).
This method seems to work great in both usual causes (user lets the balloon close itself when it times out, and user clicks "X" in balloon to force it to close), but there's a third case where BalloonTipClosed doesn't get called:
Notification balloon pops up
While it's visible, user right-clicks on notification icon to bring up context menu, causing the balloon to disappear
The BalloonTipClosed event doesn't get triggered in this instance - I figure it's a bug in the framework (I'm using 2.0), but does anybody have an idea around this? If I don't get this event, my application always thinks there's a balloon visible (I have a boolean that prevents it from displaying multiple balloons at once), and it will never show another icon again, as long as it's running.
This belongs as a comment to Aarons answer, but I am not allowed to comment yet.
If you handle the BalloonTipClicked and MouseClick events on the NotifyIcon (as well as the BalloonTipClosed) then you can capture all the ways the balloon can close. The only thing you have to be aware of is that several scenerios will trigger multiple events, so be sure to code around that (something like isClosed = true, and then reset that when a new balloon is displayed).
In the event handler for the BalloonTipClicked Event, I would check to see if the right mouse button was clicked, and if it was set the boolean to false.
Here's what I ended up doing, though I don't particularly like this solution. I added a second timer to the form and set it for 10 seconds. When a notification pops up (when I pop one), I start the timer, and then in BalloonTipClosed, I stop it. If the timer ticks (meaning that BalloonTipClosed hasn't run yet), I display the next tip manually.
The result is that if it hasn't fired yet, I take care of it. However, I'm open to better solutions if anybody has one.
I think this post from Raymond Chen about balloon notifications may help you:
http://blogs.msdn.com/oldnewthing/archive/2009/05/04/9585032.aspx