TB2Acc.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224
  1. unit TB2Acc;
  2. {
  3. Toolbar2000
  4. Copyright (C) 1998-2005 by Jordan Russell
  5. All rights reserved.
  6. The contents of this file are subject to the "Toolbar2000 License"; you may
  7. not use or distribute this file except in compliance with the
  8. "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
  9. TB2k-LICENSE.txt or at:
  10. http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
  11. Alternatively, the contents of this file may be used under the terms of the
  12. GNU General Public License (the "GPL"), in which case the provisions of the
  13. GPL are applicable instead of those in the "Toolbar2000 License". A copy of
  14. the GPL may be found in GPL-LICENSE.txt or at:
  15. http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt
  16. If you wish to allow use of your version of this file only under the terms of
  17. the GPL and not to allow others to use your version of this file under the
  18. "Toolbar2000 License", indicate your decision by deleting the provisions
  19. above and replace them with the notice and other provisions required by the
  20. GPL. If you do not delete the provisions above, a recipient may use your
  21. version of this file under either the "Toolbar2000 License" or the GPL.
  22. $jrsoftware: tb2k/Source/TB2Acc.pas,v 1.7 2005/01/06 03:56:50 jr Exp $
  23. This unit is used internally to implement the IAccessible interface on
  24. TTBView and TTBItemViewer for Microsoft Active Accessibility support.
  25. }
  26. interface
  27. {$I TB2Ver.inc}
  28. uses
  29. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  30. TB2Item;
  31. type
  32. { Our declaration for IAccessible }
  33. ITBAccessible = interface(IDispatch)
  34. ['{618736E0-3C3D-11CF-810C-00AA00389B71}']
  35. function get_accParent(out ppdispParent: IDispatch): HRESULT; stdcall;
  36. function get_accChildCount(out pcountChildren: Integer): HRESULT; stdcall;
  37. function get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HRESULT; stdcall;
  38. function get_accName(varChild: OleVariant; out pszName: WideString): HRESULT; stdcall;
  39. function get_accValue(varChild: OleVariant; out pszValue: WideString): HRESULT; stdcall;
  40. function get_accDescription(varChild: OleVariant; out pszDescription: WideString): HRESULT; stdcall;
  41. function get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HRESULT; stdcall;
  42. function get_accState(varChild: OleVariant; out pvarState: OleVariant): HRESULT; stdcall;
  43. function get_accHelp(varChild: OleVariant; out pszHelp: WideString): HRESULT; stdcall;
  44. function get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HRESULT; stdcall;
  45. function get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HRESULT; stdcall;
  46. function get_accFocus(out pvarID: OleVariant): HRESULT; stdcall;
  47. function get_accSelection(out pvarChildren: OleVariant): HRESULT; stdcall;
  48. function get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HRESULT; stdcall;
  49. function accSelect(flagsSelect: Integer; varChild: OleVariant): HRESULT; stdcall;
  50. function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer;
  51. out pcyHeight: Integer; varChild: OleVariant): HRESULT; stdcall;
  52. function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEnd: OleVariant): HRESULT; stdcall;
  53. function accHitTest(xLeft: Integer; yTop: Integer; out pvarID: OleVariant): HRESULT; stdcall;
  54. function accDoDefaultAction(varChild: OleVariant): HRESULT; stdcall;
  55. function put_accName(varChild: OleVariant; const pszName: WideString): HRESULT; stdcall;
  56. function put_accValue(varChild: OleVariant; const pszValue: WideString): HRESULT; stdcall;
  57. end;
  58. TTBCustomAccObject = class(TTBBaseAccObject, IUnknown, IDispatch)
  59. private
  60. FPrevious, FNext: TTBCustomAccObject;
  61. public
  62. constructor Create;
  63. destructor Destroy; override;
  64. end;
  65. TTBViewAccObject = class(TTBCustomAccObject, IUnknown, IDispatch, ITBAccessible)
  66. private
  67. FView: TTBView;
  68. function Check(const varChild: OleVariant; var ErrorCode: HRESULT): Boolean;
  69. { ITBAccessible }
  70. function accDoDefaultAction(varChild: OleVariant): HRESULT; stdcall;
  71. function accHitTest(xLeft: Integer; yTop: Integer; out pvarID: OleVariant): HRESULT; stdcall;
  72. function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer;
  73. out pcyHeight: Integer; varChild: OleVariant): HRESULT; stdcall;
  74. function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEnd: OleVariant): HRESULT; stdcall;
  75. function accSelect(flagsSelect: Integer; varChild: OleVariant): HRESULT; stdcall;
  76. function get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HRESULT; stdcall;
  77. function get_accChildCount(out pcountChildren: Integer): HRESULT; stdcall;
  78. function get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HRESULT; stdcall;
  79. function get_accDescription(varChild: OleVariant; out pszDescription: WideString): HRESULT; stdcall;
  80. function get_accFocus(out pvarID: OleVariant): HRESULT; stdcall;
  81. function get_accHelp(varChild: OleVariant; out pszHelp: WideString): HRESULT; stdcall;
  82. function get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HRESULT; stdcall;
  83. function get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HRESULT; stdcall;
  84. function get_accName(varChild: OleVariant; out pszName: WideString): HRESULT; stdcall;
  85. function get_accParent(out ppdispParent: IDispatch): HRESULT; stdcall;
  86. function get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HRESULT; stdcall;
  87. function get_accSelection(out pvarChildren: OleVariant): HRESULT; stdcall;
  88. function get_accState(varChild: OleVariant; out pvarState: OleVariant): HRESULT; stdcall;
  89. function get_accValue(varChild: OleVariant; out pszValue: WideString): HRESULT; stdcall;
  90. function put_accName(varChild: OleVariant; const pszName: WideString): HRESULT; stdcall;
  91. function put_accValue(varChild: OleVariant; const pszValue: WideString): HRESULT; stdcall;
  92. public
  93. constructor Create(AView: TTBView);
  94. destructor Destroy; override;
  95. procedure ClientIsDestroying; override;
  96. end;
  97. TTBItemViewerAccObject = class(TTBCustomAccObject, IUnknown, IDispatch, ITBAccessible)
  98. private
  99. FViewer: TTBItemViewer;
  100. function Check(const varChild: OleVariant; var ErrorCode: HRESULT): Boolean;
  101. function IsActionable: Boolean;
  102. function IsAvailable: Boolean;
  103. function IsFocusable: Boolean;
  104. { ITBAccessible }
  105. function accDoDefaultAction(varChild: OleVariant): HRESULT; stdcall;
  106. function accHitTest(xLeft: Integer; yTop: Integer; out pvarID: OleVariant): HRESULT; stdcall;
  107. function accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer;
  108. out pcyHeight: Integer; varChild: OleVariant): HRESULT; stdcall;
  109. function accNavigate(navDir: Integer; varStart: OleVariant; out pvarEnd: OleVariant): HRESULT; stdcall;
  110. function accSelect(flagsSelect: Integer; varChild: OleVariant): HRESULT; stdcall;
  111. function get_accChild(varChild: OleVariant; out ppdispChild: IDispatch): HRESULT; stdcall;
  112. function get_accChildCount(out pcountChildren: Integer): HRESULT; stdcall;
  113. function get_accDefaultAction(varChild: OleVariant; out pszDefaultAction: WideString): HRESULT; stdcall;
  114. function get_accDescription(varChild: OleVariant; out pszDescription: WideString): HRESULT; stdcall;
  115. function get_accFocus(out pvarID: OleVariant): HRESULT; stdcall;
  116. function get_accHelp(varChild: OleVariant; out pszHelp: WideString): HRESULT; stdcall;
  117. function get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant; out pidTopic: Integer): HRESULT; stdcall;
  118. function get_accKeyboardShortcut(varChild: OleVariant; out pszKeyboardShortcut: WideString): HRESULT; stdcall;
  119. function get_accName(varChild: OleVariant; out pszName: WideString): HRESULT; stdcall;
  120. function get_accParent(out ppdispParent: IDispatch): HRESULT; stdcall;
  121. function get_accRole(varChild: OleVariant; out pvarRole: OleVariant): HRESULT; stdcall;
  122. function get_accSelection(out pvarChildren: OleVariant): HRESULT; stdcall;
  123. function get_accState(varChild: OleVariant; out pvarState: OleVariant): HRESULT; stdcall;
  124. function get_accValue(varChild: OleVariant; out pszValue: WideString): HRESULT; stdcall;
  125. function put_accName(varChild: OleVariant; const pszName: WideString): HRESULT; stdcall;
  126. function put_accValue(varChild: OleVariant; const pszValue: WideString): HRESULT; stdcall;
  127. public
  128. constructor Create(AViewer: TTBItemViewer);
  129. destructor Destroy; override;
  130. procedure ClientIsDestroying; override;
  131. procedure HandleAccSelect(const AExecute: Boolean);
  132. end;
  133. procedure CallNotifyWinEvent(event: DWORD; hwnd: HWND; idObject: DWORD;
  134. idChild: Longint);
  135. function InitializeOleAcc: Boolean;
  136. var
  137. LresultFromObjectFunc: function(const riid: TGUID; wParam: WPARAM;
  138. pUnk: IUnknown): LRESULT; stdcall;
  139. AccessibleObjectFromWindowFunc: function(hwnd: HWND; dwId: DWORD;
  140. const riid: TGUID; out ppvObject: Pointer): HRESULT; stdcall;
  141. { For debugging purposes only: }
  142. ViewAccObjectInstances: Integer = 0;
  143. ItemViewerAccObjectInstances: Integer = 0;
  144. implementation
  145. uses
  146. {$IFDEF JR_D6} Variants, {$ENDIF} ActiveX, Menus, TB2Common;
  147. const
  148. { Constants from OleAcc.h }
  149. ROLE_SYSTEM_MENUBAR = $2;
  150. ROLE_SYSTEM_CLIENT = $a;
  151. ROLE_SYSTEM_MENUPOPUP = $b;
  152. ROLE_SYSTEM_MENUITEM = $c;
  153. ROLE_SYSTEM_SEPARATOR = $15;
  154. ROLE_SYSTEM_TOOLBAR = $16;
  155. ROLE_SYSTEM_PUSHBUTTON = $2b;
  156. ROLE_SYSTEM_BUTTONMENU = $39;
  157. STATE_SYSTEM_HASPOPUP = $40000000;
  158. NAVDIR_UP = 1;
  159. NAVDIR_DOWN = 2;
  160. NAVDIR_LEFT = 3;
  161. NAVDIR_RIGHT = 4;
  162. NAVDIR_NEXT = 5;
  163. NAVDIR_PREVIOUS = 6;
  164. NAVDIR_FIRSTCHILD = 7;
  165. NAVDIR_LASTCHILD = 8;
  166. SELFLAG_TAKEFOCUS = 1;
  167. type
  168. TControlAccess = class(TControl);
  169. TTBViewAccess = class(TTBView);
  170. TTBCustomItemAccess = class(TTBCustomItem);
  171. TTBItemViewerAccess = class(TTBItemViewer);
  172. var
  173. LastAccObject: TTBCustomAccObject; { last object in the linked list }
  174. LastAccObjectCritSect: TRTLCriticalSection;
  175. NotifyWinEventInited: BOOL;
  176. NotifyWinEventFunc: procedure(event: DWORD; hwnd: HWND; idObject: DWORD;
  177. idChild: Longint); stdcall;
  178. procedure CallNotifyWinEvent(event: DWORD; hwnd: HWND; idObject: DWORD;
  179. idChild: Longint);
  180. begin
  181. if not NotifyWinEventInited then begin
  182. NotifyWinEventFunc := GetProcAddress(GetModuleHandle(user32), 'NotifyWinEvent');
  183. InterlockedExchange(Integer(NotifyWinEventInited), Ord(True));
  184. end;
  185. if Assigned(NotifyWinEventFunc) then
  186. NotifyWinEventFunc(event, hwnd, idObject, idChild);
  187. end;
  188. var
  189. OleAccInited: BOOL;
  190. OleAccAvailable: BOOL;
  191. function InitializeOleAcc: Boolean;
  192. var
  193. M: HMODULE;
  194. begin
  195. if not OleAccInited then begin
  196. M := {$IFDEF JR_D5} SafeLoadLibrary {$ELSE} LoadLibrary {$ENDIF} ('oleacc.dll');
  197. if M <> 0 then begin
  198. LresultFromObjectFunc := GetProcAddress(M, 'LresultFromObject');
  199. AccessibleObjectFromWindowFunc := GetProcAddress(M, 'AccessibleObjectFromWindow');
  200. if Assigned(LresultFromObjectFunc) and
  201. Assigned(AccessibleObjectFromWindowFunc) then
  202. OleAccAvailable := True;
  203. end;
  204. InterlockedExchange(Integer(OleAccInited), Ord(True));
  205. end;
  206. Result := OleAccAvailable;
  207. end;
  208. function AccObjectFromWindow(const Wnd: HWND; out ADisp: IDispatch): Boolean;
  209. var
  210. P: Pointer;
  211. begin
  212. if Assigned(AccessibleObjectFromWindowFunc) and
  213. (AccessibleObjectFromWindowFunc(Wnd, OBJID_WINDOW, IDispatch, P) = S_OK) then begin
  214. ADisp := IDispatch(P);
  215. IDispatch(P)._Release;
  216. Result := True;
  217. end
  218. else
  219. Result := False;
  220. end;
  221. procedure DisconnectAccObjects;
  222. { This procedure calls CoDisconnectObject() on all acc. objects still
  223. allocated. This is needed to prevent potential AV's when TB2k is compiled
  224. into a DLL, since a DLL may be freed by the application while an MSAA
  225. client still holds acc. object references. }
  226. var
  227. Obj, PrevObj: TTBCustomAccObject;
  228. begin
  229. Obj := LastAccObject;
  230. while Assigned(Obj) do begin
  231. { Make a copy of Obj.FPrevious since CoDisconnectObject may cause Obj
  232. to be freed }
  233. PrevObj := Obj.FPrevious;
  234. { CoDisconnectObject should cause remote MSAA clients to release all
  235. references to the object, thus destroying it (assuming the local
  236. application doesn't have references of its own). }
  237. CoDisconnectObject(Obj, 0);
  238. Obj := PrevObj;
  239. end;
  240. end;
  241. function GetAltKeyName: String;
  242. { This silly function is needed since ShortCutToText(VK_MENU) fails on Delphi
  243. and C++Builder versions <= 4 }
  244. var
  245. ScanCode: UINT;
  246. KeyName: array[0..255] of Char;
  247. begin
  248. ScanCode := MapVirtualKey(VK_MENU, 0) shl 16;
  249. if (ScanCode <> 0) and
  250. (GetKeyNameText(ScanCode, KeyName, SizeOf(KeyName)) > 0) then
  251. Result := KeyName
  252. else
  253. Result := 'Alt'; { shouldn't get here, but just in case... }
  254. end;
  255. { TTBCustomAccObject }
  256. constructor TTBCustomAccObject.Create;
  257. begin
  258. inherited Create;
  259. { Add Self to linked list of objects }
  260. EnterCriticalSection(LastAccObjectCritSect);
  261. try
  262. FPrevious := LastAccObject;
  263. if Assigned(FPrevious) then
  264. FPrevious.FNext := Self;
  265. LastAccObject := Self;
  266. finally
  267. LeaveCriticalSection(LastAccObjectCritSect);
  268. end;
  269. end;
  270. destructor TTBCustomAccObject.Destroy;
  271. begin
  272. { Remove Self from linked list of objects }
  273. EnterCriticalSection(LastAccObjectCritSect);
  274. try
  275. if LastAccObject = Self then
  276. LastAccObject := FPrevious;
  277. if Assigned(FPrevious) then
  278. FPrevious.FNext := FNext;
  279. if Assigned(FNext) then
  280. FNext.FPrevious := FPrevious;
  281. finally
  282. LeaveCriticalSection(LastAccObjectCritSect);
  283. end;
  284. inherited;
  285. end;
  286. { TTBViewAccObject }
  287. constructor TTBViewAccObject.Create(AView: TTBView);
  288. begin
  289. inherited Create;
  290. FView := AView;
  291. InterlockedIncrement(ViewAccObjectInstances);
  292. end;
  293. destructor TTBViewAccObject.Destroy;
  294. begin
  295. InterlockedDecrement(ViewAccObjectInstances);
  296. if Assigned(FView) then begin
  297. TTBViewAccess(FView).FAccObjectInstance := nil;
  298. FView := nil;
  299. end;
  300. inherited;
  301. end;
  302. procedure TTBViewAccObject.ClientIsDestroying;
  303. begin
  304. FView := nil;
  305. end;
  306. function TTBViewAccObject.Check(const varChild: OleVariant;
  307. var ErrorCode: HRESULT): Boolean;
  308. begin
  309. if FView = nil then begin
  310. ErrorCode := E_FAIL;
  311. Result := False;
  312. end
  313. else if (VarType(varChild) <> varInteger) or (varChild <> CHILDID_SELF) then begin
  314. ErrorCode := E_INVALIDARG;
  315. Result := False;
  316. end
  317. else
  318. Result := True;
  319. end;
  320. function TTBViewAccObject.accDoDefaultAction(varChild: OleVariant): HRESULT;
  321. begin
  322. Result := S_FALSE;
  323. end;
  324. function TTBViewAccObject.accHitTest(xLeft, yTop: Integer;
  325. out pvarID: OleVariant): HRESULT;
  326. var
  327. ViewWnd, W: HWND;
  328. R: TRect;
  329. P: TPoint;
  330. D: IDispatch;
  331. V: TTBItemViewer;
  332. begin
  333. try
  334. if FView = nil then begin
  335. Result := E_FAIL;
  336. Exit;
  337. end;
  338. ViewWnd := FView.Window.Handle;
  339. GetWindowRect(ViewWnd, R);
  340. P.X := xLeft;
  341. P.Y := yTop;
  342. if PtInRect(R, P) then begin
  343. P := FView.Window.ScreenToClient(P);
  344. W := ChildWindowFromPointEx(ViewWnd, P, CWP_SKIPINVISIBLE);
  345. if (W <> 0) and (W <> ViewWnd) then begin
  346. { Point is inside a child window (most likely belonging to a
  347. TTBControlItem) }
  348. if AccObjectFromWindow(W, D) then begin
  349. pvarID := D;
  350. Result := S_OK;
  351. end
  352. else
  353. Result := E_UNEXPECTED;
  354. end
  355. else begin
  356. V := FView.ViewerFromPoint(P);
  357. if Assigned(V) then
  358. pvarID := V.GetAccObject
  359. else
  360. pvarID := CHILDID_SELF;
  361. Result := S_OK;
  362. end;
  363. end
  364. else
  365. Result := S_FALSE;
  366. except
  367. Result := E_UNEXPECTED;
  368. end;
  369. end;
  370. function TTBViewAccObject.accLocation(out pxLeft, pyTop, pcxWidth,
  371. pcyHeight: Integer; varChild: OleVariant): HRESULT;
  372. var
  373. R: TRect;
  374. begin
  375. try
  376. if not Check(varChild, Result) then
  377. Exit;
  378. GetWindowRect(FView.Window.Handle, R);
  379. pxLeft := R.Left;
  380. pyTop := R.Top;
  381. pcxWidth := R.Right - R.Left;
  382. pcyHeight := R.Bottom - R.Top;
  383. Result := S_OK;
  384. except
  385. Result := E_UNEXPECTED;
  386. end;
  387. end;
  388. function TTBViewAccObject.accNavigate(navDir: Integer; varStart: OleVariant;
  389. out pvarEnd: OleVariant): HRESULT;
  390. var
  391. I: Integer;
  392. begin
  393. try
  394. if not Check(varStart, Result) then
  395. Exit;
  396. Result := S_FALSE;
  397. case navDir of
  398. NAVDIR_FIRSTCHILD: begin
  399. for I := 0 to FView.ViewerCount-1 do
  400. if FView.Viewers[I].IsAccessible then begin
  401. pvarEnd := FView.Viewers[I].GetAccObject;
  402. Result := S_OK;
  403. Break;
  404. end;
  405. end;
  406. NAVDIR_LASTCHILD: begin
  407. for I := FView.ViewerCount-1 downto 0 do
  408. if FView.Viewers[I].IsAccessible then begin
  409. pvarEnd := FView.Viewers[I].GetAccObject;
  410. Result := S_OK;
  411. Break;
  412. end;
  413. end;
  414. end;
  415. except
  416. Result := E_UNEXPECTED;
  417. end;
  418. end;
  419. function TTBViewAccObject.accSelect(flagsSelect: Integer;
  420. varChild: OleVariant): HRESULT;
  421. begin
  422. Result := DISP_E_MEMBERNOTFOUND;
  423. end;
  424. function TTBViewAccObject.get_accChild(varChild: OleVariant;
  425. out ppdispChild: IDispatch): HRESULT;
  426. var
  427. I, J: Integer;
  428. Viewer: TTBItemViewer;
  429. Ctl: TControl;
  430. begin
  431. try
  432. if FView = nil then begin
  433. Result := E_FAIL;
  434. Exit;
  435. end;
  436. if VarType(varChild) <> varInteger then begin
  437. Result := E_INVALIDARG;
  438. Exit;
  439. end;
  440. I := varChild;
  441. if I = CHILDID_SELF then begin
  442. ppdispChild := Self;
  443. Result := S_OK;
  444. end
  445. else begin
  446. { Convert a one-based child index (I) into a real viewer index (J) }
  447. J := 0;
  448. while J < FView.ViewerCount do begin
  449. if FView.Viewers[J].IsAccessible then begin
  450. if I = 1 then Break;
  451. Dec(I);
  452. end;
  453. Inc(J);
  454. end;
  455. if J >= FView.ViewerCount then begin
  456. { 'I' was either negative or too high }
  457. Result := E_INVALIDARG;
  458. Exit;
  459. end;
  460. Viewer := FView.Viewers[J];
  461. if Viewer.Item is TTBControlItem then begin
  462. { For windowed controls, return the window's accessible object instead
  463. of the item viewer's }
  464. Ctl := TTBControlItem(Viewer.Item).Control;
  465. if (Ctl is TWinControl) and TWinControl(Ctl).HandleAllocated then begin
  466. if AccObjectFromWindow(TWinControl(Ctl).Handle, ppdispChild) then
  467. Result := S_OK
  468. else
  469. Result := E_UNEXPECTED;
  470. Exit;
  471. end;
  472. end;
  473. ppdispChild := Viewer.GetAccObject;
  474. Result := S_OK;
  475. end;
  476. except
  477. Result := E_UNEXPECTED;
  478. end;
  479. end;
  480. function TTBViewAccObject.get_accChildCount(out pcountChildren: Integer): HRESULT;
  481. var
  482. Count, I: Integer;
  483. begin
  484. try
  485. if Assigned(FView) then begin
  486. Count := 0;
  487. for I := 0 to FView.ViewerCount-1 do
  488. if FView.Viewers[I].IsAccessible then
  489. Inc(Count);
  490. pCountChildren := Count;
  491. Result := S_OK;
  492. end
  493. else
  494. Result := E_FAIL;
  495. except
  496. Result := E_UNEXPECTED;
  497. end;
  498. end;
  499. function TTBViewAccObject.get_accDefaultAction(varChild: OleVariant;
  500. out pszDefaultAction: WideString): HRESULT;
  501. begin
  502. Result := S_FALSE;
  503. end;
  504. function TTBViewAccObject.get_accDescription(varChild: OleVariant;
  505. out pszDescription: WideString): HRESULT;
  506. begin
  507. Result := S_FALSE;
  508. end;
  509. function TTBViewAccObject.get_accFocus(out pvarID: OleVariant): HRESULT;
  510. begin
  511. Result := S_FALSE;
  512. end;
  513. function TTBViewAccObject.get_accHelp(varChild: OleVariant;
  514. out pszHelp: WideString): HRESULT;
  515. begin
  516. Result := S_FALSE;
  517. end;
  518. function TTBViewAccObject.get_accHelpTopic(out pszHelpFile: WideString;
  519. varChild: OleVariant; out pidTopic: Integer): HRESULT;
  520. begin
  521. pidTopic := 0; { Delphi doesn't implicitly clear Integer 'out' parameters }
  522. Result := S_FALSE;
  523. end;
  524. function TTBViewAccObject.get_accKeyboardShortcut(varChild: OleVariant;
  525. out pszKeyboardShortcut: WideString): HRESULT;
  526. begin
  527. try
  528. if not Check(varChild, Result) then
  529. Exit;
  530. if vsMenuBar in FView.Style then begin
  531. pszKeyboardShortcut := GetAltKeyName;
  532. Result := S_OK;
  533. end
  534. else
  535. Result := S_FALSE;
  536. except
  537. Result := E_UNEXPECTED;
  538. end;
  539. end;
  540. function TTBViewAccObject.get_accName(varChild: OleVariant;
  541. out pszName: WideString): HRESULT;
  542. var
  543. S: String;
  544. begin
  545. try
  546. if not Check(varChild, Result) then
  547. Exit;
  548. if Assigned(FView.ParentView) and Assigned(FView.ParentView.OpenViewer) then
  549. S := StripAccelChars(TTBItemViewerAccess(FView.ParentView.OpenViewer).GetCaptionText);
  550. if S = '' then
  551. S := TControlAccess(FView.Window).Caption;
  552. pszName := S;
  553. Result := S_OK;
  554. except
  555. Result := E_UNEXPECTED;
  556. end;
  557. end;
  558. function TTBViewAccObject.get_accParent(out ppdispParent: IDispatch): HRESULT;
  559. begin
  560. try
  561. if Assigned(FView) then begin
  562. if Assigned(FView.ParentView) and Assigned(FView.ParentView.OpenViewer) then begin
  563. ppdispParent := FView.ParentView.OpenViewer.GetAccObject;
  564. Result := S_OK;
  565. end
  566. else begin
  567. if AccObjectFromWindow(FView.Window.Handle, ppdispParent) then
  568. Result := S_OK
  569. else
  570. Result := E_UNEXPECTED;
  571. end;
  572. end
  573. else
  574. Result := E_FAIL;
  575. except
  576. Result := E_UNEXPECTED;
  577. end;
  578. end;
  579. function TTBViewAccObject.get_accRole(varChild: OleVariant;
  580. out pvarRole: OleVariant): HRESULT;
  581. begin
  582. try
  583. if not Check(varChild, Result) then
  584. Exit;
  585. if FView.IsPopup then
  586. pvarRole := ROLE_SYSTEM_MENUPOPUP
  587. else begin
  588. if vsMenuBar in FView.Style then
  589. pvarRole := ROLE_SYSTEM_MENUBAR
  590. else
  591. pvarRole := ROLE_SYSTEM_TOOLBAR;
  592. end;
  593. Result := S_OK;
  594. except
  595. Result := E_UNEXPECTED;
  596. end;
  597. end;
  598. function TTBViewAccObject.get_accSelection(out pvarChildren: OleVariant): HRESULT;
  599. begin
  600. Result := S_FALSE;
  601. end;
  602. function TTBViewAccObject.get_accState(varChild: OleVariant;
  603. out pvarState: OleVariant): HRESULT;
  604. begin
  605. try
  606. if not Check(varChild, Result) then
  607. Exit;
  608. pvarState := 0;
  609. Result := S_OK;
  610. except
  611. Result := E_UNEXPECTED;
  612. end;
  613. end;
  614. function TTBViewAccObject.get_accValue(varChild: OleVariant;
  615. out pszValue: WideString): HRESULT;
  616. begin
  617. Result := S_FALSE;
  618. end;
  619. function TTBViewAccObject.put_accName(varChild: OleVariant;
  620. const pszName: WideString): HRESULT;
  621. begin
  622. Result := S_FALSE;
  623. end;
  624. function TTBViewAccObject.put_accValue(varChild: OleVariant;
  625. const pszValue: WideString): HRESULT;
  626. begin
  627. Result := S_FALSE;
  628. end;
  629. { TTBItemViewerAccObject }
  630. constructor TTBItemViewerAccObject.Create(AViewer: TTBItemViewer);
  631. begin
  632. inherited Create;
  633. FViewer := AViewer;
  634. InterlockedIncrement(ItemViewerAccObjectInstances);
  635. end;
  636. destructor TTBItemViewerAccObject.Destroy;
  637. begin
  638. InterlockedDecrement(ItemViewerAccObjectInstances);
  639. if Assigned(FViewer) then begin
  640. TTBItemViewerAccess(FViewer).FAccObjectInstance := nil;
  641. FViewer := nil;
  642. end;
  643. inherited;
  644. end;
  645. procedure TTBItemViewerAccObject.ClientIsDestroying;
  646. begin
  647. FViewer := nil;
  648. end;
  649. function TTBItemViewerAccObject.Check(const varChild: OleVariant;
  650. var ErrorCode: HRESULT): Boolean;
  651. begin
  652. if FViewer = nil then begin
  653. ErrorCode := E_FAIL;
  654. Result := False;
  655. end
  656. else if (VarType(varChild) <> varInteger) or (varChild <> CHILDID_SELF) then begin
  657. ErrorCode := E_INVALIDARG;
  658. Result := False;
  659. end
  660. else
  661. Result := True;
  662. end;
  663. function TTBItemViewerAccObject.IsActionable: Boolean;
  664. { Returns True if 'doDefaultAction' may be performed on the viewer, i.e. if
  665. it's visible/off-edge/clipped, enabled & selectable, and the view is
  666. focusable. }
  667. begin
  668. Result := FViewer.IsAccessible and IsAvailable and IsFocusable;
  669. end;
  670. function TTBItemViewerAccObject.IsAvailable: Boolean;
  671. { Returns True if the viewer's item is enabled and selectable }
  672. begin
  673. Result := FViewer.Item.Enabled and
  674. (tbisSelectable in TTBCustomItemAccess(FViewer.Item).ItemStyle);
  675. end;
  676. function TTBItemViewerAccObject.IsFocusable: Boolean;
  677. { Returns True if viewers on the view can be 'focused' (i.e. the view's window
  678. doesn't have the csDesigning state, the window is visible and enabled, and
  679. the application is active). }
  680. function IsWindowAndParentsEnabled(W: HWND): Boolean;
  681. begin
  682. Result := True;
  683. repeat
  684. if not IsWindowEnabled(W) then begin
  685. Result := False;
  686. Break;
  687. end;
  688. W := GetParent(W);
  689. until W = 0;
  690. end;
  691. var
  692. ViewWnd, ActiveWnd: HWND;
  693. begin
  694. Result := False;
  695. if csDesigning in FViewer.View.Window.ComponentState then
  696. Exit;
  697. ViewWnd := FViewer.View.Window.Handle;
  698. if IsWindowVisible(ViewWnd) and IsWindowAndParentsEnabled(ViewWnd) then begin
  699. if vsModal in FViewer.View.State then
  700. Result := True
  701. else begin
  702. ActiveWnd := GetActiveWindow;
  703. if (ActiveWnd <> 0) and
  704. ((ActiveWnd = ViewWnd) or IsChild(ActiveWnd, ViewWnd)) then
  705. Result := True;
  706. end;
  707. end;
  708. end;
  709. procedure TTBItemViewerAccObject.HandleAccSelect(const AExecute: Boolean);
  710. begin
  711. if Assigned(FViewer) and
  712. ((AExecute and IsActionable) or (not AExecute and IsFocusable)) then begin
  713. FViewer.View.Selected := FViewer;
  714. FViewer.View.ScrollSelectedIntoView;
  715. if vsModal in FViewer.View.State then begin
  716. if AExecute then
  717. FViewer.View.ExecuteSelected(False);
  718. end
  719. else if (FViewer.View.ParentView = nil) and (GetCapture = 0) then begin
  720. if AExecute then
  721. FViewer.View.EnterToolbarLoop([tbetExecuteSelected, tbetFromMSAA])
  722. else
  723. FViewer.View.EnterToolbarLoop([tbetFromMSAA]);
  724. end;
  725. end;
  726. end;
  727. function TTBItemViewerAccObject.accDoDefaultAction(varChild: OleVariant): HRESULT;
  728. begin
  729. try
  730. if not Check(varChild, Result) then
  731. Exit;
  732. { NOTE: This must be kept in synch with get_accDefaultAction }
  733. if IsActionable then begin
  734. Result := S_OK;
  735. if FViewer.View.OpenViewer = FViewer then begin
  736. FViewer.View.CancelChildPopups;
  737. { Like standard menus, cancel the modal loop when a top-level menu
  738. is closed }
  739. if (vsModal in FViewer.View.State) and not FViewer.View.IsPopup then
  740. FViewer.View.EndModal;
  741. end
  742. else begin
  743. FViewer.View.Selected := FViewer;
  744. FViewer.View.ScrollSelectedIntoView;
  745. TTBItemViewerAccess(FViewer).PostAccSelect(True);
  746. end;
  747. end
  748. else
  749. { Note: Standard menus return DISP_E_MEMBERNOTFOUND in this case but
  750. that doesn't make much sense. The member is there but just isn't
  751. currently available. }
  752. Result := E_FAIL;
  753. except
  754. Result := E_UNEXPECTED;
  755. end;
  756. end;
  757. function TTBItemViewerAccObject.accHitTest(xLeft, yTop: Integer;
  758. out pvarID: OleVariant): HRESULT;
  759. var
  760. P: TPoint;
  761. begin
  762. try
  763. if FViewer = nil then begin
  764. Result := E_FAIL;
  765. Exit;
  766. end;
  767. P := FViewer.View.Window.ScreenToClient(Point(xLeft, yTop));
  768. if PtInRect(FViewer.BoundsRect, P) then begin
  769. pvarID := CHILDID_SELF;
  770. Result := S_OK;
  771. end
  772. else
  773. Result := S_FALSE;
  774. except
  775. Result := E_UNEXPECTED;
  776. end;
  777. end;
  778. function TTBItemViewerAccObject.accLocation(out pxLeft, pyTop, pcxWidth,
  779. pcyHeight: Integer; varChild: OleVariant): HRESULT;
  780. var
  781. R: TRect;
  782. P: TPoint;
  783. begin
  784. try
  785. if not Check(varChild, Result) then
  786. Exit;
  787. R := FViewer.BoundsRect;
  788. P := FViewer.View.Window.ClientToScreen(Point(0, 0));
  789. OffsetRect(R, P.X, P.Y);
  790. pxLeft := R.Left;
  791. pyTop := R.Top;
  792. pcxWidth := R.Right - R.Left;
  793. pcyHeight := R.Bottom - R.Top;
  794. Result := S_OK;
  795. except
  796. Result := E_UNEXPECTED;
  797. end;
  798. end;
  799. function TTBItemViewerAccObject.accNavigate(navDir: Integer; varStart: OleVariant;
  800. out pvarEnd: OleVariant): HRESULT;
  801. var
  802. I, J: Integer;
  803. View: TTBView;
  804. begin
  805. try
  806. if not Check(varStart, Result) then
  807. Exit;
  808. Result := S_FALSE;
  809. if (navDir = NAVDIR_FIRSTCHILD) or (navDir = NAVDIR_LASTCHILD) then begin
  810. { Return the child view's acc. object }
  811. View := FViewer.View.OpenViewerView;
  812. if Assigned(View) then begin
  813. pvarEnd := View.GetAccObject;
  814. Result := S_OK;
  815. end;
  816. end
  817. else begin
  818. I := FViewer.View.IndexOf(FViewer);
  819. if I >= 0 then begin
  820. case navDir of
  821. NAVDIR_UP, NAVDIR_LEFT, NAVDIR_PREVIOUS:
  822. for J := I-1 downto 0 do
  823. if FViewer.View.Viewers[J].IsAccessible then begin
  824. pvarEnd := FViewer.View.Viewers[J].GetAccObject;
  825. Result := S_OK;
  826. Break;
  827. end;
  828. NAVDIR_DOWN, NAVDIR_RIGHT, NAVDIR_NEXT:
  829. for J := I+1 to FViewer.View.ViewerCount-1 do
  830. if FViewer.View.Viewers[J].IsAccessible then begin
  831. pvarEnd := FViewer.View.Viewers[J].GetAccObject;
  832. Result := S_OK;
  833. Break;
  834. end;
  835. end;
  836. end;
  837. end;
  838. except
  839. Result := E_UNEXPECTED;
  840. end;
  841. end;
  842. function TTBItemViewerAccObject.accSelect(flagsSelect: Integer;
  843. varChild: OleVariant): HRESULT;
  844. begin
  845. try
  846. if not Check(varChild, Result) then
  847. Exit;
  848. if flagsSelect <> SELFLAG_TAKEFOCUS then begin
  849. Result := E_INVALIDARG;
  850. Exit;
  851. end;
  852. if IsFocusable and (FViewer.Show or FViewer.Clipped) then begin
  853. FViewer.View.Selected := FViewer;
  854. FViewer.View.ScrollSelectedIntoView;
  855. if not(vsModal in FViewer.View.State) and
  856. (FViewer.View.ParentView = nil) then
  857. TTBItemViewerAccess(FViewer).PostAccSelect(False);
  858. end
  859. else
  860. Result := E_FAIL;
  861. { ^ what Office XP returns when you try focusing an off-edge item }
  862. except
  863. Result := E_UNEXPECTED;
  864. end;
  865. end;
  866. function TTBItemViewerAccObject.get_accChild(varChild: OleVariant;
  867. out ppdispChild: IDispatch): HRESULT;
  868. var
  869. View: TTBView;
  870. begin
  871. try
  872. if FViewer = nil then begin
  873. Result := E_FAIL;
  874. Exit;
  875. end;
  876. Result := E_INVALIDARG;
  877. if VarType(varChild) = varInteger then begin
  878. if varChild = CHILDID_SELF then begin
  879. ppdispChild := Self;
  880. Result := S_OK;
  881. end
  882. else if varChild = 1 then begin
  883. { Return the child view's acc. object }
  884. View := FViewer.View.OpenViewerView;
  885. if Assigned(View) then begin
  886. ppdispChild := View.GetAccObject;
  887. Result := S_OK;
  888. end;
  889. end;
  890. end;
  891. except
  892. Result := E_UNEXPECTED;
  893. end;
  894. end;
  895. function TTBItemViewerAccObject.get_accChildCount(out pcountChildren: Integer): HRESULT;
  896. begin
  897. try
  898. if FViewer = nil then begin
  899. Result := E_FAIL;
  900. Exit;
  901. end;
  902. { Return 1 if the viewer has a child view }
  903. if FViewer.View.OpenViewer = FViewer then
  904. pCountChildren := 1
  905. else
  906. pCountChildren := 0;
  907. Result := S_OK;
  908. except
  909. Result := E_UNEXPECTED;
  910. end;
  911. end;
  912. function TTBItemViewerAccObject.get_accDefaultAction(varChild: OleVariant;
  913. out pszDefaultAction: WideString): HRESULT;
  914. begin
  915. try
  916. if not Check(varChild, Result) then
  917. Exit;
  918. if IsActionable then begin
  919. { I'm not sure if these should be localized, or even if any screen
  920. readers make use of this text...
  921. NOTE: This must be kept in synch with accDoDefaultAction }
  922. if FViewer.View.OpenViewer = FViewer then
  923. pszDefaultAction := 'Close'
  924. else if tbisSubmenu in TTBCustomItemAccess(FViewer.Item).ItemStyle then
  925. pszDefaultAction := 'Open'
  926. else if FViewer.View.IsPopup or (vsMenuBar in FViewer.View.Style) then
  927. pszDefaultAction := 'Execute'
  928. else
  929. pszDefaultAction := 'Press';
  930. Result := S_OK;
  931. end
  932. else
  933. Result := S_FALSE;
  934. except
  935. Result := E_UNEXPECTED;
  936. end;
  937. end;
  938. function TTBItemViewerAccObject.get_accDescription(varChild: OleVariant;
  939. out pszDescription: WideString): HRESULT;
  940. begin
  941. Result := S_FALSE;
  942. end;
  943. function TTBItemViewerAccObject.get_accFocus(out pvarID: OleVariant): HRESULT;
  944. begin
  945. try
  946. if FViewer = nil then begin
  947. Result := E_FAIL;
  948. Exit;
  949. end;
  950. if (vsModal in FViewer.View.State) and
  951. (FViewer.View.Selected = FViewer) then begin
  952. pvarID := CHILDID_SELF;
  953. Result := S_OK;
  954. end
  955. else
  956. Result := S_FALSE;
  957. except
  958. Result := E_UNEXPECTED;
  959. end;
  960. end;
  961. function TTBItemViewerAccObject.get_accHelp(varChild: OleVariant;
  962. out pszHelp: WideString): HRESULT;
  963. begin
  964. Result := S_FALSE;
  965. end;
  966. function TTBItemViewerAccObject.get_accHelpTopic(out pszHelpFile: WideString;
  967. varChild: OleVariant; out pidTopic: Integer): HRESULT;
  968. begin
  969. pidTopic := 0; { Delphi doesn't implicitly clear Integer 'out' parameters }
  970. Result := S_FALSE;
  971. end;
  972. function TTBItemViewerAccObject.get_accKeyboardShortcut(varChild: OleVariant;
  973. out pszKeyboardShortcut: WideString): HRESULT;
  974. var
  975. C: Char;
  976. begin
  977. try
  978. if not Check(varChild, Result) then
  979. Exit;
  980. Result := S_FALSE;
  981. if TTBItemViewerAccess(FViewer).CaptionShown then begin
  982. C := FindAccelChar(TTBItemViewerAccess(FViewer).GetCaptionText);
  983. if C <> #0 then begin
  984. CharLowerBuff(@C, 1); { like standard menus, always use lowercase... }
  985. if FViewer.View.IsPopup then
  986. pszKeyboardShortcut := C
  987. else begin
  988. { Prefix 'Alt+' }
  989. pszKeyboardShortcut := GetAltKeyName + '+' + C;
  990. end;
  991. Result := S_OK;
  992. end;
  993. end;
  994. except
  995. Result := E_UNEXPECTED;
  996. end;
  997. end;
  998. function TTBItemViewerAccObject.get_accName(varChild: OleVariant;
  999. out pszName: WideString): HRESULT;
  1000. var
  1001. C, S: String;
  1002. begin
  1003. try
  1004. if not Check(varChild, Result) then
  1005. Exit;
  1006. C := StripAccelChars(TTBItemViewerAccess(FViewer).GetCaptionText);
  1007. if not FViewer.IsToolbarStyle then
  1008. S := FViewer.Item.GetShortCutText;
  1009. if S = '' then
  1010. pszName := C
  1011. else
  1012. pszName := C + #9 + S;
  1013. Result := S_OK;
  1014. except
  1015. Result := E_UNEXPECTED;
  1016. end;
  1017. end;
  1018. function TTBItemViewerAccObject.get_accParent(out ppdispParent: IDispatch): HRESULT;
  1019. begin
  1020. try
  1021. if Assigned(FViewer) then begin
  1022. ppdispParent := FViewer.View.GetAccObject;
  1023. Result := S_OK;
  1024. end
  1025. else
  1026. Result := E_FAIL;
  1027. except
  1028. Result := E_UNEXPECTED;
  1029. end;
  1030. end;
  1031. function TTBItemViewerAccObject.get_accRole(varChild: OleVariant;
  1032. out pvarRole: OleVariant): HRESULT;
  1033. begin
  1034. try
  1035. if not Check(varChild, Result) then
  1036. Exit;
  1037. pvarRole := TTBItemViewerAccess(FViewer).GetAccRole;
  1038. Result := S_OK;
  1039. except
  1040. Result := E_UNEXPECTED;
  1041. end;
  1042. end;
  1043. function TTBItemViewerAccObject.get_accSelection(out pvarChildren: OleVariant): HRESULT;
  1044. begin
  1045. Result := S_FALSE;
  1046. end;
  1047. function TTBItemViewerAccObject.get_accState(varChild: OleVariant;
  1048. out pvarState: OleVariant): HRESULT;
  1049. var
  1050. Flags: Integer;
  1051. begin
  1052. try
  1053. if not Check(varChild, Result) then
  1054. Exit;
  1055. Flags := 0;
  1056. if FViewer.View.Selected = FViewer then begin
  1057. Flags := Flags or STATE_SYSTEM_HOTTRACKED;
  1058. if vsModal in FViewer.View.State then
  1059. Flags := Flags or STATE_SYSTEM_FOCUSED;
  1060. if FViewer.View.MouseOverSelected and FViewer.View.Capture then
  1061. { ^ based on "IsPushed :=" code in TTBView.DrawItem }
  1062. Flags := Flags or STATE_SYSTEM_PRESSED;
  1063. end;
  1064. if tbisSubmenu in TTBCustomItemAccess(FViewer.Item).ItemStyle then
  1065. Flags := Flags or STATE_SYSTEM_HASPOPUP;
  1066. if FViewer.Show or FViewer.Clipped then begin
  1067. if IsFocusable then
  1068. Flags := Flags or STATE_SYSTEM_FOCUSABLE;
  1069. end
  1070. else begin
  1071. { Mark off-edge items as invisible, like Office }
  1072. Flags := Flags or STATE_SYSTEM_INVISIBLE;
  1073. end;
  1074. if not IsAvailable then
  1075. Flags := Flags or STATE_SYSTEM_UNAVAILABLE;
  1076. if FViewer.Item.Checked then
  1077. Flags := Flags or STATE_SYSTEM_CHECKED;
  1078. pvarState := Flags;
  1079. Result := S_OK;
  1080. except
  1081. Result := E_UNEXPECTED;
  1082. end;
  1083. end;
  1084. function TTBItemViewerAccObject.get_accValue(varChild: OleVariant;
  1085. out pszValue: WideString): HRESULT;
  1086. begin
  1087. try
  1088. if not Check(varChild, Result) then
  1089. Exit;
  1090. if TTBItemViewerAccess(FViewer).GetAccValue(pszValue) then
  1091. Result := S_OK
  1092. else begin
  1093. pszValue := '';
  1094. Result := S_FALSE;
  1095. end;
  1096. except
  1097. Result := E_UNEXPECTED;
  1098. end;
  1099. end;
  1100. function TTBItemViewerAccObject.put_accName(varChild: OleVariant;
  1101. const pszName: WideString): HRESULT;
  1102. begin
  1103. Result := S_FALSE;
  1104. end;
  1105. function TTBItemViewerAccObject.put_accValue(varChild: OleVariant;
  1106. const pszValue: WideString): HRESULT;
  1107. begin
  1108. Result := S_FALSE;
  1109. end;
  1110. { Note: This COM initialization code based on code from DBTables }
  1111. var
  1112. SaveInitProc: Pointer;
  1113. NeedToUninitialize: Boolean;
  1114. procedure InitCOM;
  1115. begin
  1116. if SaveInitProc <> nil then TProcedure(SaveInitProc);
  1117. NeedToUninitialize := SUCCEEDED(CoInitialize(nil));
  1118. end;
  1119. initialization
  1120. InitializeCriticalSection(LastAccObjectCritSect);
  1121. if not IsLibrary then begin
  1122. SaveInitProc := InitProc;
  1123. InitProc := @InitCOM;
  1124. end;
  1125. finalization
  1126. DisconnectAccObjects;
  1127. if NeedToUninitialize then
  1128. CoUninitialize;
  1129. DeleteCriticalSection(LastAccObjectCritSect);
  1130. end.