Lo stesso VCL non implementa nativamente alcun supporto per MSAA. Windows fornisce le implementazioni predefinite per i controlli dell'interfaccia utente standard, che includono molti componenti VCL standard. Se hai bisogno di più supporto MSAA di quello fornito da Windows, dovrai implementare l'interfaccia IAccessible
da solo, e quindi avere il tuo controllo rispondere al messaggio WM_GETOBJECT
in modo che possa restituire un puntatore a un'istanza della tua implementazione.
Update: Ad esempio, un modo per aggiungere MSAA a un TEdit
esistente (se non si vuole ricavare il proprio componente) potrebbe essere simile a questa:
uses
..., oleacc;
type
TMyAccessibleEdit = class(TInterfacedObject, IAccessible)
private
fEdit: TEdit;
fDefAcc: IAccessible;
public
constructor Create(aEdit: TEdit; aDefAcc: IAccessible);
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
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;
end;
constructor TMyAccessibleEdit.Create(aEdit: TEdit; aDefAcc: IAccessible);
begin
inherited Create;
fEdit := aEdit;
fDefAcc := aDefAcc;
end;
function TMyAccessibleEdit.QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
begin
if IID = IID_IAccessible then
Result := inherited QueryInterface(IID, Obj)
else
Result := fDefAcc.QueryInterface(IID, Obj);
end;
function TMyAccessibleEdit.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
begin
Result := fDefAcc.GetTypeInfoCount(Count);
end;
function TMyAccessibleEdit.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
begin
Result := fDefAcc.GetTypeInfo(Index, LocaleID, TypeInfo);
end;
function TMyAccessibleEdit.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
begin
Result := fDefAcc.GetIDsOfNames(IID, Names, NameCount, LocaleID, DispIDs);
end;
function TMyAccessibleEdit.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
begin
Result := fDefAcc.Invoke(DispID, IID, LocaleID, Flags, Params, VarResult, ExcepInfo, ArgErr);
end;
function TMyAccessibleEdit.Get_accParent(out ppdispParent: IDispatch): HResult; stdcall;
begin
Result := fDefAcc.Get_accParent(ppdispParent);
end;
function TMyAccessibleEdit.Get_accChildCount(out pcountChildren: Integer): HResult; stdcall;
begin
Result := fDefAcc.Get_accChildCount(pcountChildren);
end;
function TMyAccessibleEdit.Get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HResult; stdcall;
begin
Result := fDefAcc.Get_accChild(varChild, ppdispChild);
end;
function TMyAccessibleEdit.Get_accName(varChild: OleVariant; out pszName: WideString): HResult; stdcall;
begin
Result := fDefAcc.Get_accName(varChild, pszName);
if (Result = S_OK) and (pszName <> '') then Exit;
if Integer(varChild) = CHILDID_SELF then begin
pszName := fEdit.Name;
Result := S_OK;
end else
Result := S_FALSE;
end;
function TMyAccessibleEdit.Get_accValue(varChild: OleVariant; out pszValue: WideString): HResult; stdcall;
begin
Result := fDefAcc.Get_accValue(varChild, pszValue);
end;
function TMyAccessibleEdit.Get_accDescription(varChild: OleVariant; out pszDescription: WideString): HResult; stdcall;
begin
Result := fDefAcc.Get_accDescription(varChild, pszDescription);
if (Result = S_OK) and (pszDescription <> '') then Exit;
if Integer(varChild) = CHILDID_SELF then begin
pszDescription := fEdit.Hint;
Result := S_OK;
end else
Result := S_FALSE;
end;
function TMyAccessibleEdit.Get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.Get_accRole(varChild, pvarRole);
end;
function TMyAccessibleEdit.Get_accState(varChild: OleVariant; out pvarState: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.Get_accState(varChild, pvarState);
end;
function TMyAccessibleEdit.Get_accHelp(varChild: OleVariant; out pszHelp: WideString): HResult; stdcall;
begin
Result := fDefAcc.Get_accHelp(varChild, pszHelp);
end;
function TMyAccessibleEdit.Get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HResult; stdcall;
begin
Result := fDefAcc.Get_accHelpTopic(pszHelpFile, varChild, pidTopic);
end;
function TMyAccessibleEdit.Get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HResult; stdcall;
begin
Result := fDefAcc.Get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
end;
function TMyAccessibleEdit.Get_accFocus(out pvarChild: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.Get_accFocus(pvarChild);
end;
function TMyAccessibleEdit.Get_accSelection(out pvarChildren: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.Get_accSelection(pvarChildren);
end;
function TMyAccessibleEdit.Get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HResult; stdcall;
begin
Result := fDefAcc.Get_accDefaultAction(varChild, pszDefaultAction);
end;
function TMyAccessibleEdit.accSelect(flagsSelect: Integer; varChild: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.accSelect(flagsSelect, varChild);
end;
function TMyAccessibleEdit.accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer; out pcyHeight: Integer; varChild: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild);
end;
function TMyAccessibleEdit.accNavigate(navDir: Integer; varStart: OleVariant; out pvarEndUpAt: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.accNavigate(navDir, varStart, pvarEndUpAt);
end;
function TMyAccessibleEdit.accHitTest(xLeft: Integer; yTop: Integer; out pvarChild: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.accHitTest(xLeft, yTop, pvarChild);
end;
function TMyAccessibleEdit.accDoDefaultAction(varChild: OleVariant): HResult; stdcall;
begin
Result := fDefAcc.accDoDefaultAction(varChild);
end;
function TMyAccessibleEdit.Set_accName(varChild: OleVariant; const pszName: WideString): HResult; stdcall;
begin
Result := fDefAcc.Set_accName(varChild, pszName);
end;
function TMyAccessibleEdit.Set_accValue(varChild: OleVariant; const pszValue: WideString): HResult; stdcall;
begin
Result := fDefAcc.Set_accValue(varChild, pszValue);
end;
type
TMyForm = class(TForm)
procedure FormCreate(Sender: TObject);
...
private
DefEditWndProc: TWndMethod;
procedure EditWndProc(var Message: TMessage);
...
end;
procedure TMyForm.FormCreate(Sender: TObject);
begin
DefEditWndProc := Edit1.WindowProc;
Edit1.WindowProc := EditWndProc;
end;
procedure TMyForm.EditWndProc(var Message: TMessage);
var
DefAcc, MyAcc: IAccessible;
Ret: LRESULT;
begin
DefEditWndProc(Message);
if (Message.Msg = WM_GETOBJECT) and (Message.LParam = OBJID_CLIENT) and (Message.Result > 0) then
begin
if ObjectFromLresult(Message.Result, IAccessible, Message.WParam, DefAcc) = S_OK then
begin
MyAcc := TMyAccessibleEdit.Create(Edit1, DefAcc) as IAccessible;
Message.Result := LresultFromObject(IAccessible, Message.WParam, MyAcc);
end;
end;
end;
Vergognati per aver accettato la tua risposta invece di quella di Remy che ti ha portato alla soluzione del tuo problema! Dovresti dare credito dove è dovuto. La risposta dettagliata di Remy merita upvoting e accettazione. –