Minimizing windows using VBA

Becks
2StarLounger
Posts: 196
Joined: 31 Mar 2011, 03:41
Location: Perth, Western Australia

Re: Minimizing windows using VBA

Post by Becks »

Sorry, you're correct - that version waits for the process to be completed before returning. The Option Base 0 is not required for the Shell procedure so they can be placed in the same module. I don't know whether I have to release the process handle or not if the launched application is to remain open. When using "notepad.exe" as a test application, the procedure appears to behave the same when the CloseHandle statement is commented out

Code: Select all

Public Sub ShellAndWaitTillRunning(AppCmdLine As String)
Dim NameOfProc As PROCESS_INFORMATION
Dim NameStart As STARTUPINFO
Dim rC As Long

    NameStart.cb = Len(NameStart)
    rC = CreateProcessA(0&, AppCmdLine, 0&, 0&, 1&, _
        NORMAL_PRIORITY_CLASS, 0&, 0&, NameStart, NameOfProc)
    'wait 10 milliseconds
    rC = WaitForSingleObject(NameOfProc.hProcess, 10)
    rC = CloseHandle(NameOfProc.hProcess)
    'for test purposes
    'myAppActivate "Excel"
    'MsgBox "done"
End Sub

Kevin

User avatar
Peter Kinross
5StarLounger
Posts: 962
Joined: 09 Feb 2010, 00:33
Location: Patterson Lakes, Victoria, Australia

Re: Minimizing windows using VBA

Post by Peter Kinross »

Yes that works. thanks Kevin
You stated
with a little tweaking, could also minimize the window if it is found by using the SW_MINIMIZE constant
How would that work?
Avagr8day, regards, Peter

Becks
2StarLounger
Posts: 196
Joined: 31 Mar 2011, 03:41
Location: Perth, Western Australia

Re: Minimizing windows using VBA

Post by Becks »

This is one way.

Code: Select all

 
Public Sub myAppActivate(appTitle As String, Optional Wait As Boolean, Optional bShowMaximised As Boolean= True)
'Version 2 to allow for selection whether window is maximised or minimised
Dim hWndArray() As Long
Dim iret As Long
Const SW_MAXIMIZE = 3
Const SW_MINIMIZE = 6
Dim i_SW_Show   As Integer

    If bShowMaximised Then
        i_SW_Show = SW_MAXIMIZE
    Else
        i_SW_Show = SW_MINIMIZE
    End If
    
    If Left(appTitle, 1) <> "*" Then appTitle = "*" & appTitle
    If Right(appTitle, 1) <> "*" Then appTitle = appTitle & "*"

    If FindWindowLike(hWndArray, 0, appTitle, "*", Null) > 0 Then
        iret = SetForegroundWindow32(hWndArray(1))
        iret = ShowWindow32(hWndArray(1), i_SW_Show)
    End If
End Sub

Another way could be to pass the desired constant as a parameter, allowing the full suite of constants to be used.
(Google SW_MAXIMIZE to get other constants)
It can be noted that the Wait parameter isn't used in either version because the code was adapted from existing code.

Kevin

User avatar
Peter Kinross
5StarLounger
Posts: 962
Joined: 09 Feb 2010, 00:33
Location: Patterson Lakes, Victoria, Australia

Re: Minimizing windows using VBA

Post by Peter Kinross »

Thanks Kevin.
Revised version of your 'myAppActivate' code.

Code: Select all

Public Sub myAppActivate(appTitle As String, MinMax As Integer)
'Public Sub myAppActivate(appTitle As String, Optional Wait As Boolean, Optional bShowMaximised As Boolean = True)
'Version 2 to allow for selection whether window is maximised or minimised
'MinMax = 3 for Maximizing, 6 for Minimizing and 9 for Restoring.

Dim hWndArray() As Long
Dim iret As Long
Dim i_SW_Show   As Integer
If Left(appTitle, 1) <> "*" Then appTitle = "*" & appTitle
If Right(appTitle, 1) <> "*" Then appTitle = appTitle & "*"

If FindWindowLike(hWndArray, 0, appTitle, "*", Null) > 0 Then
    iret = SetForegroundWindow32(hWndArray(1))
    iret = ShowWindow32(hWndArray(1), MinMax)
End If
End Sub
I can't get this code to Minimize. It only opens Skype (1st line) and executes the code following after Skype opens.
But it neither minimizes Skype nor brings Access to the front.

Code: Select all

ShellAndWaitTillRunning "C:\Program Files\Skype\Phone\Skype.exe"
myAppActivate appTitle:="Skype", MinMax:=6
myAppActivate appTitle:="Contacts", MinMax:=3
Avagr8day, regards, Peter

Becks
2StarLounger
Posts: 196
Joined: 31 Mar 2011, 03:41
Location: Perth, Western Australia

Re: Minimizing windows using VBA

Post by Becks »

I've converted the myAppActivate to function to test for success (or existence)

Code: Select all


Public Function myAppActivate(appTitle As String, MinMax As Integer) As Boolean
'Public Sub myAppActivate(appTitle As String, Optional Wait As Boolean, Optional bShowMaximised As Boolean = True)
'Version 2 to allow for selection whether window is maximised or minimised
'MinMax = 3 for Maximizing, 6 for Minimizing and 9 for Restoring.

Dim hWndArray() As Long
Dim iret As Long

If Left(appTitle, 1) <> "*" Then appTitle = "*" & appTitle
If Right(appTitle, 1) <> "*" Then appTitle = appTitle & "*"

If FindWindowLike(hWndArray, 0, appTitle, "*", Null) > 0 Then
    iret = SetForegroundWindow32(hWndArray(1))
    iret = ShowWindow32(hWndArray(1), MinMax)
    myAppActivate = True
Else
    myAppActivate = False
End If
End Function
and a test procedure follows

Code: Select all

Sub testit()
If Not myAppActivate(appTitle:="Notepad", MinMax:=3) Then
    ShellAndWaitTillRunning "notepad.exe"
End If
If Not myAppActivate(appTitle:="Basic", MinMax:=9) Then Debug.Print "No Basic"
If Not myAppActivate(appTitle:="Notepad", MinMax:=6) Then Debug.Print "No notepad"
End Sub
I don't have Microsoft Access on this computer so I can't test it within Access's VB environment
The order of the latter two myAppActivate functions appears to be important :scratch:

Kevin

User avatar
Peter Kinross
5StarLounger
Posts: 962
Joined: 09 Feb 2010, 00:33
Location: Patterson Lakes, Victoria, Australia

Re: Minimizing windows using VBA

Post by Peter Kinross »

Kevin, that's great.
I am using 'myAppActivate appTitle:="Contacts", MinMax:=9' to bring Access to the front. But that function only acts on one of the Db's windows, not on the Db app window.
"Contacts ......" is the name of the Access application I am using. But some of that Db's windows have the word "Contacts" somewhere in their title. So 'FindWindowLike' finds one of those and acts on it.
So what I need now is to stop 'FindWindowLike' being recursive so that it only finds application windows. I'm not to sure how to modify your code for that. Any hints?
Avagr8day, regards, Peter

Becks
2StarLounger
Posts: 196
Joined: 31 Mar 2011, 03:41
Location: Perth, Western Australia

Re: Minimizing windows using VBA

Post by Becks »

Is this of any use ? I'm unsure of how you are initiating the procedure so I'm second-guessing

Code: Select all


Function myHWnd() As Long
Dim hWnd As Long

On Error Resume Next
hWnd = Application.Screen.ActiveDatasheet.hWnd
If hWnd = 0 Then hWnd = Application.Screen.ActiveForm.hWnd
If hWnd = 0 Then hWnd = Application.Screen.ActiveReport.hWnd
On Error GoTo 0

myHWnd = hWnd

End Function


Public Sub testIt()
Dim hWnd    As Long
Dim iret   As Long

hWnd = myHWnd()

myAppActivate "Lounge", 9
myAppActivate "Access", 9
myAppActivate "Macro1", 3
MsgBox "waiting"

        iret = ShowWindow32(hWnd, 3)
End Sub
Kevin

User avatar
Peter Kinross
5StarLounger
Posts: 962
Joined: 09 Feb 2010, 00:33
Location: Patterson Lakes, Victoria, Australia

Re: Minimizing windows using VBA

Post by Peter Kinross »

Yes thanks Kevin.
I now have Skype opening then being minimized with Access placed on top.
Although 'myAppActivate' actually minimizes Access and then, after about 0.25 second, restores it. Strange, but I can't see why this is happening.

Code: Select all

If Not myAppActivate(hwnd:=hwnd, appTitle:="Skype", MinMax:=6) Then
    T1 = Timer
    ShellAndWaitTillRunning "C:\Program Files\Skype\Phone\Skype.exe"
    'Takes Skype 5 secs to set itself up. No way of getting around it.
    Do Until Timer - T1 > 6: Loop
End If
PutWintoForeground hwnd
myAppActivate hwnd:=hwnd, appTitle:="Insurance", MinMax:=9


Code: Select all

Function PutWintoForeground(hWnd As Long)
SetForegroundWindow (hWnd)
End Function

Public Function myAppActivate(hWnd As Long, appTitle As String, MinMax As Integer) As Boolean
'MinMax:
        'for Maximizing = 3
        'for Minimizing =6
        'for Restoring = 9
Dim hwndArray() As Long
Dim iret As Long
If Left(appTitle, 1) <> "*" Then appTitle = "*" & appTitle
If Right(appTitle, 1) <> "*" Then appTitle = appTitle & "*"
If FindWindowLike(hwndArray, 0, appTitle, "*", Null) > 0 Then
    iret = ShowWindow32(hWnd, MinMax)
    myAppActivate = True
Else
    myAppActivate = False
End If
End Function
Avagr8day, regards, Peter

Becks
2StarLounger
Posts: 196
Joined: 31 Mar 2011, 03:41
Location: Perth, Western Australia

Re: Minimizing windows using VBA

Post by Becks »

The function myHWnd will return a handle to the active form /report / datasheet within Access, so there is no need to hunt for its handle using the FindWindowLike recursion function.
The first call of myAppActivate for Skype tests to see if it is already open. If it isn't then it is opened, otherwise it needs to be minimized.
A call to myAppActivate with "Access" for the window title should ensure it is the active foreground program, then a call to ShowWindow32 should restore the active form /report /datasheet.

Revert back to a previous version of myAppActivate as the version you posted won't perform properly as the handle returned by the FindWindowLike function isn't used to show the window: hWnd <> hWndArray

Code: Select all

'calling code - written without being tested
Dim hWnd As Long, iret As Long
'get handle of active form etc within Access, function defined in earlier post
hWnd = myHWnd()
'test for existence of Skype 
'if it is found, then it is minimized
If Not myAppActivate(appTitle:="Skype", MinMax:=6) Then
    'it isn't open, so start it    
    T1 = Timer
    ShellAndWaitTillRunning "C:\Program Files\Skype\Phone\Skype.exe"
    'Takes Skype 5 secs to set itself up. No way of getting around it.
    Do Until Timer - T1 > 6: Loop
End If
'now activate Access - any window for the moment
myAppActivate appTitle:="Access", MinMax:=3 
'ensure Skype is minimized
myAppActivate appTitle:="Skype", MinMax:=6 
'now active the original form, restored
iret = ShowWindow32(hWnd, 9)

Kevin

User avatar
Peter Kinross
5StarLounger
Posts: 962
Joined: 09 Feb 2010, 00:33
Location: Patterson Lakes, Victoria, Australia

Re: Minimizing windows using VBA

Post by Peter Kinross »

Thanks Kevin. I fear I am taking up too much of your time, and as you seem to be pretty good at this, your time must be valuable.
The function myHWnd will return a handle to the active form /report / datasheet within Access, so there is no need to hunt for its handle using the FindWindowLike recursion function.
I don't. I get hWnd from hWnd = Access.Application.hWndAccessApp. This works well.
A call to myAppActivate with "Access" for the window title should ensure it is the active foreground program
I don't think that "Access" will work as I have changed the title of the Db to "Contacts ver 14 May 11". The last part of the title changes frequently.
Revert back to a previous version of myAppActivate as the version you posted won't perform properly as the handle returned by the FindWindowLike function isn't used to show the window: hWnd <> hWndArray
I still call 'FindWindowLike' using the array hwndArray(). but only to see if Skype is loaded. Within my version of 'myAppActivate' I use iret = ShowWindow32(hWnd, MinMax). hWnd is passed to 'myAppActivate' when it is called, so I don't need it from 'FindWindowLike'.
Phew that's all confusing. I think I am on the right track as it all works, but I am sure open to suggestions. EG. how to get 'FindWindowLike' to be non-recursive, as I only want to see if the parent window is open.
Avagr8day, regards, Peter

Becks
2StarLounger
Posts: 196
Joined: 31 Mar 2011, 03:41
Location: Perth, Western Australia

Re: Minimizing windows using VBA

Post by Becks »

Because you know the hWnd to both Access and to the calling form/report/datasheet, you don't need myAppActivate to find them. myAppActivate uses FindWindowLike to get the hWnd for application of concern.

hWnd_Access = Access.Application.hWndAccessApp
hWnd_Form = myHWnd()
'test for Skype using myAppActivate, opening it if not already runnning (hWnd of Skype would be 0 if not running)
iret = SetForegroundWindow32(hWnd_Access)
iret = ShowWindow32(hWnd_Form, 9)
'minimize Skype using myAppActivate


(but it's increasing the number of my posts :evilgrin: )
Kevin

User avatar
Peter Kinross
5StarLounger
Posts: 962
Joined: 09 Feb 2010, 00:33
Location: Patterson Lakes, Victoria, Australia

Re: Minimizing windows using VBA

Post by Peter Kinross »

Thanks for all your help Kevin.
Avagr8day, regards, Peter