Finally, the promised post.
Types of Controls
There are three types of controls you’ll discover when automating UI
How automation typically works
Automating UI requires three critical aspects:
These tasks can usually be achieved via Win32 API calls, MSAA, or in some cases, from the application’s object model when dealing with Standard Windows controls and Owner-drawn controls.
For example, consider capturing a regular button to verify its caption and what it does when clicked. You would first use a tool like Spy to find the control and to get information on the control, like its classname. From the automation framework, you would search for the window with this particular classname among all available windows to get its handle. Using the handle, you’ll be able to use Win32 API calls and MSAA calls to either manipulate the control, ie pressing the button using IAccessible::DoDefaultAction() or acquiring data from it, ie getting the button’s caption using GetWindowText().
But what happens if the control doesn’t have its own window?
Consider File Tabs on the File Tab Channel. See my post on the File Tab Channel for a picture of what this looks like. If you were to use Spy on the File Tab Channel, the first thing you’ll notice is that the individual file tabs do not have their own windows. There’s only one window (the File Tab Channel itself) that hosts the File Tabs. How does one capture the File Tabs if all of them are contained within the same window?
Use Test Hooks
Test hooks are “hidden” messages the developer will write into the application. I call these hidden because you have to ask the developer what messages to send to which window (or look at the code). The tester supplies the developer with a list of requirements, like being able to press the button or get the caption. And the developer in returns gives you back a set of messages to send to a given window that will produce the desired effect, like click the button or return the button’s caption.
Here’s how an automation framework might use the test hook to get the caption of a particular File Tab on the File Tab Channel.
Several things to note:
Const FileTabMessage As Integer = &H8000 + &H1001 ‘ WM_USER + test message app is expecting – note: this is just a number I made up
Const Text As Integer = 1
Const Click As Integer = 2
Private Function GetFileTabText(ByVal fileTabIndex As Integer) As String
‘ send message to test hook requesting the ATOM for the requested file tab’s caption
Dim atom As IntPtr = SendMessage(MainWindowHwnd, FileTabMessage, fileTabIndex, Text)
‘ convert ATOM to String
Dim buffer As New String(" "c, 255)
GlobalGetAtomName(atom.ToInt32, buffer, buffer.Length)
Return buffer.Substring(0, buffer.IndexOf(Nothing))