Wrox Home  
Search P2P Archive for: Go

  Return to Index  

pro_vb thread: Getting a reference to an Excel application object from it's window handle


Message #1 by "andy irvine" <andy@i...> on Wed, 20 Mar 2002 22:05:59
Dear all,

Firstly, apologies in advance for such a long post, however most of it is 
example code, so you should be able to get through it quickly :~)

PROBLEM:
I would like to get the handle to a particular instance of Excel.  I can 
get a reference to a running instance of excel like this:

Dim Xlapp as Excel.Application
Set Xlapp = GetObject(, "Excel.Application")

However it always returns a reference to the instance which was launched 
first.  What about if I want the one that was launched second? Well, 
here's my thought process so far....

WORK SO FAR:
Getting a handle to the window of a specific window running excel is 
relatively straight forward.  Paste the following code into a form and put 
a command button on it.  Launch a few instances of Excel and run the 
project.  You will see the Hwnds for the Windows running Excel printed to 
the immediate window.

<Form 1>
'--------------------------------------------------------------------------
Option Explicit

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
 ByVal wCmd As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindowLW Lib "user32" Alias "GetWindowLongA" _
 (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
 (ByVal hwnd As Long, ByVal lpClassName As String, _
  ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" 
_
 (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) _
  As Long
Private Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, _
               ByVal lpWindowName As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
               ByVal lParam As Long) As Long
Private Declare Function GetActiveWindow Lib "user32" () As Long


' ShowWindow commands
Const SW_HIDE = 0
Const SW_SHOWNORMAL = 1
Const SW_NORMAL = 1
Const SW_SHOWMINIMIZED = 2
Const SW_SHOWMAXIMIZED = 3
Const SW_MAXIMIZE = 3
Const SW_SHOWNOACTIVATE = 4
Const SW_SHOW = 5
Const SW_MINIMIZE = 6
Const SW_SHOWMINNOACTIVE = 7
Const SW_SHOWNA = 8
Const SW_RESTORE = 9
Const SW_SHOWDEFAULT = 10
Const SW_MAX = 10

'const for FindWindow
Const GW_HWNDNEXT = 2
Const GW_CHILD = 5
'--------------------------------------------------------------------------
Private Sub Command1_Click()
Dim hWnds() As Long, r&, i%
' Find excel app
r& = FindWindowLike(hWnds(), 0, "*", "XLMAIN")
' Print Hwnds of Excel windows
For i% = 0 To r& - 1
  Debug.Print "found excel in window"; hWnds(i)
Next
End Sub
'--------------------------------------------------------------------------
Function FindWindowLike(hwndArray() As Long, _
  Optional ByVal hWndStart As Long = 0, _
  Optional WindowText As String = "*", _
  Optional ClassName As String = "*") As Long
'..........................................................................
' Modified from code on MSDN - Thank you Microsoft

'PURPOSE
'-------
' - Finds the window handles of the windows matching the specified
'   parameters

'PARAMETERS
'----------
'hwndArray()
' - An integer array used to return the window handles
'
'WindowText
' - The pattern used with the Like operator to compare window's text.
'
'ClassName
' - The pattern used with the Like operator to compare window's class
'   name.
'
'ID
' - A child ID number used to identify a window.
' - Can be a decimal number or a hex string.
' - Prefix hex strings with "&H" or an error will occur.
' - To ignore the ID pass the Visual Basic Null function.
'
'Returns
' - The number of windows that matched the parameters.
' - Also returns the window handles in hWndArray()
'..........................................................................
Dim hwnd As Long
Dim r As Long

' Hold the number of matching windows:
Static iFound As Long
' Window info
Dim sWindowText As String, sClassname As String

' Initialize
iFound = 0
ReDim hwndArray(0 To 0)
If hWndStart = 0 Then hWndStart = GetDesktopWindow()

' Get first  window:
hwnd = GetWindow(hWndStart, GW_CHILD)
Do Until hwnd = 0
  DoEvents ' Not necessary
  ' Get the window text
  sWindowText = Space(255)
  r = GetWindowText(hwnd, sWindowText, 255)
  sWindowText = Left(sWindowText, r)
  'Get the class name:
  sClassname = Space(255)
  r = GetClassName(hwnd, sClassname, 255)
  sClassname = Left(sClassname, r)
  ' Check that window matches the search parameters:
  If sWindowText Like WindowText And sClassname Like ClassName Then
    ' If find a match, increment counter and add handle to array:
    ReDim Preserve hwndArray(0 To iFound)
    hwndArray(iFound) = hwnd
    iFound = iFound + 1
    ' print result
    'Debug.Print "Window Found: "
    'Debug.Print "  Window Text  : " & sWindowText
    'Debug.Print "  Window Class : " & sClassname
    'Debug.Print "  Window Handle: " & CStr(hwnd)
  End If
  
' Get next window:
hwnd = GetWindow(hwnd, GW_HWNDNEXT)
Loop

' Return the number of windows found:
FindWindowLike = iFound
End Function
'--------------------------------------------------------------------------
<Form 1:end>

However, what I really want do in Command1_Click is something like this:

'--------------------------------------------------------------------------
Private Sub Command1_Click()
Dim hWnds() As Long, r&, i%, sWindowText$
Dim xlapp As Excel.Application

' Find excel app
r& = FindWindowLike(hWnds(), 0, "*", "XLMAIN")
' Print Hwnds of Excel windows

' Get the window text
sWindowText = Space(255)
r = GetWindowText(hWnds(1), sWindowText, 255)
sWindowText = Left(sWindowText, r)

Set xlapp = AppActivate(sWindowText)  <----This obviously doesn't work _ 
						as AppActivate doesn't 
return an object
xlapp.Visible
End Sub 
'--------------------------------------------------------------------------

Does anybody have any suggestions on how to do this in VB???  I understand 
that this sort of thing is easier in C, but I don't know C so that doesn't 
help me much.

cheers
andy

  Return to Index