Of course! The FindWindowEx function is a key part of the Windows API (specifically user32.dll) used to find child windows within a parent window by their class name and/or window title.

While there isn't a built-in Python function named FindWindowEx, you can easily access it using the pywin32 library, which provides Python access to many Windows-specific APIs.
Here’s a complete guide on how to use it.
Prerequisites: Install pywin32
First, you need to install the pywin32 library. You can do this using pip:
pip install pywin32
Understanding FindWindowEx
The FindWindowEx function has the following signature:

HWND FindWindowEx(
HWND hWndParent, // Handle to the parent window
HWND hWndChildAfter, // Handle to a child window
LPCSTR lpszClass, // Class name of the window to find
LPCSTR lpszWindow // Window title (text) of the window to find
);
Let's break down the parameters for Python:
| Parameter | Python (pywin32) Type |
Description |
|---|---|---|
hWndParent |
int or None |
A handle to the parent window. If you pass 0 or None, it searches the top-level windows. |
hWndChildAfter |
int or None |
A handle to a child window to start searching after. If you pass None, the search starts from the first child window. This is useful for finding multiple controls with the same class/title. |
lpszClass |
str or None |
The class name of the window to find (e.g., "Edit", "Button", "Notepad"). You can use tools like Spy++ (included with Visual Studio) or AutoIt Window Info to find these. |
lpszWindow |
str or None |
The window title (the text displayed on the window/control). This is often the most user-friendly parameter. |
Return Value:
- Returns a handle (
int) to the window if found. - Returns
0orNoneif the window is not found.
Finding a Child Window: A Practical Example
Let's find the text input field in the Windows Calculator application.
Step 1: Open the Calculator.
Step 2: Use Spy++ or a similar tool to find the window class.
If you use Spy++ to inspect the Calculator's display, you'll find its class name is ApplicationFrameWindow.

Here is the Python code to find that display field:
import win32gui
import win32con
# The title of the main Calculator window
calculator_title = "Calculator"
# The class name of the display control
display_class = "Windows.UI.Core.CoreWindow" # This is the class for the display in modern calculator
# Alternatively, for older versions, it might be "Static"
# Let's try a more robust approach by finding the main window first.
def find_calculator_display():
"""Finds the display window of the Calculator application."""
try:
# 1. Find the main Calculator window by its title
hwnd_main = win32gui.FindWindow(None, calculator_title)
if not hwnd_main:
print(f"Could not find main window with title '{calculator_title}'. Is Calculator open?")
return None
print(f"Found main Calculator window. Handle: {hwnd_main}")
# 2. Find the child window (the display) within the main window.
# We'll search by its class name. For modern Calculator, it's "Windows.UI.Core.CoreWindow"
# We pass hwnd_main as the parent.
hwnd_display = win32gui.FindWindowEx(hwnd_main, 0, "Windows.UI.Core.CoreWindow", None)
if not hwnd_display:
# Fallback for older calculator versions
hwnd_display = win32gui.FindWindowEx(hwnd_main, 0, "Static", None)
if not hwnd_display:
print("Could not find the display control. Class name might be different.")
return None
print(f"Found display window. Handle: {hwnd_display}")
return hwnd_display
except Exception as e:
print(f"An error occurred: {e}")
return None
# --- Main execution ---
if __name__ == "__main__":
display_handle = find_calculator_display()
if display_handle:
# You can now use this handle for other operations, like getting text or sending messages
print(f"Successfully found the display handle: {display_handle}")
# Example: Get the window text (the current calculation)
window_text = win32gui.GetWindowText(display_handle)
print(f"Current display text: '{window_text}'")
Finding Multiple Child Windows (e.g., all buttons)
If you want to find all buttons in a window, you can loop. The trick is to pass the handle of the last found window as the hWndChildAfter parameter in the next call.
import win32gui
def find_all_buttons_in_notepad():
"""Finds all 'Button' controls in a Notepad window."""
try:
# Find a Notepad window. We use the class name "Notepad" as it's more reliable.
hwnd_notepad = win32gui.FindWindow("Notepad", None)
if not hwnd_notepad:
print("Could not find a Notepad window. Please open Notepad.")
return
print(f"Found Notepad window. Handle: {hwnd_notepad}")
button_handles = []
last_found_handle = None # Start with None to search from the beginning
while True:
# Find the next button after the one we just found
hwnd_button = win32gui.FindWindowEx(hwnd_notepad, last_found_handle, "Button", None)
if hwnd_button == 0: # No more buttons found
break
button_handles.append(hwnd_button)
last_found_handle = hwnd_button # Update the search to start from here
print(f"\nFound {len(button_handles)} buttons:")
for i, handle in enumerate(button_handles):
# Get the button's text
text = win32gui.GetWindowText(handle)
print(f" Button {i+1}: Handle={handle}, Text='{text}'")
except Exception as e:
print(f"An error occurred: {e}")
# --- Main execution ---
if __name__ == "__main__":
find_all_buttons_in_notepad()
Important Tools for Finding Window Information
To use FindWindowEx effectively, you need to know the class names and titles of the windows you're looking for. These tools are indispensable:
- Spy++: Comes with Visual Studio. It's a powerful tool that lets you inspect the window hierarchy, find window handles, class names, and styles in real-time.
- AutoIt Window Info: A free tool that is excellent for this purpose. It gives you a simple list of all windows, their properties (handle, class, title, etc.), and even allows you to hover over controls to see their details.
- Microsoft Inspect: A modern tool from Microsoft for inspecting UI Automation elements. It's very powerful for modern WinUI and WPF applications.
Summary: FindWindowEx Cheat Sheet
| Goal | hWndParent |
lpszClass |
lpszWindow |
hWndChildAfter |
|---|---|---|---|---|
| Find a top-level window (e.g., Notepad) | None |
"Notepad" |
None |
None |
| Find a child by its title | Parent Handle | None |
"My Button" |
None |
| Find a child by its class | Parent Handle | "Edit" |
None |
None |
| Find a child by both class & title | Parent Handle | "Button" |
"OK" |
None |
| Find all buttons | Parent Handle | "Button" |
None |
Loop with last found handle |
