Google Answers Logo
View Question
 
Q: Microsoft Visual C# Method: External ( Answered 5 out of 5 stars,   1 Comment )
Question  
Subject: Microsoft Visual C# Method: External
Category: Computers > Programming
Asked by: futures_trade-ga
List Price: $200.00
Posted: 26 Aug 2006 13:27 PDT
Expires: 25 Sep 2006 13:27 PDT
Question ID: 759776
I need a method that references a listbox in an application outside of
my program and reads its data. It may be something like
"process(123).handle(123456).copydata.tostring()" but I am not sure.

Windows' calculator.exe's textbox may be used for the example.
Answer  
Subject: Re: Microsoft Visual C# Method: External
Answered By: theta-ga on 27 Aug 2006 13:29 PDT
Rated:5 out of 5 stars
 
Hi futures_trade-ga,
   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: 
[http://rapidshare.de/files/30983829/GA-ScreenScraper.zip.html]


============================================================================

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
control.
    - 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
functionality.
   2.	ScreenScraper ? This class provides the capability of obtaining
the contents of any specified control.
      Usage Example:
       1.// find the content of the textbox control in the app with caption 
         // ?Calculator?
        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);



=============================================================================

RELATED RESOURCES
==================

  - Using Spy++ to Discover a Window Class Name
    [http://support.citrix.com/article/CTX103137]
    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
    [http://www.c-sharpcorner.com/UploadFile/shrijeetnair/win32api12062005005528AM/win32api.aspx?ArticleID=c8ca42aa-faec-448d-b9ea-da5ac627dcbb]
    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
    [http://www.codeproject.com/tools/WindowScraper_Utility.asp?print=true]
    Shows how to use Win32 methods in C# to read text in dialogs.

  - LOST in HELL: pointers unsafe/fixed, TCHAR, and win32api...please help?
    [http://www.codecomments.com/archive290-2004-8-260554.html]
    A forum post outlining how listbox contents can be read using Win32 functions.

  - Screen scraping a windows application
    [http://discuss.joelonsoftware.com/default.asp?joel.3.169439.5]

  - PInvoke signatures for various WIN32 methods, for use in C#
    [http://www.pinvoke.net/]
  
  - MSDN Documentation for the Win32 functions of interest:
     - FindWindowEx:
http://windowssdk.msdn.microsoft.com/en-us/library/ms633500.aspx
     - EnumChildWindows:
http://windowssdk.msdn.microsoft.com/en-us/library/ms633494.aspx
     - GetWindowText :
http://windowssdk.msdn.microsoft.com/en-us/library/ms633520.aspx


============================================================================

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.
Regards,
Theta-ga
:)



=============================================================
Google Search Terms Used:
------------------------- 
C# SendMessage read listbox contents
msdn getwindowtext win32
win32 sendmessage getwindowtext C# -html

Request for Answer Clarification by futures_trade-ga on 06 Sep 2006 22:33 PDT
Excellent answer and code, this was exactly what I was looking for! I
have one request for clarification. I am having a little difficulty
modifying this code to read the contents out of a window whose only
child is of the class "Internet Explorer_Server" as identified by
WinSpy++.

What would I need to do get this code to read these contents?

To clarify, I want to read the contents out of a plain window that
contains no controls, only text. The method is probably the same as
just reading text out of an Internet Explorer window.

Thanks again for your help!

Please give me your email address so I can contact you directly for
future pieces of work.

Clarification of Answer by theta-ga on 08 Sep 2006 21:04 PDT
Hi futures_trade-ga,
    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
           [http://www.codeguru.com/cpp/i-n/ieprogram/article.php/c4383/]
         - http://www.vbforums.com/showthread.php?t=357460
           [http://www.vbforums.com/showthread.php?t=357460]

 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!

Regards,
Theta-ga
:)
futures_trade-ga rated this answer:5 out of 5 stars
Excellent answer; thorough and clearly explained.

Comments  
Subject: Re: Microsoft Visual C# Method: External
From: theta-ga on 27 Aug 2006 04:26 PDT
 
Hi futures_trade-ga,
   I have the solution ready for you. I am just wrapping up the code
into a demo app that reads in data from both the Calculator textbox,
and also from a listbox (since the code for the two tasks is slightly
different). I will be posting my solution soon.

Regards, 
Theta-ga

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy