To access the content of controls in external applications, we
will have to rely on some Win32 functions. I have created a demo
application that demonstrates reading the contents of a textbox and a
listbox in an external application. You can download the demo app and
the source code from:
Instructions for using the Demo App:
- The app contains two exe files. Extract them both into the same
folder, and run the ?GA-ScreenScraper.exe? file to start the demo.
- The app contains two demos : one that shows how you can read the
content of a textbox, and the other which shows how to read the
content of a listbox.
- For the textbox example, click on step 1 to launch the ?Windows
Calculator? utility. Then add some numbers in the textbox control on
Calculator. Then press the button marked as Step 3, and a message box
will show up displaying the contents of the Calculator textbox.
- For the listbox example, click on the step 1 button to launch a
sample app containing a listbox. [This sample app was taken from the
following tutorial: http://www.modula2.org/win32tutor/controls.php].
Now switch to this listbox app and add items to the listbox by
clicking on the ?Add? button. Then switch to the demo app, and click
on button 3 to read the contents of the listbox. A message box will
popup to display the same.
An Explanation of the Methodology
To get the contents of any textbox or listbox control, all we need
is it?s window handle. If you have already obtained the window handle
then move to part 2 of the explaination.
PART 1: Obtaining the control handle
- To obtain the handle of a control, we first obtain the handle of
it?s parent window. We can do this by using the Win32 FindControlEx()
method. This method takes in the window caption (such as ?Calculator?)
and/or its class name, and return its handle.
- Once we have the parent window handle, we can call the Win32
EnumChildWindows method. This method takes in a callback method, which
it calls with the handle of every child contril it finds for the
specified parent. For eg., if we call this method with the handle of
the Calculator window, it will call the callback method with the
handle of the textbox control, and then again with the handles of each
of the buttons on the Calculator window, and so on.
- Since we are only interested in the handle of the textbox
control, we can check the class of the window in the callback method.
The Win32 method GetClassName() can be used for this. This method
takes in a window handle and provides us with a string containing the
class name. So a textbox belongs to the ?Edit? class, a listbox to the
?ListBox? class and so on. Once you have determined that you have the
handle for the right control, you can read its contents.
PART 2: Reading the contents of a control
- You can read in the contents of a control by using the Win32
SendMessage() function, and using it to pass the WM_GETTEXT message to
the target control. This will give you the text content of the
control. This method will work for a textbox, button, or static
- However, the above approach will fail if you try to read the
contents of a listbox. To get the contents of a listbox, we need to
first use SendMessage() with the LB_GETCOUNT message to get the count
of list items. Then we need to call SendMessage() with the LB_GETTEXT
message for each item in the list.
The Source Code
The source code provided was compiled and tested on MS Visual Studio
2005 and requires .Net Framework 2.0 to run.
The Source code contains the following classes of interest:
1. Win32 ? This class wraps all the InterOp calls to the Win32
methods, and is used by the other classes to provide the required
2. ScreenScraper ? This class provides the capability of obtaining
the contents of any specified control.
1.// find the content of the textbox control in the app with caption
ScreenScraper scraper = new ScreenScraper(?Calculator?, null);
string content = calcScraper.GetControlContent("Edit");
2. // find the content of the control with the specified window handle
string content = ScreenScraper.GetControlContent(handle);
- Using Spy++ to Discover a Window Class Name
You can use the Spy++ utility, which ships with Visual Studio, to
find out the class name and window handle of the various windows and
controls on screen.
- Working with Win32 API in .NET
This article provides info on the WIN32 API, and how it can be
invoked from withing .Net code.
- Screen capture, window resizing utility with source code
Shows how to use Win32 methods in C# to read text in dialogs.
- LOST in HELL: pointers unsafe/fixed, TCHAR, and win32api...please help?
A forum post outlining how listbox contents can be read using Win32 functions.
- Screen scraping a windows application
- PInvoke signatures for various WIN32 methods, for use in C#
- MSDN Documentation for the Win32 functions of interest:
- GetWindowText :
Please download the code, look at the demo, and go through the
'ScreenScraper' class. If you have any further questions, or need any
clarifications, just ask!
Hope this helps.
Google Search Terms Used:
C# SendMessage read listbox contents
msdn getwindowtext win32
win32 sendmessage getwindowtext C# -html
Clarification of Answer by
08 Sep 2006 21:04 PDT
The "Internet Explorer_Server" is a custom Internet Explorer class
used to display HTML content. As you have found out, obtaining the
text from this window is not as simple as sending a WM_GETTEXT
message. Instead, we have to obtain a pointer to the IE IHTMLDocument2
interface (which is implemented by the Server class) and use this
interface to obtain the page text.
Since the scope of this question is significantly different from
your original question, I am afraid I cannot tackle it here. Please
post it as a seperate question, and I will be glad to take a look at
it, and post a working example. Meanwhile, you can take a look at the
following articles to get an idea of what needs to be done:
- Auto Testing Browser Control Applications
They also contain sample code (in C++ and VB.Net) that you should be
able to adapt for your purpose.
As for your request for my email id, I am afraid Google Answers
rules specifically prohibit researchers from sharing their email
information with clients. You can, however, prefix the subject of your
future questions with the text "for theta-ga" when you post them here
at GA, and I will take a look at them.
Hope this helps!