Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
Hi,
Switch To Last Application command restores the last NON-minimized window. How do I restore the last minimized window? This is an essential function, but looks like it takes some scripting which is beyond my ability. Can someone help?
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
It seems sp.LastApplication() does not have the same functionality as ALT+TAB, maybe it monitors only non-minimized windows stack. After minimizing a window, the focus shifts to second last window and from there sp.LastApplication() takes us to third last active window (ignores the second last active window since we minimized it ourselves) but ALT+TAB takes us back to minimized original window. Try replacing the change application gesture code from: to: Code:sp.SendModifiedVKeys([vk.LMENU], [vk.TAB]); //LMENU stands for ALT here
This will send ALT+TAB key combination instead of invoking sp.LastApplication() function and should solve the problem.
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
oh I just realized that you were talking about step and not script when you mentioned Switch To Last Application command. In your gesture you should see two sections right below the Use secondary stroke button and Active options.. Right now you are using Steps, you should see the Switch To Last Application command(step) listed there, right click on it and delete it. Then move to Script section and you will see an empty coding area, paste Code:sp.SendModifiedVKeys([vk.LMENU], [vk.TAB]); //LMENU stands for ALT here
in that area and then Apply the changes. Now that gesture is using script instead of steps, this gives you more control over the gesture, just like in this case we input a custom combination of keys. Also above the coding area you will see options such as record, insert hotkey, and so on. If you press on insert hotkey option it will open a small window where you can press any keys and it will insert the code for that in the cursor location of the coding area. That is how the above code for ALT+TAB was generated. Hope this helped.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
Quote:maybe it monitors only non-minimized windows stack Yes, it just calls EnumWindows which enumerates windows in Z-order from front to back - minimized windows go to the bottom of the window stack.
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
randomConstant, thank you for the detailed reply. Did as you said. Unfortunately in Windows 8.1 (possibly in Windows 10 too) simulating ALT+TAB won't work. So is there a way to do it without using ALT+TAB? Like committing to memory the last active window (the one just minimized) and then restoring it. Edited by user Sunday, May 8, 2022 3:09:11 PM(UTC)
| Reason: Not specified
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
I don't know the exact method but you should be able to bring an application to the foreground by filtering applications using title or process ID etc. But, ALT+TAB should work. I tested mine on Windows 10 and it works. But maybe that LMENU key in the code does not correspond to ALT key on your machine. Code:sp.SendModifiedVKeys([vk.LMENU], [vk.TAB]);
I'm talking about vk.LMENU in this code. Try to insert a hotkey in the code: - Make a gesture
- Go to its script area
- Press insert hotkey option from the options shown at the top of script area
- Press ALT+TAB and then click on OK
- It should insert a line very similar to the code above, maybe replacing vk.LMENU with the code for your ALT key.
- Apply settings and try the gesture.
The reason I suggest this method over keeping track of applications manually is because this is how it is intended to be used and it puts far less pressure on memory(resources) and is very simple. Plus you need to use ALT+TAB, ALT+ESC, SHIFT+TAB etc when making gestures to navigate applications, windows, tabs etc anyways. If possible, please post a screen shot of the script and any errors. S+ should work fine on Windows 8.1.
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
LMENU is fine, the script I used is exactly as you showed.
There are a number of ways to get around the ALT+TAB issue that can be achieved with the Autohotkey program, but none of them is 100% reliable (in most instances they work, but sometimes they fail to work properly for unknown reasons). So I thought that S+ might have either some built-in way of calling up a minimized window or it could be done by some clever scripting using Windows' commands (Windows messages). But it looks like this seemingly simple task is really hard to do without simulating ALT+TAB.
One way of getting around is by calling up Window Switcher directly. It works fine but the problem is Window Switcher gets in your face each time and I found no way to make it invisible (transparent, minimized, off the screen, etc).
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
This should restore the most recent minimized window. Code:// finds the first minimized window, restores it, and exits the loop
var allWindows = sp.AllApplications();
for(const w of allWindows) {
//StrokesPlus.Console.Log(w.Title);
if(w.Minimized) {
w.Restore();
break;
}
}
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
Rob, your script works in some cases, doesn't work in other cases. By "doesn't work" I mean it restores some other window, not the immediately minimized one. It seems to always work correctly when a window is minimized by clicking on the taskbar, but not when minimized by S+ gesture or by clicking in the top right corner icon. It never works with a Telegram window, even if it's minimized by clicking on the taskbar. Weird, huh?
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
If you're always minimizing via S+ gesture or hotkey, then it would be pretty simple since S+ is able to know which one you did last. Minimize Action:Code:action.Window.Minimize();
// Store the window that was just minimized
sp.StoreObject("LastMinimized", action.Window);
In whatever script you want to restore the last window minimized by S+ action:Code:// In a try/catch in case there is none stored, it fails silently
try {
// Restore the last minimized window
sp.GetStoredObject("LastMinimized").Restore();
} catch {}
Edited by user Monday, May 9, 2022 10:47:20 PM(UTC)
| Reason: Not specified
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
That works great! Would it be possible to make it so that instead of failing silently it would do what Switch To Last Application does? I assume I need to add the respective code to "catch {}", but I don't know the code for Switch To Last Application.
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
Yes you can. Try this code in the catch block:
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
That's what I did, but it doesn't work: Code:try {
// Restore the last minimized window
sp.GetStoredObject("LastMinimized").Restore();
} catch {sp.LastApplication();}
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
Replace the second script with this: Code:var lastMin = sp.GetStoredObject("LastMinimized");
// See if the object has the IsValid method defined. If there's no stored object
// in S+, it will return an empty object which won't have this method
var lastMinValid = lastMin.IsValid !== undefined
// If the object did have IsValid, let's call IsValid() to see if the window still exists
if(lastMinValid) {
lastMinValid = lastMin.IsValid();
}
// If the IsValid method existed and the window is valid
if(lastMinValid) {
// Restore the last minimized window
lastMin.Restore();
// Delete the stored window from S+ memory
sp.DeleteStoredObject("LastMinimized");
} else {
// Otherwise, use the last app method
sp.LastApplication();
}
Edited by user Tuesday, May 10, 2022 10:45:36 AM(UTC)
| Reason: Not specified
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
The catch block will only execute when there is an error in the try block.
The try block is restoring a minimized window, there are a few cases where this might fail, such as when the Windows first starts and no window has been minimized yet (meaning minimize gesture was not executed from S+). Or maybe when a window is minimized, then closed completely.
In those cases catch block will execute and the application should be switched to the last non minimized active window.
I'm not sure what you are trying to achieve here, are you using the same gesture for switching between minimized and non minimized windows?
Ideally, I imagine you'd want a single gesture that forgets about the minimized status of an app and just restores the windows almost like ALT+TAB would.
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
Rob, I'm afraid it doesn't work quite like I need it to.
As randomConstant says, I am trying to use the same gesture for minimized and non-minimzed windows. In other words, I need to activate (bring forward, restore) the last active window. By the last active window I mean:
1) a window I just minimized (mostly with S+). It may not necessarily be an active window when it's minimized (I often minimize inactive windows and I am not sure whether a window is made active by the minimization process.)
2) a window that was made active by me (because I opened it, clicked within it, clicked on the taskbar to restore it, was typing in it, etc) or that became active by itself because some other window was closed or minimized
So it probably is, as randomConstant says, what ALT+TAB does.
Let me know if it's too much trouble and I'll do with what you already provided me with.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
Ah okay, then ALT+Tab is your best bet. Code:sp.SendModifiedVKeys([vk.LMENU], [vk.TAB]);
It works fine for me. Are you running S+ in portable mode or from the installer?
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
Running from installed. Windows 8.1 doesn't allow simulating ALT+TAB, that's the problem.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
This might work, though it won't recognize when S+ is the foreground window for internal reasons. Once you've switched windows at least once, it should keep track of the last window. But I'm sure it may have some other odd issues, hopefully it works okay. Global Actions > Window Events > Foreground Window ChangeCode:try {
sp.StoreObject("LastWindow", sp.GetStoredObject("CurrentWindow"));
sp.StoreObject("CurrentWindow", sp.ForegroundWindow());
} catch {}
Action to switch to last window:Code:var lastWindow = sp.GetStoredObject("LastWindow");
// See if the object has the IsValid method defined. If there's no stored object
// in S+, it will return an empty object which won't have this method
var lastWindowValid = lastWindow.IsValid !== undefined
// If the object did have IsValid, let's call IsValid() to see if the window still exists
if(lastWindowValid) {
lastWindowValid = lastWindow.IsValid();
}
// If the IsValid method existed and the window is valid
if(lastWindowValid) {
// Restore the last minimized window
lastWindow.Activate();
} else {
// Otherwise, use the last app method
sp.LastApplication();
}
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
First it didn't work properly, then, after a few minutes it started to work. But it does have some odd issues: when I open a new window (say of Firefox) and then I call this action, instead of activating the last active window there appears a short title bar and a Firefox icon on the taskbar. The title bar is movable and can be closed by right-clicking on the taskbar icon. In another instance the right-click taskbar menu appeared that I cannot close. But apart from the new window issue it seems to work. Will test some more.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
Yeah, at the end of the day, handling windows can be tricky as some apps have weird hidden windows that the default logic doesn't see as any different that another window, so you'd have to add further logic.
Most of the pieces are here throughout this thread, but you might need to have some special handling for certain windows.
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
Originally Posted by: Omonym  Running from installed. Windows 8.1 doesn't allow simulating ALT+TAB, that's the problem. Rob can you please confirm if S+ is compatible with Windows 8.1? I always thought it was. Also Omonym please try some of the other ways to simulate ALT+TAB as well such as: Code:sp.SendVKeyDown(vk.LMENU);
sp.Sleep(10);
sp.SendVKeyDown(vk.TAB);
sp.SendVKeyUp(vk.TAB);
sp.SendVKeyUp(vk.LMENU);
OR Code:sp.SendAltDown();
sp.Sleep(10);
sp.SendKeys("{TAB}");
sp.SendAltUp();
Hopefully some of the methods work.
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
randomConstant, no way. I wonder why it's so difficult to replicate the internal algorithm of ALT+TAB. Looks like even experts don't know its internal workings?
|
|
|
|
Rank: Advanced Member
Groups: Translators, Approved Joined: 7/17/2021(UTC) Posts: 130
Thanks: 35 times Was thanked: 17 time(s) in 14 post(s)
|
That's why I asked the expert (Rob) It should be possible though, maybe I'll spin up a Windows 8.1 virtual machine on the weekend and check for myself. I just can't believe something as basic as a key combination wouldn't work. Especially if AHK worked.
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
AHK can't simulate ALT+TAB either. Various AHK scripts work more or less, probably 75% of time. So far the best performance is by the latest script Rob provided, it works probably 95% of time, which is great!
So far I have been unable to explain why it doesn't work in the remaining 5%. Definitely doesn't work (or produces weird artefacts) when used immediately after a new window is opened (probably when opening, Windows produces some invisible window which then gets called up by the script). But that's a minor issue.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
Try using this for the Foreground Window Change script. Code:try {
var currentWindow = sp.ForegroundWindow();
if(currentWindow.Enabled
&& currentWindow.Visible
&& !currentWindow.IsCloaked
&& (
(!currentWindow.IsDescendantOf(currentWindow.Parent)
&& (
(!currentWindow.Style.HasFlag(WindowStyleFlags.POPUP) || currentWindow.ExtendedStyle.HasFlag(WindowExStyleFlags.NOREDIRECTIONBITMAP))
&&
!currentWindow.ExtendedStyle.HasFlag(WindowExStyleFlags.TOPMOST)
)
&& !currentWindow.Rectangle.IsEmpty
&& !currentWindow.Style.HasFlag(WindowStyleFlags.CHILDWINDOW)
&& currentWindow.Title.length > 0
&& !currentWindow.ExtendedStyle.HasFlag(WindowExStyleFlags.TOOLWINDOW)
)
||
(
currentWindow.Style.HasFlag(WindowStyleFlags.VISIBLE)
&&
currentWindow.ExtendedStyle.HasFlag(WindowExStyleFlags.APPWINDOW)
)
)
){
sp.StoreObject("LastWindow", sp.GetStoredObject("CurrentWindow"));
sp.StoreObject("CurrentWindow", currentWindow);
}
} catch {}
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
First it called up the last but one active window (not the last one) and then didn't react to the next strokes. Other time it called up the last active window and again stopped doing anything.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
Oh well. Time to install Windows 10 or 11! :P
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
I will be fine with what you provided me with! Thank you!
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
I tried to get Alt+Tab to work by directly calling Window Switcher. I did it in AHK, but it would be better if I had it in S+ instead. Сan you translate it into S+ script ? I tried to do it with different versions of Run in S+, but couldn't even get it to start Window Switcher.
Run "C:\Users\Default\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\Window Switcher" WinWait ahk_class TaskSwitcherWnd ControlSend,,{Enter},ahk_class TaskSwitcherWnd
In AHK I tried to run it minimized or hidden but Window Switcher doesn't obey these commands, so I made it transparent (or off the screen). If it's difficult to do this in S+, this part will then stay in AHK.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
I was able to get this to work, with some tweaks to the delay. I also had to change to using the title "Task View", since the class name isn't the same on Windows 11 Code:sp.Run('C:\\Users\\Default\\AppData\\Roaming\\Microsoft\\Internet Explorer\\Quick Launch\\Window Switcher.lnk');
sp.Sleep(500); //I had to bump this up until the timing was right
var taskSwitcherWindow = sp.WindowFromClassOrTitle("","Task View");
//var taskSwitcherWindow = sp.WindowFromClassOrTitle("TaskSwitcherWnd", ""); //This might work for using class name
if(taskSwitcherWindow.IsValid()) {
sp.SendVKey(vk.RIGHT);
sp.SendVKey(vk.RETURN);
}
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
It says
Scripting Engine Failure
Script execution failed.
TypeError: Cannot read property 'IsValid' of null at Script [10]:7:23 -> if(taskSwitcherWindow.IsValid()) {
OK
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
And I have a question related to the ALT+TAB problem I have. If I have “Always Activate Window Where Gesture Began” checked, then the ALT+TAB script doesn’t work: suppose I need to restore the just minimized Window1, currently active is Window2 and I do the restore gesture over inactive Window3. The gesture thus activates Window3 and makes Window2 the one to be restored (as the last active window), failing to restore Windows1.
I then clear the check from “Always Activate Window Where Gesture Began”. Now the question is this: can I still manipulate an INactive window by making a gesture over it (without making it active, as per the setting) or is it impossible in principle? I know I can minimize an inactive window, but I can’t navigate File Explorer in this way: if I have two File Explorer windows, the navigation will occur in the active window even though I do the gesture over the inactive one.
|
|
|
|
Rank: Administration
Groups: Translators, Members, Administrators Joined: 1/11/2018(UTC) Posts: 1,294  Location: Tampa, FL Thanks: 28 times Was thanked: 404 time(s) in 349 post(s)
|
You can manually add this to the top of scripts where you want it to activate the window below the mouse. Code:action.Window.Activate();
But if you essentially always want to activate the window except for this one action, you can go to Global Actions > Settings > Before Action, select Custom, and add this script: Code:if(action.ActionName != "Name of Alt+Tab Action Here") // <- Change this text
{
action.Window.Activate();
}
Then for each Application defined in S+, go to the Before/After Automation tab and select Inherit from Global Actions. This way all actions for all apps and global will execute that same script before any action's defined Steps or Script, unless the name of the action matches the name in the script above.
|
|
|
|
Rank: Member
Groups: Approved
Joined: 10/31/2021(UTC) Posts: 19 
|
All right, thanks a lot, Rob!
|
|
|
|
Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.
Important Information:
The StrokesPlus.net Forum uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close