Search code examples
c#.netwinapiwinforms-interop

Getting text entered in textbox of other applications using C#


I want to get the text which is in textbox of other application. It may be a textbox of gtalk client or a soap UI screen.

Based on my research most of the forums suggested winapi is the concept that I've to use to achieve this. I didn't get any good examples to implement this.


Solution

  • Here is an example of how to grab all the text from a window by it's window title.

    Please see the comments for an explanation on how this works.

    public class GetWindowTextExample
    {
        // Example usage.
        public static void Main()
        {
            var allText = GetAllTextFromWindowByTitle("Untitled - Notepad");
            Console.WriteLine(allText);
            Console.ReadLine();
        }
    
        // Delegate we use to call methods when enumerating child windows.
        private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
    
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
    
        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        private static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
    
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, [Out] StringBuilder lParam);
    
        // Callback method used to collect a list of child windows we need to capture text from.
        private static bool EnumChildWindowsCallback(IntPtr handle, IntPtr pointer)
        {
            // Creates a managed GCHandle object from the pointer representing a handle to the list created in GetChildWindows.
            var gcHandle = GCHandle.FromIntPtr(pointer);
    
            // Casts the handle back back to a List<IntPtr>
            var list = gcHandle.Target as List<IntPtr>;
    
            if (list == null)
            {
                throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
            }
    
            // Adds the handle to the list.
            list.Add(handle);
    
            return true;
        }
    
        // Returns an IEnumerable<IntPtr> containing the handles of all child windows of the parent window.
        private static IEnumerable<IntPtr> GetChildWindows(IntPtr parent)
        {
            // Create list to store child window handles.
            var result = new List<IntPtr>();
    
            // Allocate list handle to pass to EnumChildWindows.
            var listHandle = GCHandle.Alloc(result);
    
            try
            {
                // Enumerates though all the child windows of the parent represented by IntPtr parent, executing EnumChildWindowsCallback for each. 
                EnumChildWindows(parent, EnumChildWindowsCallback, GCHandle.ToIntPtr(listHandle));
            }
            finally
            {
                // Free the list handle.
                if (listHandle.IsAllocated)
                    listHandle.Free();
            }
    
            // Return the list of child window handles.
            return result;
        }
    
        // Gets text text from a control by it's handle.
        private static string GetText(IntPtr handle)
        {
            const uint WM_GETTEXTLENGTH = 0x000E;
            const uint WM_GETTEXT = 0x000D;
    
            // Gets the text length.
            var length = (int)SendMessage(handle, WM_GETTEXTLENGTH, IntPtr.Zero, null);
    
            // Init the string builder to hold the text.
            var sb = new StringBuilder(length + 1);
    
            // Writes the text from the handle into the StringBuilder
            SendMessage(handle, WM_GETTEXT, (IntPtr)sb.Capacity, sb);
    
            // Return the text as a string.
            return sb.ToString();
        }
    
        // Wraps everything together. Will accept a window title and return all text in the window that matches that window title.
        private static string GetAllTextFromWindowByTitle(string windowTitle)
        {
            var sb = new StringBuilder();
    
            try
            {
                // Find the main window's handle by the title.
                var windowHWnd = FindWindowByCaption(IntPtr.Zero, windowTitle);
    
                // Loop though the child windows, and execute the EnumChildWindowsCallback method
                var childWindows = GetChildWindows(windowHWnd);
    
                // For each child handle, run GetText
                foreach (var childWindowText in childWindows.Select(GetText))
                {
                    // Append the text to the string builder.
                    sb.Append(childWindowText);
                }
    
                // Return the windows full text.
                return sb.ToString();
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }
    
            return string.Empty;
        }
    }