[VBA × Windows API] How to Use the FindWindow Function
FindWindow Function
The FindWindow function retrieves a handle to a window whose caption (window name) or class name matches the values you pass in.
A window handle is a special identifier used to refer to a specific window.
You use it whenever you want to tell Windows to do something to that window — open or close it, move it, resize it, change its text, and so on. Each of those operations is itself another Windows API function.
In C++, window handles are typed as HWND, but internally the value is just a long integer, so in VBA you use LongPtr (or Long on 32-bit). VBA variables that hold a window handle are commonly named hWnd to match the C++ convention.
A handle is assigned automatically when a window is created. It stays valid for the lifetime of that window, and becomes invalid as soon as the window is closed. In other words, the same window can end up with a different handle value the next time it is opened.
In VBA, a UserForm is also a window, so once you have its handle you can do things like bring it to the foreground, make it resizable, or make it semi-transparent. FindWindow is the function you use to obtain that handle in the first place. There are several other APIs that also return window handles, including GetActiveWindow, GetNextWindow, and GetParent.
You pick the right one based on “what do I already know about the window I’m looking for?" — but FindWindow is one of the most common and general-purpose ways of getting a handle.
Usage
Before calling FindWindow, you must declare it at the top of your module.
Without the declaration the function cannot be used and will raise an error, so don’t forget it.
The declaration differs depending on whether your Office/VBA host is 32-bit or 64-bit. Place one of the following near the top of your module (just after Option Explicit) to make the function available inside that module.
Declare PtrSafe Function FindWindow Lib “user32" Alias “FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Declare Function FindWindow Lib “user32" Alias “FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
If you are not sure which one to use, paste the following block at the top of your module. It automatically selects the correct declaration at compile time.
In the VBE, the unused branch may be shown in red, but this does not affect execution.
#If VBA7 Then
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
#Else
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
#End If
You can also prefix the declaration with Private or Public to control its scope.
・Public Declare PtrSafe Function … : callable from outside the module
Syntax
The syntax of the FindWindow function is as follows.
hwnd = FindWindow(lpClassName, lpWindowName)
Arguments
lpClassName (String)
The class name of the window you want a handle to.
A window class name is an identifier that Windows uses to tell different kinds of windows apart. Each application registers its own class name, so you use lpClassName to say “I want a window that belongs to this application."
The table below lists the class names of applications commonly targeted from VBA. You can look up the class name of any other application using GetClassName.
| Application | Window class name |
| Excel | XLMAIN |
| PowerPoint | PPTFrameClass |
| Word | OpusApp |
| Notepad | Notepad |
| File Explorer | CabinetWClass |
| UserForm | ThunderDFrame |
If you pass vbNullString (NULL) for this argument, every window whose caption matches lpWindowName becomes a candidate — regardless of class. If lpWindowName alone is specific enough to uniquely identify the window, passing vbNullString for lpClassName is perfectly fine.
lpWindowName (String)
The caption (window title) of the window you want a handle to.
Because a UserForm is also a window, the code below retrieves the handle of UserForm1 — which then lets you do things like make it resizable or make it transparent.
Sub Test()
UserForm1.Show vbModeless
hwnd = FindWindow(vbNullString, UserForm1.Caption) '<- pass the UserForm caption as lpWindowName
' Do something with hwnd
End Sub
If you pass vbNullString here, every window becomes a candidate.
Return value
hwnd (64-bit: LongPtr / 32-bit: Long)
On success, the return value is a handle to the window that matches the given class name and window name. If several windows match, the one closest to the front is returned.
On failure, the return value is NULL (0).
As with the arguments, the return type depends on whether you are running 32-bit or 64-bit VBA — be mindful of this when declaring variables that receive the result.
FindWindow walks this Z-order from front to back. For example, if you pass "XLMAIN" as lpClassName, you get the handle of the Excel window closest to the front. The same priority applies even when both lpClassName and lpWindowName are vbNullString — in that case, you simply get the handle of the frontmost window on screen.
Sample Code
The sample below uses FindWindow together with GetWindowText to retrieve the caption of a specific window. If Excel is open, it returns the caption of whichever Excel window is currently in the front.
Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As LongPtr
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Sub main()
Dim hwnd As LongPtr
Dim lRet As LongPtr
Dim sBuf As String * 100
Dim sCap As String
' Get the Excel window handle
hwnd = FindWindow("XLMAIN", vbNullString)
' Get the caption of that handle (into a fixed-length string)
lRet = GetWindowText(hwnd, sBuf, Len(sBuf))
' Trim the unused buffer part
sCap = Left(sBuf, InStr(sBuf, vbNullChar) - 1)
' Print the retrieved caption to the Immediate window
Debug.Print sCap
End Sub
Conversely, the sample below uses FindWindow together with GetClassName to retrieve the class name of a specific window. If Command Prompt is open, running this returns its class name. Because this sample looks up the window by its caption, note that if another window with the same caption is closer to the front, you’ll get that one’s handle instead.
Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As LongPtr, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Sub main()
Dim hwnd As LongPtr
Dim lRet As LongPtr
Dim sBuf As String * 100
Dim sCls As String
' Get the Command Prompt window handle
hwnd = FindWindow(vbNullString, "Command Prompt")
' Get the class name of that handle (into a fixed-length string)
lRet = GetClassName(hwnd, sBuf, Len(sBuf))
' Trim the unused buffer part
sCls = Left(sBuf, InStr(sBuf, vbNullChar) - 1)
' Print the retrieved class name to the Immediate window
Debug.Print sCls
End Sub
In both cases, you can confirm that FindWindow successfully returns a handle to the target window.
VBA × Windows API Index
For other Windows API functions, please also refer to the index page below.
Reference
Microsoft official: FindWindowA function (winuser.h) — Win32 apps


![[VBA Extensions] Complete Guide to Calling the Windows API from VBA](https://liclog.net/wp-content/uploads/2023/07/24b09ec528d00f75524f52dc8477a1f8-100x100.png?is-pending-load=1)





