![]() |
KnowBrainer Speech Recognition | ![]() |
Topic Title: Bring window to front Topic Summary: A Script helper which forces a named window to the front Created On: 04/05/2021 02:08 PM Status: Post and Reply |
|
|
![]() |
|||
Recent changes to Windows and/or Visual Studio has made it problematical - with both Dragon® and KnowBrainer, if you use "ShellExecute…" or "AppBringUp…" in a DVC or Advanced Scripting script AND the application opens a custom window/Form, the form probably will not display on the screen but it will in the taskbar. ShellExecute "D:\\GetMousePosition\\GetMousePosition\\bin\\Release\\GetMousePosition.exe" & " " & _Arg1, 7 Wait 500
ShellExecute "D:\\BringWindowToFront\\BringWindowToFront\\BringWindowToFront\\bin\\Release\\BringWindowToFront.exe" & " " & "Mouse Coordinates" In this case it forces a window with the title "Mouse Coordinates" (exact spelling is critical but capitalization is not) to come to the front of everything. The functional part of the code is only a few lines (here I have left out some error checking and the helper method "StringContainsPhrase"):
static void Main(string[] args) { string inputParameter = string.Join(" ", args).Trim(); Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist) { if (!String.IsNullOrEmpty(process.MainWindowTitle)) { if (StringContainsPhrase(inputParameter, process.MainWindowTitle)) { NativeMethods.ShowWindowAsync(process.MainWindowHandle, NativeMethods.ShowWindowCommands.SW_SHOWDEFAULT); NativeMethods.ShowWindowAsync(process.MainWindowHandle, NativeMethods.ShowWindowCommands.SW_SHOW); NativeMethods.SetForegroundWindow(process.MainWindowHandle); } } } } The complete Visual Studio 2019 solution is attached.
------------------------- -Edgar |
|||
|
|||
![]() |
|||
Tiny improvement - allow multiple window titles… Only the Main method has changed:
static void Main(string[] args) { if (args.Length == 0) { MessageBox.Show("You must supply a window title", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string inputParameter = string.Join(" ", args).Trim(); string[] titles = inputParameter.Split(';'); List<string> windowTitles = new List<string>(); foreach (string phrase in titles) windowTitles.Add(phrase.Trim()); foreach (string phrase in windowTitles)//DEBUG efm5 2021 04 5 testing MessageBox.Show(phrase, "DEBUG TITLE", MessageBoxButtons.OK, MessageBoxIcon.Error);
Process[] processlist = Process.GetProcesses(); foreach (Process process in processlist) { if (!String.IsNullOrEmpty(process.MainWindowTitle)) { foreach (string phrase in windowTitles){ if (StringContainsPhrase(phrase, process.MainWindowTitle)) { NativeMethods.ShowWindowAsync(process.MainWindowHandle, NativeMethods.ShowWindowCommands.SW_SHOWDEFAULT); NativeMethods.ShowWindowAsync(process.MainWindowHandle, NativeMethods.ShowWindowCommands.SW_SHOW); NativeMethods.SetForegroundWindow(process.MainWindowHandle); } } } } } WARNING - although it works reliably every time on my system, my beta tester says it only works about half the time on theirs! ------------------------- -Edgar |
|||
|
|||
![]() |
|||
Oh yeah, you use a semicolon to separate the window titles: ShellExecute "D:\\GetMousePosition\\GetMousePosition\\bin\\Release\\GetMousePosition.exe" & " " & _Arg1, 7 Wait 500
ShellExecute "D:\\BringWindowToFront\\BringWindowToFront\\bin\\Release\\BringWindowToFront.exe" & " " & "Mouse Coordinates; Preferences" I checked the syntax for "ShellExecute" and am wondering if that trailing ", 7" might be causing grief. ------------------------- -Edgar |
|||
|
|||
![]() |
|||
It turns out that it looks like my beta tester was using the code after having modified it and trying to use it for something for which it was not intended. ------------------------- -Edgar |
|||
|
|||
![]() |
|||
Hi Edgar, that was interesting! I've never seen ShowWindowAsync before. Does it bring the window to the front AND make it the active foreground window that gets keyboard input, etc? It seems like a really nice way to bring windows to the foreground even when your app didn't spawn the windows in the first place. Thank you for posting this example!
------------------------- Win10/11/x64, AMD Ryzen 7 3700X/3950X, 64/128GB RAM, Dragon 15.3, SP 7 Standard, SpeechStart, Office 365, KB 2017, Dragon Capture, Samson Meteor USB Desk Mic, Amazon YUWAKAYI headset, Klim and JUKSTG earbuds with microphones, 3 BenQ 2560x1440 monitors, Microsoft Sculpt Keyboard and fat mouse |
|||
|
|||
![]() |
|||
That is my understanding. I think that there is a similar ShowWindow library function (no Asynchronous) but I am not sure what the differences are. From my experiences it looks like SetForegroundWindow can give a window focus but does not always make it display on the desktop; ShowWindowAsync seems to (almost?) always make it show on the desktop and, from my experience it always gets focus too. ------------------------- -Edgar |
|||
|
|||
![]() |
|||
Well, I can vouch for the fact that calling ShowWindow from some random non-foreground piece of code rarely if ever works reliably. Windows has rules against doing that. But it looks like you have figured out a clever way of just sending a message to tell the window to take over the foreground itself. I'll have to try it out!
------------------------- Win10/11/x64, AMD Ryzen 7 3700X/3950X, 64/128GB RAM, Dragon 15.3, SP 7 Standard, SpeechStart, Office 365, KB 2017, Dragon Capture, Samson Meteor USB Desk Mic, Amazon YUWAKAYI headset, Klim and JUKSTG earbuds with microphones, 3 BenQ 2560x1440 monitors, Microsoft Sculpt Keyboard and fat mouse |
|||
|
|||
![]() |
|||
|
|||
|
|||
![]() |
|||
I hope I haven't inadvertently created a problem. Whenever I use ShellExecute to send stuff to an AHK program, I use "6" at the end ("minimized window; not active") because I don't need to see anything (and I have suggested such a thing over this forum often). Naturally, in a DVC (or DAS) that works on a window, I would use the proper windowStyle constant for the situation. -------------------------
|
|||
|
|||
![]() |
|||
Hi Edgar, I'm with PG on the 6,7 thing. I was probably the "someone on the forum" who suggested using 7 was the right thing to do for times when I didn't want to see a DOS console window pop up when I ran a DOS exe file (your StatementConstructor, as I recall). As far as I could tell, there was no difference between 6 and 7. PG uses 6, and ended up with using 7 because it was the last one I tried and easiest to remember. I don't recall seeing the 10 before; I've certainly never tried it.
------------------------- Win10/11/x64, AMD Ryzen 7 3700X/3950X, 64/128GB RAM, Dragon 15.3, SP 7 Standard, SpeechStart, Office 365, KB 2017, Dragon Capture, Samson Meteor USB Desk Mic, Amazon YUWAKAYI headset, Klim and JUKSTG earbuds with microphones, 3 BenQ 2560x1440 monitors, Microsoft Sculpt Keyboard and fat mouse |
|||
|
|||
![]() |
|||
I see that the DragonĀ® documentation in the Windows documentation (which I quoted) do not exactly agree. DragonĀ® says:
windowStyle Controls how the window appears when you activate the application. Must be one of the following: 1, 5, or 9 default window size; active (default) 2 minimized window; active 3 maximized window; active 4 or 8 default window size; not active 6 or 7 minimized window; not active but that may no longer be true with the new Basic in 15.61. ------------------------- -Edgar |
|||
|
|||
![]() |
|||
fwiw, here is Mark's vocola extension file for doing window activation
https://github.com/mdbridge/bit-bucket/blob/c55b19563b11766350726f346b29ac61bcdfc266/voice/Vocola_development/unofficial/vocola_ext_window_switching.py#L226 Window.Go is great cause you can use regex. But win32gui.SetForegroundWindow is annoyingly unreliable (blinking app in taskbar but no activation) Most reliable thing I've found is to "Ctrl+click" the taskbar app. I have scripts to activate apps that way, never fails. After that, the SetForegroundWindow for that app can also work reliably in my experience. |
|||
|
|||
![]() |
|||
-------------------------
|
|||
|
|||
![]() |
|||
I prefer AutoHotkey for bringing windows to the foreground. Described on https://qh.antenna.nl/unimacro/features/autohotkey/index.html, and used a lot in Unimacro and Vocola.
The clue is, you have to write a tiny script with the handle of the window you want to bring into the foreground, and run that script with autohotkey.exe. I use it also the bring for example the Messages window of Natlink macros to the foreground, by the script with contents: ``` SetTitleMatchMode, 1 WinActivate Messages from ``` I bit of setup work, but worth the trouble IMHO, Quintijn |
|||
|
|||
![]() |
|||
Do you by chance have a link to the deleted comments in that Microsoft post that show you how to override the "AllowForegroundWindow"?
![]() "Update (02/21): Deleted all comments that showed ways of circumventing the rules" Quintijin, Does autohotkey work completely reliably for you? I always hesitate to add yet another layer of technology to my stack... I used to use autohotkey, but I made the decision a while back to try to stick to purely Vocola and Python extensions if possible. (Although I do have to use the occasional .bat and .vbs, but since those come with Windows preinstalled they don't require any extra set up) |
|||
|
|||
![]() |
|||
"Update (02/21): Deleted all comments that showed ways of circumventing the rules" No, and if I had, I wouldn't share them. I have had my fill fighting with SetForegroundWindow and trying to solve it with AllowForegroundWindow, to no avail. But then I read on and found Raymond showing a way that works, without circumventing the rules. As far as AutoHotKey, which I have never used and am not considering, doesn't it also fall back on the Win32 API after all? -------------------------
|
|||
|
|||
![]() |
|||
RW, I read Chen's paper long ago, plus many others. If there was something in there that showed the way, I must have missed it. I even tracked down and watched his conference presentation on Windows and foreground and window owners and parents and a chunk of code that was supposed to "pick the right child window" out of a hierarchy of open windows. Despite tons of study, I never got anything out of his window-climbing code. I even interacted with him and he pointed me toward Microsoft's UI Automation technology. Not much help. If you know how (within the rules) to bring an app window to the foreground from a background thread that is not the foreground thread that has love to give away, I'm sure many people would like to know...
------------------------- Win10/11/x64, AMD Ryzen 7 3700X/3950X, 64/128GB RAM, Dragon 15.3, SP 7 Standard, SpeechStart, Office 365, KB 2017, Dragon Capture, Samson Meteor USB Desk Mic, Amazon YUWAKAYI headset, Klim and JUKSTG earbuds with microphones, 3 BenQ 2560x1440 monitors, Microsoft Sculpt Keyboard and fat mouse |
|||
|
|||
![]() |
|||
Oh dear, Kevin. I would have been surprised if Raymond had given you a straightforward answer along the lines of "just give me the code to copy and paste", he is certainly a lot more funny than that. However, his blog also has a superbe search function, and if you copy and paste "foreground activation love" into it, and press enter, you might find it. Probably at the top of the list. -------------------------
|
|||
|
|||
![]() |
|||
Hi RW, I have had his paper, and his blog, and N comments about that article, and so on, for years. If you mean that the solution is at the top of his love article, I'll have another look at it. His best answer, given directly to me when I asked him directly about my voice application issue, was to consider the UIA (UI automation) interface. Ugh. That wasn't helpful at all. Oh well.
------------------------- Win10/11/x64, AMD Ryzen 7 3700X/3950X, 64/128GB RAM, Dragon 15.3, SP 7 Standard, SpeechStart, Office 365, KB 2017, Dragon Capture, Samson Meteor USB Desk Mic, Amazon YUWAKAYI headset, Klim and JUKSTG earbuds with microphones, 3 BenQ 2560x1440 monitors, Microsoft Sculpt Keyboard and fat mouse |
|||
|
|||
![]() |
|||
When I read his post, it seems like he pretty much says there will always be a case when you can't do it, unless I misunderstand what he says or unless he's joking and being snarky:
In fact from what he says I'm surprised that it ever works at all. Given that we are running this from some background python process, presumably inside of dragons process space(?), A process that rarely if at all has the focus, how would it ever work?
Anyway searching around I found some stack overflow items but they come with warnings among other things.
I can of course understand the reason the OS is structured this way, but it really sucks for accessible applications as opposed to just malevolent applications...
In any case I will probably try some of those stack overflow suggestions at some stage, but my current hack seems to work well enough. |
|||
|
|||
FuseTalk Standard Edition v4.0 - © 1999-2022 FuseTalk™ Inc. All rights reserved.