23

I want to get the content of the control / handle of an application..

Here's the experimental code..

 Process[] processes = Process.GetProcessesByName("Notepad");
        foreach (Process p in processes)
        {
            StringBuilder sb = new StringBuilder();
            IntPtr pFoundWindow = p.MainWindowHandle;
             List <IntPtr> s =    GetChildWindows(pFoundWindow); 
            // function that returns a 
            //list of handle from child component on a given application.

             foreach (IntPtr test in s)
             {
              // Now I want something here that will return/show 
               the text on the notepad..


             }


            GetWindowText(pFoundWindow, sb,256);
            MessageBox.Show(sb.ToString()); // this shows the title.. no problem with that

        } 

any idea? I've read some API method like GetWindowText or WM_GETTEXT but I dont know how to use it or apply it on my code.. I need a tutorial or sample code...

Thanks in advance : )

Surjit Samra
  • 4,614
  • 1
  • 26
  • 36
user848682
  • 379
  • 2
  • 4
  • 12

3 Answers3

31
public class GetTextTestClass{

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    public static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr SendMessage(int hWnd, int Msg, int wparam, int lparam);

    const int WM_GETTEXT       = 0x000D;
    const int WM_GETTEXTLENGTH = 0x000E;

    public string GetControlText(IntPtr hWnd){

        // Get the size of the string required to hold the window title (including trailing null.) 
        Int32 titleSize = SendMessage((int)hWnd, WM_GETTEXTLENGTH, 0, 0).ToInt32();

        // If titleSize is 0, there is no title so return an empty string (or null)
        if (titleSize == 0)
            return String.Empty;

        StringBuilder title = new StringBuilder(titleSize + 1);

        SendMessage(hWnd, (int)WM_GETTEXT, title.Capacity, title);

        return title.ToString();
    }
}
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
Surjit Samra
  • 4,614
  • 1
  • 26
  • 36
  • Woah, it works on notepad.. but It doesn't work on other application but I guess the problem is that I need the control of the child component.. maybe i need to research more ; ) – user848682 Oct 12 '11 at 14:17
  • 1
    yep, if the control you are after is a child control in a given window then you need to iterativly get the controls and stop when when title matches the required one. – Surjit Samra Oct 12 '11 at 14:48
  • uhmm, samra if you have spare time, can you give me a method that accepts a handle and returns list of child control? thanks in advance. There's something wrong with the method i got from net.. – user848682 Oct 13 '11 at 03:42
  • May be raise a new question explaining what code is failing now – Surjit Samra Oct 14 '11 at 08:44
  • 3
    RegisterWindowMessage isn't necessary here, doesn't do what you think, and you never actually call RegisterControlforMessages. – Random832 Feb 22 '14 at 01:42
  • Very useful! Exactly what I was looking for. However, why using a StringBuilder and not a String? Any implications in doing so? Thanks!! – CowWarrior Jun 02 '17 at 16:46
  • 1
    @CowWarrior I'm guessing you've already discovered the answer by now, but the reason is, you're actually passing a pointer to an array (the StringBuilder buffer) to SendMessage. Strings are technically immutable. – Clay Oct 18 '19 at 16:04
4

GetWindowText won't give you the content of edit windows from other applications - it only supports default-managed text [like the captions of labels] across processes to prevent hangs... you'll have to send WM_GETTEXT.

You'll need to use a StringBuilder version of SendMessage:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);

const int WM_GETTEXT = 0xD;
StringBuilder sb = new StringBuilder(65535);
// needs to be big enough for the whole text
SendMessage(hWnd_of_Notepad_Editor, WM_GETTEXT, sb.Length, sb);
Random832
  • 37,415
  • 3
  • 44
  • 63
2

Have a look at http://pinvoke.net/default.aspx/user32/GetWindowText.html and also the documentation on MSDN. Below you find a short code example how to use the GetWindowText method.

System.Data
  • 3,878
  • 7
  • 32
  • 40