2014-02-19 288 views
1

創建可訪問的UI組件的問題這個問題是指給定的解決方案 Creating Accessible UI components in Delphi與德爾福

我試圖使用從上面的問題解決的最後一個問題(here)解決說明我的問題。在如圖所示實現了IAccessible接口之後,我進行了調試並很高興,當我嘗試通過外部程序(在這種情況下,Visual Studio的Coded UI測試記錄工具)讀取WinForm屬性時,看到接口被訪問。

可訪問的名稱被設置爲我想要的,但它以某種方式丟失了,因爲該名稱仍未在WinForm屬性中定義。


下面的代碼:

聲明:

TXControlEigenschaften = class (TInterfacedObject, IAccessible) 
strict private 
    FControl: IXControl; 

    FAccessibleName: string; 
    FAccessibleDescription: string; 
    // IAccessible 
    function Get_accParent(out ppdispParent: IDispatch): HResult; stdcall; 
    function Get_accChildCount(out pcountChildren: Integer): HResult; stdcall; 
    function Get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HResult; stdcall; 
    function Get_accName(varChild: OleVariant; out pszName: WideString): HResult; stdcall; 
    function Get_accValue(varChild: OleVariant; out pszValue: WideString): HResult; stdcall; 
    function Get_accDescription(varChild: OleVariant; out pszDescription: WideString): HResult; stdcall; 
    function Get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HResult; stdcall; 
    function Get_accState(varChild: OleVariant; out pvarState: OleVariant): HResult; stdcall; 
    function Get_accHelp(varChild: OleVariant; out pszHelp: WideString): HResult; stdcall; 
    function Get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; 
                 out pidTopic: Integer): HResult; stdcall; 
    function Get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HResult; stdcall; 
    function Get_accFocus(out pvarChild: OleVariant): HResult; stdcall; 
    function Get_accSelection(out pvarChildren: OleVariant): HResult; stdcall; 
    function Get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HResult; stdcall; 
    function accSelect(flagsSelect: Integer; varChild: OleVariant): HResult; stdcall; 
    function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer; 
              out pcyHeight: Integer; varChild: OleVariant): HResult; stdcall; 
    function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEndUpAt: OleVariant): HResult; stdcall; 
    function accHitTest(xLeft: Integer; yTop: Integer; out pvarChild: OleVariant): HResult; stdcall; 
    function accDoDefaultAction(varChild: OleVariant): HResult; stdcall; 
    function Set_accName(varChild: OleVariant; const pszName: WideString): HResult; stdcall; 
    function Set_accValue(varChild: OleVariant; const pszValue: WideString): HResult; stdcall; 

    function GetIDsOfNames(const IID: TGUID; Names: Pointer; 
    NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall; 
    function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall; 
    function GetTypeInfoCount(out Count: Integer): HResult; stdcall; 
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; 
    Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall; 

public 
    constructor Create(aControl: IXControl); 

    procedure WMGetMSAAObject(var Message : TMessage); message WM_GETOBJECT; 

    property AccessibleName: string read FAccessibleName write FAccessibleName; 
    property AccessibleDescription: string read FAccessibleDescription write FAccessibleDescription; 

end; 

了重要的實施情況:

procedure TXControlEigenschaften.WMGetMSAAObject(var Message: TMessage); 
begin 
    Message.Result := LresultFromObject(IID_IAccessible, Message.WParam, Self); 
end; 

function TXControlEigenschaften.Get_accName(varChild: OleVariant; out pszName: WideString): HResult; 
begin 
    pszName := ''; 
    Result := S_FALSE; 
    if varChild = CHILDID_SELF then 
    begin 
    if AccessibleName <> '' then 
     pszName := AccessibleName 
    else 
     pszName := FControl.Name; 
    result := S_OK; 
    end; 
end; 

創建的使用TEDIT的推導界面,這裏關於c頌:

TXCustomEdit = class(TCustomMaskEdit, IAccessible, IXControl, IXCtrlInterface, ITBXValidate, IXReadOnly, IXChange, 
        IXDelete, IXCut, IXPaste, IXSelectAll, IXVisible, IComboEdit 
        {$IFNDEF PACKAGE}, IXDPISkalierung, IExtrafeldControl{$ENDIF PACKAGE}) 

strict private 
    procedure WMGetMSAAObject(var Message : TMessage); message WM_GETOBJECT; 
    FAccessible: IAccessible; 
... 

implementation 

constructor TXCustomEdit.Create(AOwner: TComponent); 
var 
    ce: TXControlEigenschaften; 
begin 
    ... 
    FSkalierungsZustand := TSkalierungsZustand.Create(Self); 
end; 

... 

procedure TXCustomEdit.WMGetMSAAObject(var Message: TMessage); 
begin 
    (FAccessible as TXControlEigenschaften).WMGetMSAAObject(Message); 
end; 

順便說一句,這只是一個調試解決方案,所以我會改變的東西,如消息後處理。

有人有一個想法,爲什麼我仍然在WinForms-Properties中得到一個空的名稱?

+0

是否執行了「TXCustomEdit.WMGetMSAAObject」? –

+0

是的,它也可以,並且我也可以調試到TXControlEigenschaften的get_accname並且名稱設置爲 –

+0

剛剛發生了一些奇怪的事情:當我嘗試讀取Objects屬性後,通過對每個TXControlEigenschaften.WMGetMSAAObject調用進行調試時,名稱出現在我的財產清單。當我禁用斷點時,它不顯示名稱。 現在它變得荒謬...... –

回答

0

我解決了這個問題,只是返回DISP_E_MEMBERNOTFOUNDGet_accState,而不是採取在this article提供的代碼。這適用於名稱,但通過像AutoIt這樣的工具選擇組件或用於編碼用戶界面的Visual Studio測試生成器將會變得更加困難。

所以它更多的解決方法,然後一個真正的解決方案。

我對這個問題here打開了一個新問題,因爲原來的問題已經解決了。