qwert Posted April 29, 2008 Share Posted April 29, 2008 (edited) I have a GUI that must use the keyboard Enter key as a hotkey. However, whenever the GUI loses focus to another application window, I need to release the Enter key. After studying the problem for a while, the SET and KILL Windows Message Codes appeared to be the solution so I implemented these steps to register them for use: GUIRegisterMsg($WM_SETFOCUS, "On_Get_Focus") GUIRegisterMsg($WM_KILLFOCUS, "On_Lost_Focus") : : Func On_Get_Focus($wParam, $lParam) MsgBox(32, "Got Focus", "", 1) HotKeySet("{ENTER}", "NumKeyEnter") Return 0 EndFunc Func On_Lost_Focus($wParam, $lParam) MsgBox(32, "Lost Focus", "", 1) HotKeySet("{ENTER}") Return 0 EndFunc The problem is that the functions are never executed -- although the GUI does lose focus when I click on any other application window. The same GUI receives keystrokes using a registered $WM_COMMAND and that works just fine. These two functions are registered in the same manner and I don't see a difference. The MSDN2 documentation for these two notifications is very simple and to the point -- but is there an overall better way to accomplish this? I will welcome any advice. Thanks in advance. Edited May 1, 2008 by qwert Link to comment Share on other sites More sharing options...
rasim Posted April 29, 2008 Share Posted April 29, 2008 Work fine for me: #include <GUIConstants.au3> $hGUI = GUICreate("Test GUI", 300, 200) GUIRegisterMsg($WM_SETFOCUS, "On_Get_Focus") GUIRegisterMsg($WM_KILLFOCUS, "On_Lost_Focus") GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE Func On_Get_Focus($wParam, $lParam) ConsoleWrite("Got Focus" & @LF) HotKeySet("{ENTER}", "NumKeyEnter") EndFunc Func On_Lost_Focus($wParam, $lParam) ConsoleWrite("Lost Focus" & @LF) HotKeySet("{ENTER}") EndFunc Func NumKeyEnter() ConsoleWrite("Enter" & @LF) EndFunc Link to comment Share on other sites More sharing options...
qwert Posted April 29, 2008 Author Share Posted April 29, 2008 Thanks for your response. The code you suggested went into an immediate lockup state on my PC, so I modified it as shown below to use message boxes. It then displayed one each of the "got focus" and "lost focus" -- and then locked up and wouldn't respond to the gui_event_close. #include <GUIConstants.au3> $hGUI = GUICreate("Test GUI", 300, 200, 100, 100) GUIRegisterMsg($WM_SETFOCUS, "On_Get_Focus") GUIRegisterMsg($WM_KILLFOCUS, "On_Lost_Focus") GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE Func On_Get_Focus($wParam, $lParam) ; ConsoleWrite("Got Focus" & @LF) MsgBox(32, "Got Focus", "", 1) HotKeySet("{ENTER}", "NumKeyEnter") EndFunc Func On_Lost_Focus($wParam, $lParam) ; ConsoleWrite("Lost Focus" & @LF) MsgBox(32, "Lost Focus", "", 1) HotKeySet("{ENTER}") EndFunc Func NumKeyEnter() ; ConsoleWrite("Enter" & @LF) MsgBox(32, "Key", "Num Key Enter", 1) EndFunc Any idea of why it behaves this way? Link to comment Share on other sites More sharing options...
zorphnog Posted April 29, 2008 Share Posted April 29, 2008 Every time you use a MsgBox you are shifting focus, thus creating an endless loop. Link to comment Share on other sites More sharing options...
qwert Posted April 29, 2008 Author Share Posted April 29, 2008 Every time you use a MsgBox you are shifting focus, thus creating an endless loop.Thanks. That was what I was missing -- and obviously why rasim changed it to a ConsoleWrite. I'll change it back and test -- but how should I monitor the console messages? I've never used them before, but I know the command console isn't involved. Link to comment Share on other sites More sharing options...
ProgAndy Posted April 29, 2008 Share Posted April 29, 2008 If you run the Script from SCITE, you can see the ConsoleOutput in the small edit at the bottom *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
qwert Posted April 29, 2008 Author Share Posted April 29, 2008 If you run the Script from SCITE, you can see the ConsoleOutput in the small edit at the bottomThanks for your help. I've now been able to get rasim's example working. But how can I view the console output from a compiled runtime? That's how I need to test my end result. I'm aware that the documentation advises:Writes data to a stream that text editors can sometimes read.But how can the output be vectored to an open NotePad window, for example, to get the same effect SciTE provides? Link to comment Share on other sites More sharing options...
PsaltyDS Posted April 29, 2008 Share Posted April 29, 2008 But how can the output be vectored to an open NotePad window, for example, to get the same effect SciTE provides?ControlSend("Untitled - Notepad", "", "Edit1", "Line one." & @CRLF & "Line two.") Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
zorphnog Posted April 29, 2008 Share Posted April 29, 2008 Or log it: expandcollapse popup#include <GUIConstants.au3> #include <Date.au3> Global $hLogfile $hGUI = GUICreate("Test GUI", 300, 200, 100, 100) GUIRegisterMsg($WM_SETFOCUS, "On_Get_Focus") GUIRegisterMsg($WM_KILLFOCUS, "On_Lost_Focus") GUISetState() LogOpen() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE LogClose() Func On_Get_Focus($wParam, $lParam) LogWrite("Got Focus") HotKeySet("{ENTER}", "NumKeyEnter") EndFunc Func On_Lost_Focus($wParam, $lParam) LogWrite("Lost Focus") HotKeySet("{ENTER}") EndFunc Func NumKeyEnter() LogWrite("Enter") EndFunc Func LogClose() Local $tCur If $hLogfile <> 0 Then $tCur = _Date_Time_GetSystemTime() FileWriteLine($hLogfile, @CRLF & "=========================================================") FileWriteLine($hLogfile, "Log file ended: " & _Date_Time_SystemTimeToDateTimeStr($tCur)) FileClose($hLogfile) EndIf EndFunc Func LogOpen() Local $tCur $hLogfile = FileOpen(@ScriptDir & "\" & @MON & @MDAY & @YEAR & ".log", 10) If @error = -1 Then $hLogfile = 0 Return Else $tCur = _Date_Time_GetSystemTime() FileWriteLine($hLogfile, "Log file started: " & _Date_Time_SystemTimeToDateTimeStr($tCur)) FileWriteLine($hLogfile, "=========================================================" & @CRLF & @CRLF) EndIf EndFunc Func LogWrite($sMsg) Local $tCur If $hLogfile <> 0 Then $tCur = _Date_Time_GetSystemTime() FileWriteLine($hLogfile, _Date_Time_SystemTimeToTimeStr($tCur) & ": " & $sMsg) EndIf EndFunc Link to comment Share on other sites More sharing options...
qwert Posted April 30, 2008 Author Share Posted April 30, 2008 OK, after another round of testing ... I'm basically back to where I started: I'm not getting focus-related messages.Here's an updated test script:expandcollapse popup#include <GUIConstants.au3> $hGUI = GUICreate("Test GUI", 300, 200, 100, 100) $Button = GUICtrlCreateButton( "a", 20, 40, 40, 34) $Entry = GUICtrlCreateInput( "", 100, 40, 100, 20) GUIRegisterMsg($WM_COMMAND, "On_Command") GUIRegisterMsg($WM_SETFOCUS, "On_Get_Focus") GUIRegisterMsg($WM_KILLFOCUS, "On_Lost_Focus") HotKeySet("{ENTER}", "NumKeyEnter") WinSetOnTop($hGUI, "", 1) GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE Func On_Get_Focus($wParam, $lParam) ControlSend( "Untitled - Notepad", "", "Edit1", "Got Focus" & @LF,1) HotKeySet("{ENTER}", "NumKeyEnter") Return 0 EndFunc Func On_Lost_Focus($wParam, $lParam) ControlSend("Untitled - Notepad", "", "Edit1", "Lost Focus" & @LF,1) HotKeySet("{ENTER}") Return 0 EndFunc Func On_Command($hWnd, $Msg, $wParam, $lParam) ControlSend("Untitled - Notepad", "", "Edit1", "On Command" & @LF,1) Local $iNotifyCode = BitShift($wParam, 16), $iID = BitAnd($wParam, 0x0000FFFF) Return 0 EndFunc Func NumKeyEnter() ControlSend("Untitled - Notepad", "", "Edit1", "Enter Key" & @LF,1) EndFuncWhen I run it, I never receive any Got Focus and Lost Focus messages in NotePad -- but I always receive the On Command and Enter Key messages. When I had tried the simpler script (in my second post), the focus message were received in NotePad.Are there different rules when multiple notification messages are registered? I hope someone can shed some light on this. At this point, I'm baffled. Link to comment Share on other sites More sharing options...
qwert Posted May 1, 2008 Author Share Posted May 1, 2008 OK, after another round of testing ... I'm basically back to where I started: I'm not getting focus-related messages.Anyone willing to give the above (revised) script a try? The Lost Focus notification apparently never executes ... so I feel like I'm back to square one on this whole issue.Thanks for any help. Link to comment Share on other sites More sharing options...
ProgAndy Posted May 1, 2008 Share Posted May 1, 2008 (edited) I don't know, how it usually is done, but this works with a workaround: I use the $NM_OWNERDRAW-Message and check there, if Window is active and if it was Active before. expandcollapse popup#include <GUIConstants.au3> Global $WinNotActive = 1 $hGUI = GUICreate("Test GUI", 300, 200, 100, 100) $Button = GUICtrlCreateButton( "a", 20, 40, 40, 34) $Entry = GUICtrlCreateInput( "", 100, 40, 100, 20) GUIRegisterMsg($WM_COMMAND, "On_Command") GUIRegisterMsg($WM_SETFOCUS, "On_Get_Focus") GUIRegisterMsg($WM_KILLFOCUS, "On_Lost_Focus") GUIRegisterMsg($WM_NOTIFY,"On_Notify") HotKeySet("{ENTER}", "NumKeyEnter") WinSetOnTop($hGUI, "", 1) GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE Func On_Get_Focus($wParam, $lParam) ControlSend( "Unbenannt - Editor", "", "[CLASSNN:Edit1]", "Got Focus" & @LF,1) HotKeySet("{ENTER}", "NumKeyEnter") Return 0 EndFunc Func On_Lost_Focus($wParam, $lParam) ControlSend("Unbenannt - Editor", "", "[CLASSNN:Edit1]", "Lost Focus" & @LF,1) HotKeySet("{ENTER}") Return 0 EndFunc Func On_Command($hWnd, $Msg, $wParam, $lParam) ControlSend("Unbenannt - Editor", "", "[CLASSNN:Edit1]", "On Command" & @LF,1) Local $iNotifyCode = BitShift($wParam, 16), $iID = BitAnd($wParam, 0x0000FFFF) Return 0 EndFunc Func NumKeyEnter() ControlSend("Unbenannt - Editor", "", "[CLASSNN:Edit1]", "Enter Key" & @LF,1) EndFunc Func On_Notify($hWnd, $Msg, $wParam, $lParam) ControlSend("Unbenannt - Editor", "", "[CLASSNN:Edit1]", "Notify" & @LF,1) Local $param = DllStructCreate("long;int;int",$lParam) $nNotifyCode = DllStructGetData($param,3) $nID = DllStructGetData($param,2) $hCtrl = DllStructGetData($param,1) if $nNotifyCode = $NM_CUSTOMDRAW Then Select Case Not WinActive($hWnd) And Not $WinNotActive On_Lost_Focus(-1,-1) $WinNotActive = 1 Case WinActive($hWnd) And $WinNotActive On_Get_Focus(-1,-1) $WinNotActive = 0 EndSelect EndIf ; Proceed the default Autoit3 internal message commands. ; You also can complete let the line out. ; !!! But only 'Return' (without any value) will not proceed ; the default Autoit3-message in the future !!! Return $GUI_RUNDEFMSG EndFunc Edited May 1, 2008 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
qwert Posted May 1, 2008 Author Share Posted May 1, 2008 Thanks very much for the response. After a quick first look, I can't say I exactly understand your suggestion -- but I will work with it in a few hours. I've got to come up with something that's reliable since I have to be able to release the hotkey, or my application certainly won't be "user friendly". Link to comment Share on other sites More sharing options...
Siao Posted May 1, 2008 Share Posted May 1, 2008 What you need is WM_ACTIVATE. "be smart, drink your wine" Link to comment Share on other sites More sharing options...
qwert Posted May 1, 2008 Author Share Posted May 1, 2008 What you need is WM_ACTIVATE.That's more like it! I now get a notification on each and every change of focus. The one remaining problem is that the contents of the parameters being passed is always the same, so I don't know which occurrence is Lost Focus: WM_Activate 0052076A 00000006 WM_Activate 0052076A 00000006 WM_Activate 0052076A 00000006 Here's what I'm using to display the notification's parameters: ControlSend( "Untitled - Notepad", "", "Edit1", "WM_Activate " & Hex($wParam) & " " & Hex($lParam) & @LF,1) Any ideas? Link to comment Share on other sites More sharing options...
Siao Posted May 1, 2008 Share Posted May 1, 2008 The one remaining problem is that the contents of the parameters being passed is always the same, so I don't know which occurrence is Lost Focus: WM_Activate 0052076A 00000006Neither of those tells you of lost focus, if your message functions look like this Func On_Get_Focus($wParam, $lParam) ;<--- RTFM I'm pretty sure we've been here before, with you or someone else, and I'm not about explain it over again. Just have this Func On_WM_ACTIVATE($hWnd, $Msg, $wParam, $lParam) Local $iState = BitAnd($wParam, 0x0000FFFF), $iMinimize = BitShift($wParam, 16) If $iState Then HotKeySet("{ENTER}", "NumKeyEnter") Else HotKeySet("{ENTER}") EndIf EndFunc "be smart, drink your wine" Link to comment Share on other sites More sharing options...
qwert Posted May 1, 2008 Author Share Posted May 1, 2008 Func On_Get_Focus($wParam, $lParam) ;<--- RTFMI'm pretty sure we've been here before, with you or someone else, and I'm not about explain it over again.Actually, I did RTFM and the MSDN2 site told me this:WM_ACTIVATE NotificationThe WM_ACTIVATE message is sent to both the window being activated and the window being deactivated. If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the top-level window being deactivated, then to the window procedure of the top-level window being activated. If the windows use different input queues, the message is sent asynchronously, so the window is activated immediately.Syntax of WM_ACTIVATE WPARAM wParam LPARAM lParam; wParam The low-order word specifies whether the window is being activated or deactivated. This parameter can be one of the following values. The high-order word specifies the minimized state of the window being activated or deactivated. A nonzero value indicates the window is minimized. WA_ACTIVE -- Activated by some method other than a mouse click (for example, by a call to the SetActiveWindow function or by use of the keyboard interface to select the window). WA_CLICKACTIVE -- Activated by a mouse click. WA_INACTIVE -- Deactivated. lParam Handle to the window being activated or deactivated, depending on the value of the wParam parameter. If the low-order word of wParam is WA_INACTIVE, lParam is the handle to the window being activated. If the low-order word of wParam is WA_ACTIVE or WA_CLICKACTIVE, lParam is the handle to the window being deactivated. This handle can be NULL.I certainly don't use notification messages enough to recognize when that when they say "2 parameters" they mean "4 parameters". Examples of the correct results I'm getting back now are:WM_Activate 002207C0 00000006 00000001 00000000WM_Activate 002207C0 00000006 00000000 00000000WM_Activate 002207C0 00000006 00000002 00000000WM_Activate 002207C0 00000006 00000000 00000000WM_Activate 002207C0 00000006 00200001 00000000WM_Activate 002207C0 00000006 00200000 00000000I certainly appreciate the code you provided (but not so much the scolding). Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now