Visual Basic Helper Routines
SetWindowPlacement: Restore and Activate a Window via its hWnd
     
Posted:   Saturday July 17, 1999
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows NT4
OS restrictions:   None
Author:   VBnet - Randy Birch
     

Related:  

EnumWindows: Enumerate (and Restore) a Window via Callback
GetWindowThreadProcessId: Obtain the hWnd of an App Started with Shell()
     
 Prerequisites
None.

restoreappctrl.gif (1822 bytes)Scenario:
  • You have a multiple-exe application
  • Each single exe provides unique functionality
  • All apps are launched via a "control app" (ie a toolbar app or a main application).
  • All apps are standard exe's (not ActiveX exe's).restoreappmain.gif (2500 bytes)
  • No intercommunication methods (pipes, private messages) have been implemented
  • On closing an application started from the "control app", you want to assure that the control app is restored on screen ready for user input.

This code page was prompted by a post on the DevX newsgroups, in response to a terrible suggestion that the control app start a timer, poll FindWindow, and when the app in question is no longer found, restore itself. This type of help frankly makes me cringe. The WinAPI provides many methods that could be used to perform this simple task effectively without unnecessary timers or loops.. This code has worked flawlessly on Win95a/b, win98 and WinNT4.

In this example we're going to create two exe's. To assure that the code is not obscured by fancy methods, and is simple to understand, I've used the simplest means of coding the apps - using Shell and hard-coding the path to the exe's. Naturally you'll want to change this in anything you develop.

 Project 1:  BAS Module Code - "Main" App
Place the following code into the general declarations area of a bas module:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Type RECT
  Left    As Long
  Top     As Long
  Right   As Long
  Bottom  As Long
End Type

Public Type POINTAPI
  x       As Long
  y       As Long
End Type

Public Type WINDOWPLACEMENT
  Length            As Long
  flags             As Long
  showCmd           As Long
  ptMinPosition     As POINTAPI
  ptMaxPosition     As POINTAPI
  rcNormalPosition  As RECT
End Type

Public Const SW_SHOWNORMAL = 1
Public Const SW_SHOWMINIMIZED = 2
Public Const SW_SHOWMAXIMIZED = 3
Public Const SW_SHOWNOACTIVATE = 4

Public Declare Function BringWindowToTop Lib "user32" _
  (ByVal hwnd As Long) As Long

Public Declare Function FindWindow Lib "user32" _
   Alias "FindWindowA" _
  (ByVal lpClassName As String, _
   ByVal lpWindowName As String) As Long
   
Public Declare Function GetWindowPlacement Lib "user32" _
   (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long

Public Declare Function SetForegroundWindow Lib "user32" _
   (ByVal hwnd As Long) As Long

Public Declare Function SetWindowPlacement Lib "user32" _
   (ByVal hwnd As Long, lpwndpl As WINDOWPLACEMENT) As Long


Public Sub RestoreWindow(sWindowTitle As String)

   Dim hWndCtlApp As Long
   Dim currWinP As WINDOWPLACEMENT
    
  'obtain the handle to the control app
   hWndCtlApp = FindWindow(vbNullString, sWindowTitle)
   
   If hWndCtlApp Then
   
     'prepare the WINDOWPLACEMENT type
      currWinP.Length = Len(currWinP)
   
      If GetWindowPlacement(hWndCtlApp, currWinP) > 0 Then
      
        'determine the window state
         If currWinP.showCmd = SW_SHOWMINIMIZED Then
      
           'minimized, so restore
            currWinP.Length = Len(currWinP)
            currWinP.flags = 0&
            currWinP.showCmd = SW_SHOWNORMAL
            Call SetWindowPlacement(hWndCtlApp, currWinP)
         
         Else
           
           'on screen, so assure visible
            Call SetForegroundWindow(hWndCtlApp)
            Call BringWindowToTop(hWndCtlApp)
         
         End If
      
      End If
   
   End If
   
End Sub
 Project 1:  Form Code - "Main" App
For this demo, this form needs no controls. Add the following code:

Option Explicit

Private Sub Form_Load()

   Me.Move (Screen.Width - Me.Width) \ 2, _
           (Screen.Height - Me.Height) \ 2
    
End Sub


Private Sub Form_Unload(Cancel As Integer)

  'last minute clean-up code here
   
  'restore the control app
   RestoreWindow "My Control App"
   
  'we're done   
End Sub

 

 Project 2:  BAS Module Code - Control App
None.

 Project 2:  Form Code - Control App
To a form, add a command button and a checkbox. Set the Form caption to something unique - this is what is used in the activate code. Add the following:

Option Explicit

Private Sub Command1_Click()

   Dim x As Long

  'for simplicity, Shell with a hard
  'coded path will be used
  
   x = Shell("c:\apptest\appmain.exe", vbNormalFocus)
   
   If x > 32 Then
      If Check1.Value = 1 Then
         Me.WindowState = vbMinimized
      End If
   End If
   
End Sub


Private Sub Form_Load()

   Check1.Value = 1

End Sub
 Comments
Compile both forms as separate exe's, and put them into the path you specified in the Shell statement. Run the control app, and experiment.

 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter