How to restore a minimized window using AppActivate(ProcessID)
The documentation for AppActivate(ProcessID) states...
The AppActivate function changes the focus to the named application or window but does not affect whether it is maximized or minimized.
Unfortunately, it doesn't then advise how y开发者_C百科ou CAN un-Minimize an application from the task bar when you want it activated.
I can't find something like a SetWindowState on the Process object, so given I have a ProcessID and/or a Process object, what can be done to bring the window into a Normal or Maximized state?
I don't see any way other than interop.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
const UInt32 WM_SYSCOMMAND = 0x0112;
const UInt32 SC_RESTORE = 0xF120;
if (Process.MainWindowHandle != IntPtr.Zero)
SendMessage(Process.MainWindowHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
You could use PostMessage as well, if you don't need to know when it has been restored.
For unknown reasons, it appears that the Process.MainWindowHandle value returned from a VB6 application is not the appropriate value to pass to ShowWindow in order to restore the application from a minimized state.
In the situation where the application caption is not constant, the FindWindow API call is not useful. This code below provides a function that will return the handle to a running application based on the window's caption STARTING with a specified value.
Sample usage : Identifying the IDs...
Dim hwnd As Integer
Dim iProcessID As Integer
iProcessID = Shell("SampleApp.exe", AppWinStyle.NormalFocus)
hwnd = API.GetFirstWindowhandle("Sample App")
... restoring the application...
AppActivate(iProcessID)
If API.IsMinimized(hwnd) Then
API.ShowWindow(hwnd)
End If
... the functional routines ...
Imports System.Runtime.InteropServices
Public Class API
Private Declare Function apiGetTopWindow Lib "user32" Alias "GetTopWindow" (ByVal hwnd As Integer) As Integer
Private Declare Function apiGetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Integer
Private Declare Function apiGetWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Integer, ByVal wCmd As Integer) As Integer
Private Declare Function apiGetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Integer) As Integer
Private Declare Function apiGetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Integer, ByVal lpString As String, ByVal cch As Integer) As Integer
Private Declare Function apiShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As IntPtr, ByVal nCmdShow As Integer) As Integer
Private Declare Function apiIsIconic Lib "user32" Alias "IsIconic" (ByVal hwnd As IntPtr) As Boolean
Private Const GW_HWNDNEXT As Integer = 2
Private Const SW_NORMAL As Integer = 1
Public Shared Function GetFirstWindowHandle(ByVal sStartingWith As String) As Integer
Dim hwnd As Integer
Dim sWindowName As String
Dim iHandle As Integer = 0
hwnd = apiGetTopWindow(apiGetDesktopWindow)
Do While hwnd <> 0
sWindowName = zGetWindowName(hwnd)
If sWindowName.StartsWith(sStartingWith) Then
iHandle = hwnd
Exit Do
End If
hwnd = apiGetWindow(hwnd, GW_HWNDNEXT)
Loop
Return iHandle
End Function
Public Shared Function IsMinimized(ByVal hwnd As Integer) As Boolean
Dim ip As New IntPtr(hwnd)
Return apiIsIconic(ip)
End Function
Public Shared Sub ShowWindow(ByVal hwnd As Integer)
Dim ip As New IntPtr(hwnd)
apiShowWindow(ip, SW_NORMAL)
End Sub
Private Shared Function zGetWindowName(ByVal hWnd As Integer) As String
Dim nBufferLength As Integer
Dim nTextLength As Integer
Dim sName As String
nBufferLength = apiGetWindowTextLength(hWnd) + 4
sName = New String(" "c, nBufferLength)
nTextLength = apiGetWindowText(hWnd, sName, nBufferLength)
sName = sName.Substring(0, nTextLength)
Return sName
End Function
End Class
I used the SendMessage to bring my application to the front as well. The trick to making this work all the time is to minimize and then restore. This way, the app flickers, but always restores to the correct window state of normal or maximized.
SendMessage with P/Invoke
Private Function ActivateApp()
AppActivate(System.Diagnostics.Process.GetCurrentProcess().Id)
'Minimize Window
SendMessage(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle,
WM_SYSCOMMAND, SC_MINIMIZE, CType(0, IntPtr)
'Restore Window
SendMessage(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle,
WM_SYSCOMMAND, SC_RESTORE, CType(0, IntPtr))
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As UInteger, ByVal lParam As IntPtr) As IntPtr
End Function
Const WM_SYSCOMMAND As UInt32 = &H112
Const SC_RESTORE As UInt32 = &HF120
Const SC_MAXIMIZE As UInt32 = &HF030
Const SC_MINIMIZE As UInt32 = &HF020
AppActivate(ProcessID)
SendKeys "{Enter}"
It means you have to press enter key to activate the minimized process
but in case the process is not minimized then the enter key will be sent to the process and affect the process.
精彩评论