Information in this topic applies to desktop applications only. |
When TestComplete works with objects in Open Applications, it exposes all standard controls as well as their properties and methods automatically, and makes them easily accessible. However, the application you test may implement custom interfaces that TestComplete does not handle, or you may need to test an application that cannot be compiled as Open. This topic explains how you can prepare your application to work with the Microsoft Active Accessibility Support plugin manually, and how you can work directly with the object that the application returns.
Implementing IAccessible Interface Support in Tested Applications
To obtain Accessibility information about a window, the Microsoft Active Accessibility Support plugin retrieves the IAccessible
object associated with this window. To get a reference to the IAccessible
object, TestComplete calls the Windows API AccessibleObjectFromWindow
function with the OBJID_NATIVEOM
parameter. This function sends the WM_GETOBJECT
message to the window. The returned object is the one TestComplete uses.
The code that processes the WM_GETOBJECT
message can return any object that implements the IDispatch
interface or its descendants, and TestComplete will consider these methods and properties exposed by IAccessible
. In your tests, you can access these methods and properties through the NativeObject
property that TestComplete adds to the window.
The code below demonstrates how you can handle the WM_GETOBJECT message in your application. It returns an IAccessible
reference for a window.
Delphi
const
WM_GETOBJECT = $003D; // Windows MSAA message identifier
TForm1 = class(TForm)
...
procedure WMGetMSAAObject(var Message : TMessage); message WM_GETOBJECT;
...
end;
function LresultFromObject(const riid: TGUID; wParam: DWORD; pAcc: IUnknown): Integer; stdcall; external 'oleacc.dll';
...
implementation
...
procedure TForm1.WMGetMSAAObject(var Message: TMessage);
const
OBJID_NATIVEOM = $FFFFFFF0;
begin
if DWORD(Message.LParam) = OBJID_NATIVEOM then
// Returns the object which you want to obtain
// PIObject is a reference to the IDispatch interface implemented by the desired object
Message.Result := LresultFromObject(IDispatch, Message.WParam, PIObject);
else
Message.Result := DefWindowProc(Handle, Message.Msg, Message.WParam, Message.LParam);
end;
C#
// Include the needed assemblies
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace MSAAApplication
{
...
public class Form1 : System.Windows.Forms.Form
{
// Message identifiers
private const int WM_GETOBJECT = 0x003D;
private const uint OBJID_NATIVEOM = 0x0FFFFFFF0;
...
// Modified window procedure. Includes code for processing the WM_GETOBJECT message.
protected override void WndProc(ref Message m)
{
// Checks the message
if ((m.Msg == WM_GETOBJECT) & ((uint)m.LParam == OBJID_NATIVEOM))
{
// Obtains the GUID of the IDispatch interface
Guid g = new Guid(Win32.IID_IDispatch);
// Returns the object, which you want to obtain via MSAA
// IObjectDispatch is a reference to the IDispatch interface implemented by the desired object
m.Result=Win32.LresultFromObject(ref g, m.WParam, IObjectDispatch);
return;
}
else
{
// Calls the default window procedure
base.WndProc(ref m);
}
}
}
// A helper class needed to call Win32 API functions
public class Win32
{
// Imports the LresultFromObject function from oleacc.dll
[DllImport("oleacc.dll", CharSet=CharSet.Auto)]
public static extern IntPtr LresultFromObject(ref Guid riid, IntPtr wParam, [MarshalAs(UnmanagedType.IDispatch)] object pAcc);
// GUID of the IDispatch interface
public const string IID_IDispatch="00020400-0000-0000-C000-000000000046";
}
}
Visual Basic
' A data type for working with GUID values
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(7) As Byte
End Type
' Declarations of external functions
Private Declare Function CLSIDFromString Lib "OLE32" (ByVal lpszCLSID As Long, pclsid As GUID) As Long
Private Declare Function LresultFromObject Lib "oleacc.dll" (ByRef riid As GUID, ByVal wParam As Long, ByVal pAcc As Object) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Global glPrevWndProc As Long' Saves the address of the original window procedure
' Registers the modified window procedure
Public Function fSubClass() As Long
fSubClass = SetWindowLong(Form1.hwnd, GWL_WNDPROC, AddressOf pMyWindowProc)
End Function
' The following routine restores the original window procedure
Public Sub pUnSubClass()
Call SetWindowLong(Form1.hwnd, GWL_WNDPROC, glPrevWndProc)
End Sub
' A modified window procedure. Includes special processing of the WM_GETOBJECT message
Public Function pMyWindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
' Message identifiers
Const OBJID_NATIVEOM = &HFFFFFFF0
Const WM_GETOBJECT = &H3D
Dim hr As Long
Dim riid As GUID
' Checks the message
If (uMsg = WM_GETOBJECT) And (lParam = OBJID_NATIVEOM) Then
' Obtains the identifier of the IDispatch interface
hr = CLSIDFromString(StrPtr(IID_IDispatch), riid)
If hr <> 0 Then Err.Raise hr
' Returns the object, the reference to which you want to obtain via MSAA.
' Obj is a reference to the IDispatch interface implemented by the desired object.
' If Obj is empty, the application is terminated without displaying any error message
pMyWindowProc = LresultFromObject(riid, wParam, Obj)
Exit Function
End If
' Passes the message to the default window procedure
pMyWindowProc = CallWindowProc(glPrevWndProc, hw, uMsg, wParam, lParam)
End Function
Working With the Object Returned by the Application
You get access to methods and properties of the object, which the application returns, through the NativeObject
property that TestComplete appends to windows and controls. The methods and properties of the object become the methods and properties of the NativeObject
object. You can call them in tests using the syntax like MyWindowTestObj.NativeObject.Property_Name
.
You can view the available methods and properties in the Object Browser. To do this, simply click the ellipsis button of the NativeObject
property.
Note: | Some methods and properties can be hidden. To view them, enable the the Show hidden members option in the TestComplete Engines - General Options dialog. |
The following example demonstrates how you can use NativeObject
. The code snippet gets the accDescription
property of the Microsoft Word ribbon toolbar. The "Document1" file should be open in the Word application:
JavaScript, JScript
function Test()
{
// Get the object
var NativeObj = Sys.Process("WINWORD").Form("Document1 - Microsoft Word").Panel("MsoDockTop").ToolBar("Ribbon").NativeObject;
// Post its accDescription property to the log
Log.Message(NativeObj).accDescription(0);
}
Python
def Test():
# Get the object
NativeObj = Sys.Process("WINWORD").Form("Document1 - Microsoft Word").Panel("MsoDockTop").ToolBar("Ribbon").NativeObject
# Post its accDescription property to the log
Log.Message(NativeObj).accDescription(0)
VBScript
Sub Test
' Get the object
NativeObj = Sys.Process("WINWORD").Form("Document1 - Microsoft Word").Panel("MsoDockTop").ToolBar("Ribbon").NativeObject
' Post its accDescription property to the log
Log.Message(NativeObj.accDescription(0))
End Sub
DelphiScript
procedure Test();
var
NativeObj;
begin
// Get the object
NativeObj := Sys.Process('WINWORD').Form('Document1 - Microsoft Word').Panel('MsoDockTop').ToolBar('Ribbon').NativeObject.accDescription(0);
// Post its accDescription property to the log
Log.Message(NativeObj);
end;
C++Script, C#Script
function Test()
{
// Get the object
var NetiveObj = Sys["Process"]("WINWORD")["Form"]("Document1 - Microsoft Word")["Panel"]("MsoDockTop")["ToolBar"]("Ribbon")["NativeObject"]["accDescription"](0);
// Post its accDescription property to the log
Log["Message"](NetiveObj);
}
Working With Custom Objects Returned by the Application
When TestComplete requests an IAccessible
reference from a window or control, it actually sends a request for an IDispatch
object (IDispatch
is an ancestor of IAccessible
).
Your application can also return a different object as long as it is inherited from IDispatch
. This object can provide accessibility information or contain any other methods and properties. In your tests, you will access the methods and properties of this object through the NativeObject
property.
See Also
Using Microsoft Active Accessibility
About Using Microsoft Active Accessibility