1

I am trying to traverse the controls of a WinForms form (Windows CE) and retrieve/match their textual contents and names (that is, the Name property assigned to the WinForms Control object).

I do this from within a different process, thus WinAPI.

For traversing and for retrieving the text I wrote the following code. TextPresent uses DescendantControls for the traversing and Text to retrieve the text. I am fairly confident that the traversing code works correctly already - if not, please let me know. However, all of the controls that are returned have an empty text.

The code can be used as follows:

var foregroundWindow = new WinCEControl(GetForegroundWindow()); // working properly
Assert.That("The Window Title", foregroundWindow.Text); // working properly
Assert.That(manorMenu.TextPresent("Text to find")); // not working although /
    // "Text to find" is a value within the control tree of the window.

As for the name, I do not even know how to retrieve it at all. So far my searching was unsuccessful.

public class WinCEControl
{
    [DllImport("coredll.dll", SetLastError = true)]
    private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

    [DllImport("coredll.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
    private static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

    private const int WM_GETTEXT = 0x000D;
    private const uint GW_CHILD = 5;
    private const uint GW_HWNDLAST = 1;
    private const uint GW_HWNDNEXT = 2;

    public WinCEControl(IntPtr handle)
    {
        this.Handle = handle;
    }

    public IntPtr Handle { get; private set; }

    public string Text
    {
        get
        {
            var stringBuilder = new StringBuilder(256);
            SendMessage(this.Handle, WM_GETTEXT, stringBuilder.Capacity, stringBuilder);
            return stringBuilder.ToString();
        }
    }

    public IEnumerable<WinCEControl> Children()
    {
        var childHandle = GetWindow(Handle, GW_CHILD);

        if (childHandle == IntPtr.Zero)
        {
            yield break;
        }

        var lastHandle = GetWindow(childHandle, GW_HWNDLAST);

        while (childHandle != lastHandle)
        {
            yield return new WinCEWindow(childHandle);

            childHandle = GetWindow(childHandle, GW_HWNDNEXT);
        }

        yield return new WinCEWindow(lastHandle);
    }

    public IEnumerable<WinCEControl> DescendantControls()
    {
        var nodes = new Queue<WinCEControl>(new[] { this });
        while (nodes.Any())
        {
            var node = nodes.Dequeue();

            if (node != this)
            {
                yield return node;
            }

            foreach (var n in node.Children()) nodes.Enqueue(n);
        }
    }

    public bool TextPresent(string text)
    {
        foreach (var descendantControl in DescendantControls())
        {
            if (descendantControl.Text == text)
            {
                return true;
            }
        }

        return false;
    }
}

My goal is to be able to perform UI tests against a running application on the CE device. If there is a solid C# library to achieve the same which works on Windows CE I am very hear.

Update: As mentioned in my comment I have failed to find a library or framework for automating foreign WinForms processes on the Win CE. I tried the "simple-wince-gui-automation" and it fails to retrieve the texts, too.

chiccodoro
  • 14,407
  • 19
  • 87
  • 130
  • 1
    Writing this kind of code yourself is unwise, this problem has of course been solved. Google "windows ce ui automation library" to get ahead. – Hans Passant Nov 08 '13 at 14:39
  • I have started to partially answer with C++ code using WinApi to get the "name" property of a WinForm Object. But it involves using the following APIs, RegisterWindowMessage, GetWindowThreadProcessId, OpenProcess, VirtualAllocEx, SendMessage, ReadProcessMemory, VirtualFreeEx and CloseHandle... May be NOT ok on Windows CE (don't know). Are you interested? – manuell Nov 08 '13 at 15:07
  • http://code.google.com/p/simple-wince-gui-automation/ – ctacke Nov 08 '13 at 16:47
  • @Hans: You are perfectly right in this regard. I took your google query and found the DATK/WMTK as well as the simple-wince-gui-automation quoted by ctacke. Unfortunately the DATK/WMTK are overly complicated and "underly" documented and I did not manage to make them run. The simple-wince-gui-automation looks slick and lightweight but suffers of exactly the same issue that I described in my question: All elements retrieved have empty texts. – chiccodoro Nov 13 '13 at 14:09

0 Answers0