Professor_Bernd Posted May 16, 2021 Share Posted May 16, 2021 Hi guys. This time the problem is quite complex: part of the code is handled in AutoIt scripts, part in VBScript, part are AutoIt commands executed in VBScript via "AutoIt3ExecuteLine", and in addition PSPad is also involved with its internal commands. Therefore it is a bit difficult to post an example script. I hope we can find a solution without an example script. "Gui_1" has an edit, is an AutoIt gui and has PSPad as parent window, so it is displayed modal to PSPad. GUICreate("Gui_1", ... , $GUI_SS_DEFAULT_GUI - $WS_MINIMIZEBOX, -1, $g_hPSPad) If you have executed a script in PSPad, after e.g. 4 seconds the LogWin (Output-Console) of PSPad is automatically hidden. The hiding is an internal PSPad command, which unfortunately takes the focus away from Gui_1. If a user writes to Gui_1's edit at that very moment, the input ends up in PSPad's edit field instead of Gui_1's edit. Although I let Gui_1 reactivate immediately, a few characters can still end up in the PSPad editor. Now I want to block keyboard input (or redirect to Gui_1?) for that brief moment when the active window changes. I tried blocking with BlockInput(), but that only works with admin rights, which my script doesn't have. Is it possible to block or redirect the keyboard input for this short moment, without admin rights? Please consider that for a solution only very short AutoIt commands should be used, because they are called from VBScript via "AutoIt3ExecuteLine". Link to comment Share on other sites More sharing options...
JockoDundee Posted May 16, 2021 Share Posted May 16, 2021 Can’t you use ControlSend instead of send so the focus won’t matter? Have you tried to preemptively hide the PSPad window yourself before starting to send? Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 16, 2021 Author Share Posted May 16, 2021 (edited) Hello JockoDundee. There is no send or other command from outside. PSPad gets the command internally to close the LogWin. PSPad is a closed source Delphi program, so I don't know what is done internally, I can only see that closing the LogWin takes the focus away from the child (Gui_1) and puts it on the parent (PSPad). In other words: - Gui_1 has the focus and the user writes with the keyboard in the edit of Gui_1. <= Edit: Better description (hopefully). - After 4 seconds, the LogWin is automatically closed by PSPad's VBScript. <= Edit: The LogWin is in PSPad, NOT in Gui_1. - The automatic closing takes the focus away from Gui_1 (Child) and puts it on PSPad (Parent) without me being able to do anything about it. - If the user writes to the edit of Gui_1 at this moment, characters can end up in PSPad instead of Gui_1. I then use VBScript (user interface in PSPad) to quickly set the focus back to Gui_1, but unfortunately there is a small delay and a few characters can end up in the PSPad editor. As I said, it's complicated and it's not easy to explain. That's why I really appreciate your attempt to help! 👍 I tried to describe the problem with the needed information without going into too much detail. If further info is needed, I'll be happy to provide it! Edited May 16, 2021 by Professor_Bernd Link to comment Share on other sites More sharing options...
Earthshine Posted May 16, 2021 Share Posted May 16, 2021 (edited) UIAutomation might be able to Manipulate your Delphi controls. That way you could keep it in auto IT Edited May 16, 2021 by Earthshine My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
JockoDundee Posted May 16, 2021 Share Posted May 16, 2021 Ok, thx for the clarification. But my second suggestion still stands, why don’t you, when Gui_1 is created, hide or minimize the pspad logwin window? so maybe then it won’t need to steal the focus. Another thing you can do that might work, as a last resort, is to have a separate process like this: While WinWaitNotActive("[TITLE:Gui_1]") WinActivate("TITLE:Gui_1") WinWaitActive("[TITLE:Gui_1") WEnd though you must setup some mechanism to disable the logic when not needed. you may be able to put this code in the gui_event loop as well, with some mods. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 16, 2021 Author Share Posted May 16, 2021 7 minutes ago, Earthshine said: UIAutomation might be able to Manipulate your Delphi controls. That way you could keep it in auto IT I don't quite understand. Can you explain how that is meant? 10 minutes ago, JockoDundee said: why don’t you, when Gui_1 is created, hide or minimize the pspad logwin window? It is no use to close the LogWin when Gui_1 (RunParamsDialog) is created, because the LogWin will be opened again with every "Run". More details. Gui_1 is specifically "RunParamsDialog", a window where the user can enter parameters. These parameters are passed to the script when the script is run in PSPad ("Run" = F5). Screenshot of the RunParamsDialog Spoiler RunParamsDialog is opened by the user and closed by the user, it runs as long as the user wants. When the user presses F5 for "Run" the script will be executed and the LogWin will be opened each time. I think everyone knows this from SciTE. When the script is finished, the LogWin is closed automatically in PSPad (if the user wants it). 27 minutes ago, JockoDundee said: Another thing you can do that might work, as a last resort, is to have a separate process like this: While WinWaitNotActive("[TITLE:Gui_1]") WinActivate("TITLE:Gui_1") WinWaitActive("[TITLE:Gui_1") WEnd though you must setup some mechanism to disable the logic when not needed. This is not possible, because the user can't write in his script in PSPad, as long as RunParamsDialog is shown. Link to comment Share on other sites More sharing options...
Earthshine Posted May 16, 2021 Share Posted May 16, 2021 When I get back into the office I will verify that PS pad can indeed be manipulated with UIAutomation so that you can do the automation you want to that editor from AutoIt. If that is possible I will post back when I get back into the office Professor_Bernd 1 My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
JockoDundee Posted May 17, 2021 Share Posted May 17, 2021 Ok, here is the POC. Its ugly, but it seems to work. 2 Files to download - RunParams.au3 and RunNotepad.au3 (RunNotepad must be compiled to .exe) 1) RunParams.au3 This is the RunParams mock up. This has the code that you can incorporate in your .au3. Go ahead and run it either in interpretive mode or compiled. When you press F5 it will launch a new Notepad to simulate the PSPad log window (it also kills any notepad window first). Then after 4 secs the focus should change to the Notepad window, although you may not notice it because keystrokes are never lost to it, and in any event the focus will return to the RunParams, if that's what had focus when you pressed F5. 2) RunNotepad.au3/.exe This file exists only to launch Notepad in the background and then wait 4 secs before setting the focus to Notepad. Then it terminates. Here is RunParams.au3 expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> HotkeySet("{F5}", "RunNotePad") Local $hWnd=GUICreate("Run - params dialog", 325, 70) Local $hEdit=GUICtrlCreateEdit("param1 param2", 5, 3, 300, 50, $WS_VSCROLL) GUISetState(@SW_SHOW) SetKeys() GUIRegisterMsg($WM_ACTIVATE, "FocusChange") While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete() Exit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func RunNotePad() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Run("RunNotePad.exe") EndFunc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func FocusChange($hWnd, $iMsg, $wParam, $lParam) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; If $wParam Then SetKeys(True) Else If WinGetHandle("[ACTIVE]")=WinGetHandle("[CLASS:Notepad]") Then WinActivate($hWnd) Else SetKeys(False) EndIf EndIf Return $GUI_RUNDEFMSG EndFunc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func SetKeys($bSet=True) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Local $sFunc For $n=32 To 126 If $bSet Then HotkeySet(Chr($n), "SendToControl") Else HotkeySet(Chr($n)) EndIf Next EndFunc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func SendToControl() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HotkeySet(@HotKeyPressed) ControlSend($hWnd, "", $hEdit, @HotKeyPressed) HotkeySet(@HotKeyPressed,"SendToControl") EndFunc Here is RunNotepad.au3 ProcessClose("Notepad.exe") Run("Notepad.exe", @WorkingDir, @SW_SHOWNOACTIVATE) Sleep(4000) WinActivate("[CLASS:Notepad]") P.S. Its pretty ugly stuff generally, I can't say I'm proud. Professor_Bernd 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 17, 2021 Author Share Posted May 17, 2021 46 minutes ago, JockoDundee said: Ok, here is the POC. Its ugly, but it seems to work. Thank you so much for the effort you put in. 👍 I have tested your code and it seems to work in the replacement environment. I will create a Pau3 test environment where we can test if it works under real conditions. Please be patient, this will take some time. Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 17, 2021 Author Share Posted May 17, 2021 The test version is ready. I have created quick&dirty and it may contain errors. For test it should be enough. The zip contains a test script "Hello world.au3" and the following steps for testing. Spoiler LogWin AutoClose is set to 3 seconds. Steps to test. - Open PSPad. - Load "Hello world.au3", e.g. by drag&drop. - In the right panel double click "Run - parameters" => RunParamsDialog appears. - Click into PSPad editor and press F5 => Script will be executed, MsgBox appears. - Close the MsgBox => Script will be finished => 3 seconds until LogWin AutoClose. - Click into the Edit of RunParamsDialog => Dialog becomes active, Edit has the input focus. - Press any key (e.g. "a") on the keyboard and hold it until the LogWin is closed. - When the 3 seconds are over, the LogWin is closed automatically, PSPad is activated and the editor gets the input focus. => 2 or 3 characters may have ended up in the editor of PSPad. - RunParamsDialog gets the input focus = more characters end up in the edit of RunParamsDialog. . Now I have to leave and when I'm back I'll look for some relevant places in the code and post them in the next post. Download the test version from the DE AutoIt forum. Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 17, 2021 Author Share Posted May 17, 2021 (edited) Here is a listing of the scripts involved and relevant code locations. Spoiler Involved scripts "...\<Pau3>\" is the folder where the PSPad.exe is located. VBScript - "...\<Pau3>\Script\VBScript\AutoIt3_CallTip.vbs" <= NOT relevant, only COM ROT object handling. - "...\<Pau3>\Script\VBScript\AutoIt3_CompRun_LogWin.vbs" <= RELEVANT! AutoIt - "...\<Pau3>\PSPad4Au3\Au3 scripts\CallTipViewer.au3" <= NOT relevant, only COM ROT object handling. - "...\<Pau3>\PSPad4Au3\Au3 scripts\CompilerRunner.au3" <= NOT relevant, COM ROT and Params handling. - "...\<Pau3>\PSPad4Au3\Au3 scripts\RunParamsDialog.au3" <= RELEVANT! Relevant code places - "...\<Pau3>\Script\VBScript\AutoIt3_CompRun_LogWin.vbs" Line 97 - 133: Sub Au3_RunParamsDialog() Nothing specific. Line 450 - 517: Sub LogWin_AutoCloseIfNoError(b_ErrWarnMsgFound, b_DebugMsgFound) Line 498 - 516: =============== If bLogWinCloseDelayed = True And logIsVisible() = True Then ' Delay of 3 seconds before the LogWin is closed. AutoIt3___Base.WaitForMilliSecs(sLogWinAutoCloseDelay * 1000) ' sec to ms If g_bStopLogWinAutoClose = False Then If CompilerRunnerIsRunning() = False Then sLastActiveWinHwnd = AutoIt3___Base.ExecuteAu3Line("WinGetHandle('[active]')", "/WaitForResult") sLastActiveWinTitle = AutoIt3___Base.ExecuteAu3Line("WinGetTitle(HWND('" & sLastActiveWinHwnd & "'))", "/WaitForResult") ' This is the most relevant place: ' -------------------------------- ' This is where the LogWin is closed ("LogWin_Hide()"), which briefly puts the ' input focus on PSPad's editor and allows a few characters to end up there. LogWin_Hide() <= Line 508 If sLastActiveWinTitle = gc_sRunParamsDlgTitle Then ' As soon as possible the focus will be back on the RunParamsDialog. Call AutoIt3___Base.ExecuteAu3Line("WinActivate(HWND('" & sLastActiveWinHwnd & "'))", "") End If End If End If End If ' If bLogWinCloseDelayed = True And logIsVisible() = True I hope I have captured the most important parts. If you have any further questions, I'll be happy to add the info. Edited May 17, 2021 by Professor_Bernd Link to comment Share on other sites More sharing options...
JockoDundee Posted May 17, 2021 Share Posted May 17, 2021 1 hour ago, Professor_Bernd said: 2 or 3 characters may have ended up in the editor of PSPad. I’m not able to get to a PC right this sec, but are you saying that 2 or 3 characters did actually get thru to the PSPad with my mod? Or just might when you test? Or did when you tested before? Or? Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 17, 2021 Author Share Posted May 17, 2021 16 minutes ago, JockoDundee said: but are you saying that 2 or 3 characters did actually get thru to the PSPad with my mod? No, not in your replacement environment. It works fine! The info refers to the test version in the download three posts above. It happens in the real PSPad environment that 2 - 3 characters end up in the editor of PSPad instead of the edit of RunParamsDialog. Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 19, 2021 Author Share Posted May 19, 2021 Any news from you two? Link to comment Share on other sites More sharing options...
Earthshine Posted May 19, 2021 Share Posted May 19, 2021 (edited) I’m buried with work. Sorry we are releasing software Edited May 19, 2021 by Earthshine My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 19, 2021 Author Share Posted May 19, 2021 I'm looking forward to hearing about UIAutomation for PSPad. Maybe you'll have a chance to do that after you guys are done releasing the software. Thanks a lot for the feedback. Link to comment Share on other sites More sharing options...
JockoDundee Posted May 20, 2021 Share Posted May 20, 2021 15 hours ago, Professor_Bernd said: Any news from you two? The English Army has just won the war? Seriously though, is there still a problem with the keystroke leakage after you integrated my code? I think maybe you are saying that my POC worked, but then when you tried to use it in your program, it didn’t? Or are you just looking to initiate a topical discussion? Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 20, 2021 Author Share Posted May 20, 2021 4 hours ago, JockoDundee said: The English Army has just won the war? I'm not familiar with this, what does it mean? The problem persists. Unfortunately, I am not able to integrate your code in VBScript. Can you help me with this? On 5/17/2021 at 3:26 PM, Professor_Bernd said: ' This is where the LogWin is closed ("LogWin_Hide()"), which briefly puts the ' input focus on PSPad's editor and allows a few characters to end up there. LogWin_Hide() <= Line 508 As I wrote a few posts above, this is the relevant place in my VBScript. What do I need to incorporate from your code there? I'm sorry I understand so little, but keep in mind that the above code is in VBScript and I don't know exactly how to integrate your AutoIt code there. Currently there are 2 ways in PSPad's VBScript: - Launching an Au3 script that can contain multiple lines of code. - Execute a single line of AutoIt code via "/AutoIt3ExecuteLine". So far, all my attempts to prevent the leak from keystrokes have failed. My idea is that the leak on keystrokes is caused by the delays, in the interaction of the various elements arises (VBScript, AutoIt, Delphi, WSH, ...). But I don't know how to integrate your code. Link to comment Share on other sites More sharing options...
JockoDundee Posted May 20, 2021 Share Posted May 20, 2021 ok, I’m downloading the .zip, I’ll look for runparamsdialog.au3 and see if I can jam my stuff in there. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Professor_Bernd Posted May 20, 2021 Author Share Posted May 20, 2021 It's not that I wouldn't like to do the integration myself, I just can't get it done. I would love to assist you, so if it's at all possible, let me know what I can do. 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