pro_vb thread: Getting a reference to an Excel application object from it's window handle
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