 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Tekl
Joined: 24 Sep 2004 Posts: 813 Location: Germany
|
Posted: Thu Oct 07, 2004 3:06 pm Post subject: ControlGetFocus disables Doubleclick |
|
|
Hello,
I've made a script which shows me a tooltip if a entered Filename in a file-dialog-box is longer than 31 chars.
If this script is running and press Ctrl+O for example in the Notepad, than there it is not possible to open a folder with a double-click.
If I increase the timer to 400 then it works If I klick inbetween this time.
Well, if I replace
ControlGetFocus, control, ahk_id %active_id%
with
control=Edit1
it works, so the doubleclick-stealer seems to be this Command.
| Code: |
#persistent
SetTimer, Warner, 100
return
Warner:
; 31-Zeichen-Warner
WinGet, active_id, ID, A
WinGetClass, f_class, ahk_id %active_id%
If f_class = #32770
{
WinGetActiveTitle, wintitle
WinGetText, wintext, ahk_id %active_id%
if wintext contains Dateiname,Filename,Folder,Verzeichnis,Ordner,Öffnen,Speichern
{
ControlGetFocus, control, ahk_id %active_id%
if control = Edit1
{
ControlGetText, edittext, Edit1, ahk_id %active_id%
SplitPath,edittext,fname
StringLen,editlen,fname
if editlen <> %Tip31%
{
if editlen > 31
{
X = %A_CaretX%
X += 7
Y = %A_CaretY%
Y += 13
ToolTip, Dateiname länger als 31 Zeichen (%editlen%),%X%,%Y%,3
Tip31=%editlen%
SetTimer, Tip31, 1600
return
}
else
{
if editlen = 31
{
X = %A_CaretX%
X += 7
Y = %A_CaretY%
Y += 13
ToolTip, OK,%X%,%Y%,3
Tip31=%editlen%
SetTimer, Tip31, 600
return
}
else
{
Gosub, Tip31
}
}
}
}
}
else
{
Gosub, Tip31
}
}
else
{
Gosub, Tip31
}
return
Tip31:
ToolTip,,,,3
SetTimer,Tip31,off
return
|
Tekl |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Thu Oct 07, 2004 7:36 pm Post subject: |
|
|
Thanks. Unfortunately, I don't see any way to fix it. Incidentally, it also happens under AutoIt3.
I've updated the help file with the following: | Quote: | | If ControlFocus is executed repeatedly at a high frequency (i.e. every 500 ms or faster), it will probably disrupt the user's ability to double-click. There is no known workaround. |
|
|
| Back to top |
|
 |
Tekl
Joined: 24 Sep 2004 Posts: 813 Location: Germany
|
Posted: Wed Dec 22, 2004 11:22 am Post subject: |
|
|
Hi Chris,
is there another way to get the active controlname?
Tekl |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Wed Dec 22, 2004 1:46 pm Post subject: |
|
|
Since the OS does not allow an application to discover the focused control in another application, I can't think of a way (other than a system wide hook, which is currently outside the scope of the project) to do it without internally calling AttachThreadInput(), which is believe is the thing that disrupts double-clicks. Depending on what you want to do, you could use MouseGetPos to find out the control under the mouse cursor.
Assuming that isn't sufficient, you could limit your calls to ControlGetFocus to only when a keystroke or mouseclick occurs. A keystroke event can be detected with the Input command. A mouseclick can be detected by making all mouse buttons into pass-through hotkeys:
~LButton::
~RButton::
~MButton::
; For LButton in particular, give time for a double click to occur beforehand:
Sleep, 500
ControlGetFocus, FocusedControl, A
return |
|
| Back to top |
|
 |
Tekl
Joined: 24 Sep 2004 Posts: 813 Location: Germany
|
Posted: Wed Dec 22, 2004 6:53 pm Post subject: |
|
|
Hi Chris,
well, I only want to know, if the cursor is in an edit1-Control. Maybe I'll try to check the window before I check the focus. Or is there a way to check, if the caret is waiting for input?
Tekl |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Wed Dec 22, 2004 7:35 pm Post subject: |
|
|
| Tekl wrote: | | is there a way to check, if the caret is waiting for input? | I don't think so. I though of suggesting A_CaretX and Y to find out where the caret is, but unfortunately, that calls AttachThreadInput(). So it will probably disrupt double-clicks too (if you find out that it doesn't please let me know).
Don't know if this would help, but you could periodically retrieve the text from the Edit1 and see if it's changed from the previous check. |
|
| Back to top |
|
 |
David Andersen
Joined: 15 Jul 2005 Posts: 85 Location: Denmark
|
Posted: Thu Nov 09, 2006 12:21 pm Post subject: Any progress |
|
|
Hi,
Has there been any progress on this issue. I really need to see which control has focus with a high frequency. I have tried paying around with Chris' solution, but it does not work in my script for several reasons, the main reason being that it sometimes hinders the user from double clicking, which is very irritating.
Does anyone have any clue on a workaround? |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Thu Nov 09, 2006 5:40 pm Post subject: |
|
|
I've added the following example to the documentation. Hopefully it will be enough for what you need:
| Code: | ; This script retrieves the ahk_id (HWND) of the active window's focused control.
; This script requires Windows 98+ or NT 4.0 SP3+.
GuiThreadInfoSize = 48
VarSetCapacity(GuiThreadInfo, GuiThreadInfoSize)
InsertInteger(GuiThreadInfoSize, GuiThreadInfo, 0)
if not DllCall("GetGUIThreadInfo", uint, 0, str, GuiThreadInfo)
{
MsgBox GetGUIThreadInfo() indicated a failure.
return
}
FocusedHWND := ExtractInteger(GuiThreadInfo, 12) ; Retrieve the hwndFocus field from the struct.
MsgBox % "The focused control's ahk_id (HWND) is " . FocusedHWND
; This ID can be used all control commands. For example:
; ControlGetText, OutputVar,, ahk_id %FocusedHWND% |
| Code: |
; SUPPORT FUNCTIONS:
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
return -(0xFFFFFFFF - result + 1)
} |
MSDN docs: GetGUIThreadInfo() |
|
| Back to top |
|
 |
David Andersen
Joined: 15 Jul 2005 Posts: 85 Location: Denmark
|
Posted: Fri Nov 10, 2006 12:52 pm Post subject: |
|
|
Thanks a lot Chris! This really helps me one step on the way.
My problem now is to retreve the name of the control (like "Edit1") from the HWND. This should be fairly trivial, but I cannot use any of the standard functions like ControlGet etc. A search on the forum got me to an article of how to get the HWND from the control name, but not the other way around. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Fri Nov 10, 2006 1:40 pm Post subject: |
|
|
I don't see why you need it. As stated in my post above, this ahk_id number (HWND) can be used all control commands. For example:
ControlGetText, OutputVar,, ahk_id %FocusedHWND% |
|
| Back to top |
|
 |
David Andersen
Joined: 15 Jul 2005 Posts: 85 Location: Denmark
|
Posted: Fri Nov 10, 2006 2:46 pm Post subject: |
|
|
| The reason is that I want to record macros that are reusable even after the user has closed the given window. As far as I could see the HWND id of a control is different each time one opens the given application. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Fri Nov 10, 2006 10:54 pm Post subject: |
|
|
I don't think there's an easy way to do it, so you might have to design the script to dynamically fetch the ahk_id (HWND) every time. If that isn't feasible, you could try the following, though I'm not proficient in it so it might not work (and might require more research):
ControlID := DllCall("GetDlgCtrlID", uint, ControlHWND) ; Given the ahk_id (HWND), this retrieves a unique identifier of the control that might be persistent across sessions.
ControlHWND := DllCall("GetDlgItem", uint, ParentHWND, int, ControlID) ; This goes the opposite direction: given the parent window's ahk_id and the control's controlID, it gets the ControlHWND, which can then be used via ahk_id in all the control commands. |
|
| Back to top |
|
 |
David Andersen
Joined: 15 Jul 2005 Posts: 85 Location: Denmark
|
Posted: Sat Nov 11, 2006 4:34 pm Post subject: |
|
|
Thanks again Chris! The identifier gotten from ControlID := DllCall("GetDlgCtrlID", uint, ControlHWND) is not always unique across sessions. I noticed this by focusing on the "font" control inside Microsoft Word which was different when I had two windows of Word open. The URL edit control in Firefox also has the number 0.
After further researching, I came across the following article:
http://msdn2.microsoft.com/en-us/library/ms996405.aspx
In the section "Recommended Solution for Windows Forms", which should be an article of general interest. It describes using WM_GETCONTROLNAME to get the name given the HWND. I attempted to use WM_GETCONTROLNAME in a send message call, but I cannot find the hex (like 0x111) number for WM_GETCONTROLNAME, and a general search on google did not get me further. Any clues? |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Sun Nov 12, 2006 9:41 am Post subject: |
|
|
First site I looked at when searching WM_GETCONTROLNAME in Google: http://www.pcreview.co.uk/forums/thread-1229324.php
It seems this message can be used only internally. Not even sure it works outside Windows Forms (a .NET technology I believe). _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
David Andersen
Joined: 15 Jul 2005 Posts: 85 Location: Denmark
|
Posted: Sun Nov 26, 2006 12:51 pm Post subject: |
|
|
I have now spent an awful lot of time on this without getting any further. If someone can solve this problem, I will pay them a symbolic 50$ over PayPal.
What I need is this:
The ControlGetFocus to work without hindering the double click, and without taking up unreasonable amounts of resources like CPU and memory. I suggest first retreving the HWND of the control and, somehow retreving the identifier of the control (just like ControlGetFocus) from there.
I hope you can help me out.
Regards,
David |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|