Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find control of specific class in another application

Tags:

c#

winapi

user32

I am scrapping content from another Windows application. The application has a Listbox and two TRichEdit controls (and other controls without interest).

When using SendKeys.SendWait("{DOWN}") to the Listbox, the content in the two TRichEdit boxes changes. Thats where I want to scrap the content. That works.

RichEdit1 : No problem - I get the content using SendMessageW()

RichEdit2: Big problem. It changes Windows Handle each time I use SendKeys.SendWait on the LIstBox, so I can't access it.

The solution is to find the new Windows Handle for RichEdit2. I think that I can get a list of Handles for RichEdit control and select the one with Handle different from RichEdit1.

Question: How can I get a list of Handles of a specific class (RichEdit) from a different windows forms application?

Or

Does anyone has a better solution? A code snippet in C# will be appreciated.

Thanks in advance.

like image 941
Anders Finn Jørgensen Avatar asked Dec 11 '25 13:12

Anders Finn Jørgensen


1 Answers

For the question on how to get the RichEdit window handles:

You can PInvoke FindWindowEx setting the child window parameter to NULL to check all child windows and the class name set to the class names of RichEdit control from here:

v1.0 = RICHEDIT
v2.0 & v3.0 = RichEdit20A or RichEdit20W
v4.1 = RICHEDIT50W
v5.0 = RichEdit50W
v6.0 = RichEdit60W

Still, MSDN states that:

The function searches among windows that are child windows of the desktop.

So basically you get a search depth of one. If your controls are nested deeper, then you may need to combine this with EnumChildWindows to perfrom a full depth search.

EDIT

This is a snippet on how to enumerate the windows and find matching windows for a given class using the described method, hope you can fine tune it.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace UIAutomation
{
    class Program
    {
        public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        public static bool EnumChildWindowsCallback(IntPtr hWnd, IntPtr lParam)
        {
            StringBuilder className = new StringBuilder(256);
            GetClassName(hWnd, className, className.Capacity);
            var windowInformation = new WindowInformation(hWnd, lParam, className.ToString());
            _windowLookupMap[hWnd] = windowInformation;
            if (lParam != IntPtr.Zero)
            {
                _windowLookupMap[lParam]._children.Add(windowInformation);
            }
            EnumChildWindows(hWnd, EnumChildWindowsCallback, hWnd);
            return true;
        }

        class WindowInformation
        {
            public IntPtr _parent;

            public IntPtr _hWnd;

            public string _className;

            public List<WindowInformation> _children = new List<WindowInformation>();

            public WindowInformation(IntPtr hWnd, IntPtr parent, string className)
            {
                _hWnd = hWnd;
                _parent = parent;
                _className = className;
            }
        }

        static Dictionary<IntPtr, WindowInformation> _windowLookupMap = new Dictionary<IntPtr, WindowInformation>();

        static void FindWindowsByClass(string className, WindowInformation root, ref  List<WindowInformation> matchingWindows)
        {
            if (root._className == className)
            {
                matchingWindows.Add(root);
            }
            foreach (var child in root._children)
            {
                FindWindowsByClass(className, child, ref matchingWindows);
            }
        }

        static void Main(string[] args)
        {
            var processes = Process.GetProcessesByName("notepad");
            StringBuilder className = new StringBuilder(256);
            GetClassName(processes[0].MainWindowHandle, className, className.Capacity);
            _windowLookupMap[processes[0].MainWindowHandle] = new WindowInformation(processes[0].MainWindowHandle, IntPtr.Zero, className.ToString());
            EnumChildWindows(processes[0].MainWindowHandle, EnumChildWindowsCallback, processes[0].MainWindowHandle);
            List<WindowInformation> matchingWindows = new List<WindowInformation>();
            FindWindowsByClass("Edit", _windowLookupMap.Single(window => window.Value._parent == IntPtr.Zero).Value, ref matchingWindows);
            Console.WriteLine("Found {0} matching window handles", matchingWindows.Count);
        }
    }
}
like image 159
Rudolfs Bundulis Avatar answered Dec 14 '25 03:12

Rudolfs Bundulis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!