ただし、画像とキャプションのないボタンを使用する場合があります。キャプションがない場合、スクリーンリーダーは何も言いません。スクリーンリーダーがこのボタンの意味を伝えるようにするにはどうすればよいですか?
IAccessible
ボタンの実装は、スクリーンリーダーに必要なテキストを提供する必要があります。デフォルトでは、OSにはボタンを含む多くのUIコントロールのデフォルトのIAccessible
実装が用意されています。
だから、あなたができる簡単な一のトリックは、手動ボタンを-描く所有者になり、その後は正常に使用するデフォルトIAccessible
実装のための標準Caption
を設定することができ、そしてときに、あなたは単にCaption
が含まれていませんでしたボタンを描く。
WM_GETOBJECT
メッセージを直接処理して、ボタンのデフォルトのIAccessible
の実装を取得し、それをラップして、必要なテキストを返すことができ、他のすべてをデフォルト実装に委譲することができます。例えば:
type
TMyAccessibleText = class(TInterfacedObject, IAccessible)
private
fAcc: IAccessible;
fAccessibleText: string;
public:
constructor Create(Acc: IAccessible; AccessibleText: string);
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 TMyAccessibleText.Create(Acc: IAccessible; AccessibleText: string);
begin
inherited Create;
fAcc := Acc;
fAccessibleText := AccessibleText;
end;
function TMyAccessibleText.QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
begin
if IID = IID_IAccessible then
Result := inherited QueryInterface(IID, Obj)
else
Result := fAcc.QueryInterface(IID, Obj);
end;
function TMyAccessibleText.GetTypeInfoCount(out Count: Integer): HResult; stdcall;
begin
Result := fAcc.GetTypeInfoCount(Count);
end;
function TMyAccessibleText.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
begin
Result := fAcc.GetTypeInfo(Index, LocaleID, TypeInfo);
end;
function TMyAccessibleText.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
begin
Result := fAcc.GetIDsOfNames(IID, Names, NameCount, LocaleID, DispIDs);
end;
function TMyAccessibleText.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
begin
Result := fAcc.Invoke(DispID, IID, LocaleID, Flags, Params, VarResult, ExcepInfo, ArgErr);
end;
function TMyAccessibleText.Get_accParent(out ppdispParent: IDispatch): HResult; stdcall;
begin
Result := fAcc.Get_accParent(ppdispParent);
end;
function TMyAccessibleText.Get_accChildCount(out pcountChildren: Integer): HResult; stdcall;
begin
Result := fAcc.Get_accChildCount(pcountChildren);
end;
function TMyAccessibleText.Get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HResult; stdcall;
begin
Result := fAcc.Get_accChild(varChild, ppdispChild);
end;
function TMyAccessibleText.Get_accName(varChild: OleVariant; out pszName: WideString): HResult; stdcall;
begin
Result := fAcc.Get_accName(varChild, pszName);
end;
function TMyAccessibleText.Get_accValue(varChild: OleVariant; out pszValue: WideString): HResult; stdcall;
begin
if varChild = CHILDID_SELF then
begin
pszValue := fAccessibleText;
Result := S_OK;
end else
Result := fAcc.Get_accValue(varChild, pszValue);
end;
function TMyAccessibleText.Get_accDescription(varChild: OleVariant; out pszDescription: WideString): HResult; stdcall;
begin
Result := fAcc.Get_accDescription(varChild, pszDescription);
end;
function TMyAccessibleText.Get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HResult; stdcall;
begin
Result := fAcc.Get_accRole(varChild, pvarRole);
end;
function TMyAccessibleText.Get_accState(varChild: OleVariant; out pvarState: OleVariant): HResult; stdcall;
begin
Result := fAcc.Get_accState(varChild, pvarState);
end;
function TMyAccessibleText.Get_accHelp(varChild: OleVariant; out pszHelp: WideString): HResult; stdcall;
begin
Result := fAcc.Get_accHelp(varChild, pszHelp);
end;
function TMyAccessibleText.Get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HResult; stdcall;
begin
Result := fAcc.Get_accHelpTopic(pszHelpFile, varChild, pidTopic);
end;
function TMyAccessibleText.Get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HResult; stdcall;
begin
Result := fAcc.Get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
end;
function TMyAccessibleText.Get_accFocus(out pvarChild: OleVariant): HResult; stdcall;
begin
Result := fAcc.Get_accFocus(pvarChild);
end;
function TMyAccessibleText.Get_accSelection(out pvarChildren: OleVariant): HResult; stdcall;
begin
Result := fAcc.Get_accSelection(pvarChildren);
end;
function TMyAccessibleText.Get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HResult; stdcall;
begin
Result := fAcc.Get_accDefaultAction(varChild, pszDefaultAction);
end;
function TMyAccessibleText.accSelect(flagsSelect: Integer; varChild: OleVariant): HResult; stdcall;
begin
Result := fAcc.accSelect(flagsSelect, varChild);
end;
function TMyAccessibleText.accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer; out pcyHeight: Integer; varChild: OleVariant): HResult; stdcall;
begin
Result := fAcc.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild);
end;
function TMyAccessibleText.accNavigate(navDir: Integer; varStart: OleVariant; out pvarEndUpAt: OleVariant): HResult; stdcall;
begin
Result := fAcc.accNavigate(navDir, varStart, pvarEndUpAt);
end;
function TMyAccessibleText.accHitTest(xLeft: Integer; yTop: Integer; out pvarChild: OleVariant): HResult; stdcall;
begin
Result := fAcc.accHitTest(xLeft, yTop, pvarChild);
end;
function TMyAccessibleText.accDoDefaultAction(varChild: OleVariant): HResult; stdcall;
begin
Result := fAcc.accDoDefaultAction(varChild);
end;
function TMyAccessibleText.Set_accName(varChild: OleVariant; const pszName: WideString): HResult; stdcall;
begin
Result := fAcc.Set_accName(varChild, pszName);
end;
function TMyAccessibleText.Set_accValue(varChild: OleVariant; const pszValue: WideString): HResult; stdcall;
begin
if varChild = CHILDID_SELF then
begin
fAccessibleText := pszValue;
Result := S_OK;
end else
Result := fAcc.Set_accValue(varChild, pszValue);
end;
のTGraphicから派生形態の画像についても同様
type
TBitBtn = class(Vcl.Buttons.TBitBtn)
private
procedure WMGetObject(var Message: TMessage): message WM_GETOBJECT;
public
MyAccessibleText: string;
end;
TMyForm = class(TForm)
Button1: TBitBtn;
...
procedure FormCreate(Sender: TObject);
...
end;
procedure TMyForm.FormCreate(Sender: TObject);
begin
Button1.MyAccessibleText := 'There is an image here';
end;
procedure TBitBtn.WMGetObject(var Message: TMessage);
var
Acc: IAccessible;
begin
inherited;
if (Message.LParam = OBJID_CLIENT) and (Message.Result > 0) and (Caption = '') and (MyAccessibleText <> '') then
begin
if ObjectFromLresult(Message.Result, IAccessible, Message.WParam, Acc) = S_OK then
begin
Acc := TMyAccessibleText.Create(Acc, MyAccessibleText) as IAccessible;
Message.Result := LresultFromObject(IAccessible, Message.WParam, Acc);
end;
end;
end;
。オブジェクトがフォーカスを取得したときに何を言うべきかをスクリーンリーダーに伝えるにはどうすればよいですか?
まず、TGraphic
はコンポーネントクラスではありません。これは、TPicture
によって使用される画像データのラッパーであり、それ自体は例えばTImage
によって使用されるヘルパーです。代わりにTGraphicControl
を意味すると仮定します(TImage
から派生します)。
TGraphicControl
ベースのコンポーネントは、独自のウィンドウを持たないため、デフォルトでスクリーンリーダーに直接アクセスすることはできず、OS自体にも知られていません。
スクリーンリーダーをグラフィカルコントロールとやり取りする場合は、Parent
コンポーネント(ウィンドウはあります)からIAccessible
の完全実装を提供し、そのグラフィカルな子どもに関する追加のアクセシビリティ情報を公開する必要があります。
私はIAccessibleラッパーを調べましたが、できる限り使用しているすべてのコントロールを拡張したくないです。
申し訳ありませんが、必要な処理を行うサードパーティの実装が見つからない限り、必要があります。 VCLは単にIAccessible
の機能を実装していないため、OSが提供する機能を超えてカスタマイズする必要がある場合は、独自のコードで手動で実装する必要があります。
'TGraphic'はフォーカスを取得できません。コンポーネントでもありません。あなたはおそらく 'TGraphicControl'と言うことになりますが、これはまだフォーカスを得ることができません。それは 'TGraphicControl'の主な目的の一つです。 –
ありがとうございました。私は本当にTGraphicControlを意味し、それに応じて質問を更新しました。私はコントロールの上にマウスを意味し、フォーカスを取得しませんでした。 TGraphicControlsのある種のaltテキストをフォーム上で処理するために他の人が考え出したアイディアを知りたいのです。 –