When I run the following script via CMD.EXE the display of Word is normal i.e. Maximized.
Set oWord = CreateObject("Word.Application")
oWord.Visible = True
oWord.Documents.open(sTempWordFile)
oWord.Run WScript.Arguments.item(0)
oWord.Activate
When I call the same script as Target in a shortcut .LNK file the display is always minimized!
The .LNK file target is: "%OWNERS_CORP_ROOT%\cmd\RunWord.vbs" memos
Using Windows 8.1, Office 2013. Shortcut .LNK file is set to Run 'Maximized'.
How do I make a 'Maximized' display when using the shortcut?
SetForegroundWindow Function
The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user. The system assigns a slightly higher priority to the thread that created the foreground window than it does to other threads.
Syntax
BOOL SetForegroundWindow( HWND hWnd
);
Parameters
hWnd
[in] Handle to the window that should be activated and brought to the foreground.
Return Value
If the window was brought to the foreground, the return value is nonzero.
If the window was not brought to the foreground, the return value is zero.
Remarks
Windows 98/Me: The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.
With this change, an application cannot force a window to the foreground while the user is working with another window. Instead, Foreground and Background Windows will activate the window (see SetActiveWindow) and call the function to notify the user. However, on Microsoft Windows 98 and Windows Millennium Edition (Windows Me), if a nonforeground thread calls SetForegroundWindow and passes the handle of a window that was not created by the calling thread, the window is not flashed on the taskbar. To have SetForegroundWindow behave the same as it did on Windows 95 and Microsoft Windows NT 4.0, change the foreground lock timeout value when the application is installed. This can be done from the setup or installation application with the following function call:
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
This method allows SetForegroundWindow on Windows 98/Windows Me and Windows 2000/Windows XP to behave the same as Windows 95 and Windows NT 4.0, respectively, for all applications. The setup application should warn the user that this is being done so that the user isn't surprised by the changed behavior. On Windows Windows 2000 and Windows XP, the call fails unless the calling thread can change the foreground window, so this must be called from a setup or patch application. For more information, see Foreground and Background Windows.
A process that can set the foreground window can enable another process to set the foreground window by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the ability to set the foreground window the next time the user generates input, unless the input is directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that process is specified.
The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.
Function Information
Minimum DLL Version user32.dll
Header Declared in Winuser.h, include Windows.h
Import library User32.lib
Minimum operating systems Windows 95, Windows NT 3.1
Unicode Implemented as Unicode version.
See Also
Windows Overview, AllowSetForegroundWindow, FlashWindowEx, GetForegroundWindow, LockSetForegroundWindow, SetActiveWindow
Related
I am using a script that:
Launches Thunderbird
Creates a new message
Minimizes the message box
Copies the path to the selected folder
How to activate a minimized Thunderbird message box, knowing its Title?
The code below does not work:
Set WshShell = CreateObject("WScript.Shell")
Set WshExec = WshShell.Exec("""C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe""")
WScript.Sleep 2000
WshShell.SendKeys("^n")
WScript.Sleep 500
PID = WshShell.AppActivate(WshExec.ProcessID)
WshShell.Run("notepad")
If PID Then
WshShell.SendKeys("^k")
Else
MsgBox "Nothing!"
End If
VBS's AppActivate wraps the API's SetForegroundWindow. Your program MUST comply with one of the following rules to set the active window. Note the standard lockout time is 2 seconds - which is where most people get caught. Note VBScript has no user interface so cannot be the foreground window - you have 2 seconds to set windows after your program starts.
From https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setforegroundwindow
SetForegroundWindow
Remarks
The foreground window is the window at the top of the Z order. It is
the window that the user is working with. In a preemptive multitasking
environment, you should generally let the user control which window is
the foreground window.
Windows 98/Me, Windows 2000/XP: The system restricts which processes
can set the foreground window. A process can set the foreground window
only if one of the following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
Windows 2000/XP: No menus are active.
With this change, an application cannot force a window to the
foreground while the user is working with another window. Instead,
SetForegroundWindow will activate the window (see SetActiveWindow) and
call the FlashWindowEx function to notify the user.
Two use-cases:
Enumerate windows and then get the process handle for each window
Enumerate processes and then get the main application window handle for each process
Enumerate windows and then get the process handle for each window
You need these APIs:
win32gui.EnumWindows() to enumerate all top-level windows (that is no child windows aka controls)
win32process.GetWindowThreadProcessId() to get process ID from window handle
win32api.OpenProcess() to get process handle from process ID
Enumerate processes and then get the main application window handle
for each process
You need these APIs:
win32process.EnumProcesses() to enumerate all processes
win32api.GetWindowLong() with argument GWL_STYLE to get window styles and GWL_EXSTYLE to get extended window styles
win32gui.GetParent() to determine unowned windows
By filtering the result of EnumWindows() using GetWindowThreadProcessId() you can get all windows that belong to a given process.
Determining the main window can be tricky as there is no single window style that would designate a window as the main window. After all, an application might have multiple main windows.
Best you could do is to use the same rules that the taskbar uses to determine application windows, because that's what the user perceives as main windows:
The Shell places a button on the taskbar whenever an application
creates an unowned window—that is, a window that does not have a
parent and that has the appropriate extended style bits.
To ensure that the window button is
placed on the taskbar, create an unowned window with the
WS_EX_APPWINDOW extended style. To prevent the window button from
being placed on the taskbar, create the unowned window with the
WS_EX_TOOLWINDOW extended style. As an alternative, you can create a
hidden window and make this hidden window the owner of your visible
window.
Use GetParent() and GetWindowLong() to determine the unowned windows that have the right window styles according to these rules.
I have VSTO addins for Office (Excel / Word / Outlook) 2007 / 2010. Through the use of the NativeWindow the office programs listen for Hotkeys. Upon hotkey recognition a message (WinApi SendMessage) is sent to my own application which then uses the SetForegroundWindow SetForegroundWindow(Hwnd) function to bring Internet Explorer to the front. This works fairly well on most occasions but sometimes it does not. When it does not work the office application is left in front and the Internet Explorer icon is flashing in the task bar.
I am aware that this is by design from Microsoft for the SetForegroundWindow function to stop malicious code.
I do not know exactly why it works sometimes and not others but think it is because the user is using the keyboard to enter the hotkeys and thus the Office application does not want to give up this focus.
My first thought was to simply minimize the Office program but I do not want to do this as some people have multiple screens with Internet Explorer on one and the office application on the other.
When my VSTO addin receives the hotkey signal I would like the office application to relinquish being the foreground or active window, but I do not want it to be minimized.
I know the last paragraph might not be a correct question so maybe more generally as the VSTO addin is working with the Office application process what can I do here so that a call to SetForegroundWindow will work.
Edit: To be clear the only code I am using so far is SetForegroundWindow(Hwnd) where the Hwnd is that of Internet Explorer. As the conditions are now posted I am interested in creating the condition "There is no foreground process"
From the documentation:
A process can set the foreground window only if one of the following conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The process is being debugged.
The foreground process is not a Modern Application or the Start Screen.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user. [Emphasis Mine]
How do you know if you successfully set the foreground window?
If the window was brought to the foreground, the return value is nonzero.
If the window was not brought to the foreground, the return value is zero.
Without any code to go on, there's no way to know which is causing the problem.
I have an issue where the Windows 8 User Account Control (UAC) popup is minimized when I execute a command line helper program that requests admin privileges in its manifest. The UAC popup window just blinks yellow in the Windows taskbar, causing a confusing user experience:
After clicking the taskbar icon, then the UAC alert shows:
In Windows 7, the UAC alert is not minimized but shows in the foreground. Any thoughts on how to fix this in Windows 8?
For reference, my main application runs under user privilege and executes the helper program with ShellExecuteEx. I am setting ShellExecuteEx's TShellExecuteInfo.nShow to SW_SHOW.
MSDN says ".. you must pass a parent HWND with a ShellExecute .." and explains,
The UAC elevation mechanism uses the HWND as part of determining
whether the elevation is a background or foreground elevation. If the
application is determined to be a background application, the
elevation is placed on the taskbar as a blinking button. ..
Be sure to supply your foreground window's handle to ShellExecuteEx.
I need to write application A, which intercepts the WM_ACTIVATE message to a window of application B in order to prevent B from becoming top-most application.
Is it possible to do this without DLL injection (add a hook on that message, process and "neutralize" it with a series of WinAPI calls) ?
I think this is what you're after:
LockSetForegroundWindow
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
Remarks
The system automatically enables calls to SetForegroundWindow if the user presses the ALT key or takes some action that causes the system itself to change the foreground window (for example, clicking a background window).
This function is provided so applications can prevent other applications from making a foreground change that can interrupt its interaction with the user.
Just don't forget to unlock :)
Edit:
Try SetWinEventHook as described here:
Is there Windows system event on active window changed?
Then when the unwanted window comes to the front you can send it to the background.