comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/Accessible.d @ 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children 950d84783eac
comparison
equal deleted inserted replaced
-1:000000000000 0:6dd524f61e62
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.swt.accessibility.Accessible;
14
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.SWTException;
17 import org.eclipse.swt.internal.ole.win32.COM;
18 import org.eclipse.swt.internal.ole.win32.OAIDL;
19 import org.eclipse.swt.internal.ole.win32.ifs;
20 import org.eclipse.swt.internal.ole.win32.extras;
21 import org.eclipse.swt.internal.win32.OS;
22 import org.eclipse.swt.internal.SWTEventListener;
23 import org.eclipse.swt.ole.win32.OLE;
24 import org.eclipse.swt.ole.win32.Variant;
25 import org.eclipse.swt.widgets.Control;
26 import org.eclipse.swt.widgets.Table;
27 import org.eclipse.swt.widgets.TableItem;
28 import org.eclipse.swt.widgets.Tree;
29 import org.eclipse.swt.widgets.TreeItem;
30 import org.eclipse.swt.widgets.Widget;
31
32 import org.eclipse.swt.accessibility.ACC;
33 import org.eclipse.swt.accessibility.AccessibleControlListener;
34 import org.eclipse.swt.accessibility.AccessibleListener;
35 import org.eclipse.swt.accessibility.AccessibleTextListener;
36 import org.eclipse.swt.accessibility.AccessibleControlEvent;
37 import org.eclipse.swt.accessibility.AccessibleEvent;
38
39 import java.lang.all;
40 import tango.core.Array;
41 import tango.core.Thread;
42
43 /**
44 * Instances of this class provide a bridge between application
45 * code and assistive technology clients. Many platforms provide
46 * default accessible behavior for most widgets, and this class
47 * allows that default behavior to be overridden. Applications
48 * can get the default Accessible object for a control by sending
49 * it <code>getAccessible</code>, and then add an accessible listener
50 * to override simple items like the name and help string, or they
51 * can add an accessible control listener to override complex items.
52 * As a rule of thumb, an application would only want to use the
53 * accessible control listener to implement accessibility for a
54 * custom control.
55 *
56 * @see Control#getAccessible
57 * @see AccessibleListener
58 * @see AccessibleEvent
59 * @see AccessibleControlListener
60 * @see AccessibleControlEvent
61 * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a>
62 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
63 *
64 * @since 2.0
65 */
66 public class Accessible {
67 int refCount = 0, enumIndex = 0;
68 _IAccessibleImpl objIAccessible;
69 _IEnumVARIANTImpl objIEnumVARIANT;
70 IAccessible iaccessible;
71 SWTEventListener[] accessibleListeners;
72 SWTEventListener[] accessibleControlListeners;
73 SWTEventListener[] textListeners;
74 Object[] variants;
75 Control control;
76
77 this(Control control) {
78 this.control = control;
79 int /*long*/[] ppvObject = new int /*long*/[1];
80 /* CreateStdAccessibleObject([in] hwnd, [in] idObject, [in] riidInterface, [out] ppvObject).
81 * AddRef has already been called on ppvObject by the callee and must be released by the caller.
82 */
83 HRESULT result = COM.CreateStdAccessibleObject(control.handle, COM.OBJID_CLIENT, &COM.IIDIAccessible, cast(void**)&iaccessible);
84 /* The object needs to be checked, because if the CreateStdAccessibleObject()
85 * symbol is not found, the return value is S_OK.
86 */
87 if (iaccessible is null) return;
88 if (result !is COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
89
90 objIAccessible = new _IAccessibleImpl(this);
91
92 //PORTING_FIXME: i don't understand this...
93 /+
94 int /*long*/ ppVtable = objIAccessible.ppVtable;
95 int /*long*/[] pVtable = new int /*long*/[1];
96 COM.MoveMemory(pVtable, ppVtable, OS.PTR_SIZEOF);
97 int /*long*/[] funcs = new int /*long*/[28];
98 COM.MoveMemory(funcs, pVtable[0], OS.PTR_SIZEOF * funcs.length);
99 funcs[9] = COM.get_accChild_CALLBACK(funcs[9]);
100 funcs[10] = COM.get_accName_CALLBACK(funcs[10]);
101 funcs[11] = COM.get_accValue_CALLBACK(funcs[11]);
102 funcs[12] = COM.get_accDescription_CALLBACK(funcs[12]);
103 funcs[13] = COM.get_accRole_CALLBACK(funcs[13]);
104 funcs[14] = COM.get_accState_CALLBACK(funcs[14]);
105 funcs[15] = COM.get_accHelp_CALLBACK(funcs[15]);
106 funcs[16] = COM.get_accHelpTopic_CALLBACK(funcs[16]);
107 funcs[17] = COM.get_accKeyboardShortcut_CALLBACK(funcs[17]);
108 funcs[20] = COM.get_accDefaultAction_CALLBACK(funcs[20]);
109 funcs[21] = COM.accSelect_CALLBACK(funcs[21]);
110 funcs[22] = COM.accLocation_CALLBACK(funcs[22]);
111 funcs[23] = COM.accNavigate_CALLBACK(funcs[23]);
112 funcs[25] = COM.accDoDefaultAction_CALLBACK(funcs[25]);
113 funcs[26] = COM.put_accName_CALLBACK(funcs[26]);
114 funcs[27] = COM.put_accValue_CALLBACK(funcs[27]);
115 COM.MoveMemory(pVtable[0], funcs, OS.PTR_SIZEOF * funcs.length);
116 +/
117
118 objIEnumVARIANT = new _IEnumVARIANTImpl(this) ;
119 AddRef();
120 }
121
122 /**
123 * Invokes platform specific functionality to allocate a new accessible object.
124 * <p>
125 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
126 * API for <code>Accessible</code>. It is marked public only so that it
127 * can be shared within the packages provided by SWT. It is not
128 * available on all platforms, and should never be called from
129 * application code.
130 * </p>
131 *
132 * @param control the control to get the accessible object for
133 * @return the platform specific accessible object
134 */
135 public static Accessible internal_new_Accessible(Control control) {
136 return new Accessible(control);
137 }
138
139 /**
140 * Adds the listener to the collection of listeners who will
141 * be notified when an accessible client asks for certain strings,
142 * such as name, description, help, or keyboard shortcut. The
143 * listener is notified by sending it one of the messages defined
144 * in the <code>AccessibleListener</code> interface.
145 *
146 * @param listener the listener that should be notified when the receiver
147 * is asked for a name, description, help, or keyboard shortcut string
148 *
149 * @exception IllegalArgumentException <ul>
150 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
151 * </ul>
152 * @exception SWTException <ul>
153 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
154 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
155 * </ul>
156 *
157 * @see AccessibleListener
158 * @see #removeAccessibleListener
159 */
160 public void addAccessibleListener(AccessibleListener listener) {
161 checkWidget();
162 if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
163 accessibleListeners ~= listener;
164 }
165
166 /**
167 * Adds the listener to the collection of listeners who will
168 * be notified when an accessible client asks for custom control
169 * specific information. The listener is notified by sending it
170 * one of the messages defined in the <code>AccessibleControlListener</code>
171 * interface.
172 *
173 * @param listener the listener that should be notified when the receiver
174 * is asked for custom control specific information
175 *
176 * @exception IllegalArgumentException <ul>
177 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
178 * </ul>
179 * @exception SWTException <ul>
180 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
181 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
182 * </ul>
183 *
184 * @see AccessibleControlListener
185 * @see #removeAccessibleControlListener
186 */
187 public void addAccessibleControlListener(AccessibleControlListener listener) {
188 checkWidget();
189 if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
190 accessibleControlListeners ~= listener;
191 }
192
193 /**
194 * Adds the listener to the collection of listeners who will
195 * be notified when an accessible client asks for custom text control
196 * specific information. The listener is notified by sending it
197 * one of the messages defined in the <code>AccessibleTextListener</code>
198 * interface.
199 *
200 * @param listener the listener that should be notified when the receiver
201 * is asked for custom text control specific information
202 *
203 * @exception IllegalArgumentException <ul>
204 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
205 * </ul>
206 * @exception SWTException <ul>
207 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
208 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
209 * </ul>
210 *
211 * @see AccessibleTextListener
212 * @see #removeAccessibleTextListener
213 *
214 * @since 3.0
215 */
216 public void addAccessibleTextListener (AccessibleTextListener listener) {
217 checkWidget ();
218 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
219 textListeners ~= listener;
220 }
221
222 /**
223 * Returns the control for this Accessible object.
224 *
225 * @return the receiver's control
226 * @since 3.0
227 */
228 public Control getControl() {
229 return control;
230 }
231
232 /**
233 * Invokes platform specific functionality to dispose an accessible object.
234 * <p>
235 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
236 * API for <code>Accessible</code>. It is marked public only so that it
237 * can be shared within the packages provided by SWT. It is not
238 * available on all platforms, and should never be called from
239 * application code.
240 * </p>
241 */
242 public void internal_dispose_Accessible() {
243 if (iaccessible !is null) {
244 iaccessible.Release();
245 }
246 iaccessible = null;
247 Release();
248 }
249
250 /**
251 * Invokes platform specific functionality to handle a window message.
252 * <p>
253 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
254 * API for <code>Accessible</code>. It is marked public only so that it
255 * can be shared within the packages provided by SWT. It is not
256 * available on all platforms, and should never be called from
257 * application code.
258 * </p>
259 */
260 public int /*long*/ internal_WM_GETOBJECT (int /*long*/ wParam, int /*long*/ lParam) {
261 if (objIAccessible is null) return 0;
262 if (lParam is COM.OBJID_CLIENT) {
263 /* LresultFromObject([in] riid, [in] wParam, [in] pAcc)
264 * The argument pAcc is owned by the caller so reference count does not
265 * need to be incremented.
266 */
267 return COM.LresultFromObject(&COM.IIDIAccessible, wParam, cast(IAccessible)objIAccessible);
268 }
269 return 0;
270 }
271
272 /**
273 * Removes the listener from the collection of listeners who will
274 * be notified when an accessible client asks for certain strings,
275 * such as name, description, help, or keyboard shortcut.
276 *
277 * @param listener the listener that should no longer be notified when the receiver
278 * is asked for a name, description, help, or keyboard shortcut string
279 *
280 * @exception IllegalArgumentException <ul>
281 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
282 * </ul>
283 * @exception SWTException <ul>
284 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
285 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
286 * </ul>
287 *
288 * @see AccessibleListener
289 * @see #addAccessibleListener
290 */
291 public void removeAccessibleListener(AccessibleListener listener) {
292 checkWidget();
293 if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
294 accessibleListeners.length = accessibleListeners.remove(listener);
295 }
296
297 /**
298 * Removes the listener from the collection of listeners who will
299 * be notified when an accessible client asks for custom control
300 * specific information.
301 *
302 * @param listener the listener that should no longer be notified when the receiver
303 * is asked for custom control specific information
304 *
305 * @exception IllegalArgumentException <ul>
306 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
307 * </ul>
308 * @exception SWTException <ul>
309 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
310 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
311 * </ul>
312 *
313 * @see AccessibleControlListener
314 * @see #addAccessibleControlListener
315 */
316 public void removeAccessibleControlListener(AccessibleControlListener listener) {
317 checkWidget();
318 if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
319 accessibleControlListeners.length = accessibleControlListeners.remove(listener);
320 }
321
322 /**
323 * Removes the listener from the collection of listeners who will
324 * be notified when an accessible client asks for custom text control
325 * specific information.
326 *
327 * @param listener the listener that should no longer be notified when the receiver
328 * is asked for custom text control specific information
329 *
330 * @exception IllegalArgumentException <ul>
331 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
332 * </ul>
333 * @exception SWTException <ul>
334 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
335 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
336 * </ul>
337 *
338 * @see AccessibleTextListener
339 * @see #addAccessibleTextListener
340 *
341 * @since 3.0
342 */
343 public void removeAccessibleTextListener (AccessibleTextListener listener) {
344 checkWidget ();
345 if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
346 textListeners.length = textListeners.remove (listener);
347 }
348
349 /**
350 * Sends a message to accessible clients that the child selection
351 * within a custom container control has changed.
352 *
353 * @exception SWTException <ul>
354 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
355 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
356 * </ul>
357 *
358 * @since 3.0
359 */
360 public void selectionChanged () {
361 checkWidget();
362 COM.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, COM.OBJID_CLIENT, COM.CHILDID_SELF);
363 }
364
365 /**
366 * Sends a message to accessible clients indicating that the focus
367 * has changed within a custom control.
368 *
369 * @param childID an identifier specifying a child of the control
370 *
371 * @exception SWTException <ul>
372 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
373 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
374 * </ul>
375 */
376 public void setFocus(int childID) {
377 checkWidget();
378 COM.NotifyWinEvent (COM.EVENT_OBJECT_FOCUS, control.handle, COM.OBJID_CLIENT, childIDToOs(childID));
379 }
380
381 /**
382 * Sends a message to accessible clients that the text
383 * caret has moved within a custom control.
384 *
385 * @param index the new caret index within the control
386 *
387 * @exception SWTException <ul>
388 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
389 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
390 * </ul>
391 *
392 * @since 3.0
393 */
394 public void textCaretMoved (int index) {
395 checkWidget();
396 COM.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, COM.OBJID_CARET, COM.CHILDID_SELF);
397 }
398
399 /**
400 * Sends a message to accessible clients that the text
401 * within a custom control has changed.
402 *
403 * @param type the type of change, one of <code>ACC.NOTIFY_TEXT_INSERT</code>
404 * or <code>ACC.NOTIFY_TEXT_DELETE</code>
405 * @param startIndex the text index within the control where the insertion or deletion begins
406 * @param length the non-negative length in characters of the insertion or deletion
407 *
408 * @exception SWTException <ul>
409 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
410 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
411 * </ul>
412 *
413 * @see ACC#TEXT_INSERT
414 * @see ACC#TEXT_DELETE
415 *
416 * @since 3.0
417 */
418 public void textChanged (int type, int startIndex, int length) {
419 checkWidget();
420 COM.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, COM.OBJID_CLIENT, COM.CHILDID_SELF);
421 }
422
423 /**
424 * Sends a message to accessible clients that the text
425 * selection has changed within a custom control.
426 *
427 * @exception SWTException <ul>
428 * <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
429 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
430 * </ul>
431 *
432 * @since 3.0
433 */
434 public void textSelectionChanged () {
435 checkWidget();
436 // not an MSAA event
437 }
438
439 /* QueryInterface([in] iid, [out] ppvObject)
440 * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
441 * must be incremented before returning. Caller is responsible for releasing ppvObject.
442 */
443 HRESULT QueryInterface(REFIID riid, void** ppvObject) {
444 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
445
446 if (COM.IsEqualGUID(riid, &COM.IIDIUnknown)) {
447 *ppvObject = cast(void*)cast(IUnknown) objIAccessible;
448 AddRef();
449 return COM.S_OK;
450 }
451
452 if (COM.IsEqualGUID(riid, &COM.IIDIDispatch)) {
453 *ppvObject = cast(void*)cast(IDispatch) objIAccessible;
454 AddRef();
455 return COM.S_OK;
456 }
457
458 if (COM.IsEqualGUID(riid, &COM.IIDIAccessible)) {
459 *ppvObject = cast(void*)cast(IAccessible) objIAccessible;
460 AddRef();
461 return COM.S_OK;
462 }
463
464 if (COM.IsEqualGUID(riid, &COM.IIDIEnumVARIANT)) {
465 *ppvObject = cast(void*)cast(IEnumVARIANT) objIEnumVARIANT;
466 AddRef();
467 enumIndex = 0;
468 return COM.S_OK;
469 }
470
471 HRESULT result = iaccessible.QueryInterface(riid, ppvObject);
472 return result;
473 }
474
475 ULONG AddRef() {
476 refCount++;
477 return refCount;
478 }
479
480 ULONG Release() {
481 refCount--;
482
483 if (refCount is 0) {
484 objIAccessible = null;
485 objIEnumVARIANT = null;
486 }
487 return refCount;
488 }
489
490 HRESULT accDoDefaultAction(VARIANT variant) {
491 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
492 // Currently, we don't let the application override this. Forward to the proxy.
493 int code = iaccessible.accDoDefaultAction(variant);
494 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
495 return code;
496 }
497
498 HRESULT accHitTest(LONG xLeft, LONG yTop, VARIANT* pvarChild) {
499 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
500 if (accessibleControlListeners.length is 0) {
501 return iaccessible.accHitTest(xLeft, yTop, pvarChild);
502 }
503
504 AccessibleControlEvent event = new AccessibleControlEvent(this);
505 event.childID = ACC.CHILDID_NONE;
506 event.x = xLeft;
507 event.y = yTop;
508 for (int i = 0; i < accessibleControlListeners.length; i++) {
509 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
510 listener.getChildAtPoint(event);
511 }
512 int childID = event.childID;
513 if (childID is ACC.CHILDID_NONE) {
514 return iaccessible.accHitTest(xLeft, yTop, pvarChild);
515 }
516 //TODO - use VARIANT structure
517 pvarChild.vt = COM.VT_I4;
518 pvarChild.lVal = childIDToOs(childID);
519 return COM.S_OK;
520 }
521
522 HRESULT accLocation(LONG* pxLeft, LONG* pyTop, LONG* pcxWidth, LONG* pcyHeight, VARIANT variant) {
523 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
524 VARIANT* v = &variant;
525 //COM.MoveMemory(v, variant, VARIANT.sizeof);
526 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
527
528 /* Get the default location from the OS. */
529 int osLeft = 0, osTop = 0, osWidth = 0, osHeight = 0;
530 int code = iaccessible.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, variant);
531 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
532 if (accessibleControlListeners.length is 0) return code;
533 if (code is COM.S_OK) {
534 int[1] pLeft, pTop, pWidth, pHeight;
535 COM.MoveMemory(pLeft.ptr, pxLeft, 4);
536 COM.MoveMemory(pTop.ptr, pyTop, 4);
537 COM.MoveMemory(pWidth.ptr, pcxWidth, 4);
538 COM.MoveMemory(pHeight.ptr, pcyHeight, 4);
539 osLeft = pLeft[0]; osTop = pTop[0]; osWidth = pWidth[0]; osHeight = pHeight[0];
540 }
541
542 AccessibleControlEvent event = new AccessibleControlEvent(this);
543 event.childID = osToChildID(v.lVal);
544 event.x = osLeft;
545 event.y = osTop;
546 event.width = osWidth;
547 event.height = osHeight;
548 for (int i = 0; i < accessibleControlListeners.length; i++) {
549 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
550 listener.getLocation(event);
551 }
552 OS.MoveMemory(pxLeft, &event.x, 4);
553 OS.MoveMemory(pyTop, &event.y, 4);
554 OS.MoveMemory(pcxWidth, &event.width, 4);
555 OS.MoveMemory(pcyHeight, &event.height, 4);
556 return COM.S_OK;
557 }
558
559 HRESULT accNavigate(LONG navDir, VARIANT variant, VARIANT* pvarEndUpAt) {
560 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
561 // Currently, we don't let the application override this. Forward to the proxy.
562 int code = iaccessible.accNavigate(navDir, variant, pvarEndUpAt);
563 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
564 return code;
565 }
566
567 HRESULT accSelect(LONG flagsSelect, VARIANT variant) {
568 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
569 // Currently, we don't let the application override this. Forward to the proxy.
570 int code = iaccessible.accSelect(flagsSelect, variant);
571 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
572 return code;
573 }
574
575 /* get_accChild([in] varChild, [out] ppdispChild)
576 * Ownership of ppdispChild transfers from callee to caller so reference count on ppdispChild
577 * must be incremented before returning. The caller is responsible for releasing ppdispChild.
578 */
579 HRESULT get_accChild(VARIANT variant, LPDISPATCH* ppdispChild) {
580 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
581 VARIANT* v = &variant;
582 //COM.MoveMemory(v, variant, VARIANT.sizeof);
583 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
584 if (accessibleControlListeners.length is 0) {
585 int code = iaccessible.get_accChild(variant, ppdispChild);
586 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
587 return code;
588 }
589
590 AccessibleControlEvent event = new AccessibleControlEvent(this);
591 event.childID = osToChildID(v.lVal);
592 for (int i = 0; i < accessibleControlListeners.length; i++) {
593 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
594 listener.getChild(event);
595 }
596 Accessible accessible = event.accessible;
597 if (accessible !is null) {
598 accessible.AddRef();
599 *ppdispChild = accessible.objIAccessible;
600 return COM.S_OK;
601 }
602 return COM.S_FALSE;
603 }
604
605 HRESULT get_accChildCount(LONG* pcountChildren) {
606 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
607
608 /* Get the default child count from the OS. */
609 int osChildCount = 0;
610 int code = iaccessible.get_accChildCount(pcountChildren);
611 if (accessibleControlListeners.length is 0) return code;
612 if (code is COM.S_OK) {
613 int[1] pChildCount;
614 COM.MoveMemory(pChildCount.ptr, pcountChildren, 4);
615 osChildCount = pChildCount[0];
616 }
617
618 AccessibleControlEvent event = new AccessibleControlEvent(this);
619 event.childID = ACC.CHILDID_SELF;
620 event.detail = osChildCount;
621 for (int i = 0; i < accessibleControlListeners.length; i++) {
622 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
623 listener.getChildCount(event);
624 }
625
626 *pcountChildren = event.detail;
627 return COM.S_OK;
628 }
629
630 HRESULT get_accDefaultAction(VARIANT variant, BSTR* pszDefaultAction) {
631 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
632 VARIANT* v = &variant;
633 //COM.MoveMemory(v, variant, VARIANT.sizeof);
634 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
635
636 /* Get the default defaultAction from the OS. */
637 String osDefaultAction = null;
638 int code = iaccessible.get_accDefaultAction(variant, pszDefaultAction);
639 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
640 if (accessibleControlListeners.length is 0) return code;
641 if (code is COM.S_OK) {
642 osDefaultAction = BSTRToStr( *pszDefaultAction, true );
643 }
644
645 AccessibleControlEvent event = new AccessibleControlEvent(this);
646 event.childID = osToChildID(v.lVal);
647 event.result = osDefaultAction;
648 for (int i = 0; i < accessibleControlListeners.length; i++) {
649 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
650 listener.getDefaultAction(event);
651 }
652 if (event.result is null) return code;
653 auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
654 *pszDefaultAction = ptr;
655 return COM.S_OK;
656 }
657
658 HRESULT get_accDescription(VARIANT variant, BSTR* pszDescription) {
659 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
660 VARIANT* v = &variant;
661 //COM.MoveMemory(v, variant, VARIANT.sizeof);
662 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
663
664 /* Get the default description from the OS. */
665 String osDescription = null;
666 int code = iaccessible.get_accDescription(variant, pszDescription);
667 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
668 // TEMPORARY CODE - process tree even if there are no apps listening
669 if (accessibleListeners.length is 0 && !( null is cast(Tree)control )) return code;
670 if (code is COM.S_OK) {
671 int size = COM.SysStringByteLen(*pszDescription);
672 if (size > 0) {
673 size = (size + 1) /2;
674 osDescription = WCHARzToStr(*pszDescription, size);
675 }
676 }
677
678 AccessibleEvent event = new AccessibleEvent(this);
679 event.childID = osToChildID(v.lVal);
680 event.result = osDescription;
681
682 // TEMPORARY CODE
683 /* Currently our tree columns are emulated using custom draw,
684 * so we need to create the description using the tree column
685 * header text and tree item text. */
686 if (v.lVal !is COM.CHILDID_SELF) {
687 if (auto tree = cast(Tree)control ) {
688 int columnCount = tree.getColumnCount ();
689 if (columnCount > 1) {
690 HWND hwnd = control.handle;
691 int hItem;
692 if (OS.COMCTL32_MAJOR >= 6) {
693 hItem = OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
694 } else {
695 hItem = v.lVal;
696 }
697 Widget widget = tree.getDisplay ().findWidget (hwnd, hItem);
698 event.result = "";
699 if (widget !is null ) if( auto item = cast(TreeItem) widget ) {
700 for (int i = 1; i < columnCount; i++) {
701 event.result ~= tree.getColumn(i).getText() ~ ": " ~ item.getText(i);
702 if (i + 1 < columnCount) event.result ~= ", ";
703 }
704 }
705 }
706 }
707 }
708 for (int i = 0; i < accessibleListeners.length; i++) {
709 AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
710 listener.getDescription(event);
711 }
712 if (event.result is null) return code;
713 auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
714 *pszDescription = ptr;
715 return COM.S_OK;
716 }
717
718 /* get_accFocus([out] int pvarChild)
719 * Ownership of pvarChild transfers from callee to caller so reference count on pvarChild
720 * must be incremented before returning. The caller is responsible for releasing pvarChild.
721 */
722 HRESULT get_accFocus(VARIANT* pvarChild) {
723 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
724
725 /* Get the default focus child from the OS. */
726 int osChild = ACC.CHILDID_NONE;
727 int code = iaccessible.get_accFocus(pvarChild);
728 if (accessibleControlListeners.length is 0) return code;
729 if (code is COM.S_OK) {
730 //TODO - use VARIANT structure
731 short[1] pvt;
732 COM.MoveMemory(pvt.ptr, pvarChild, 2);
733 if (pvt[0] is COM.VT_I4) {
734 int[1] pChild;
735 COM.MoveMemory(pChild.ptr, pvarChild + 8, 4);
736 osChild = osToChildID(pChild[0]);
737 }
738 }
739
740 AccessibleControlEvent event = new AccessibleControlEvent(this);
741 event.childID = osChild;
742 for (int i = 0; i < accessibleControlListeners.length; i++) {
743 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
744 listener.getFocus(event);
745 }
746 Accessible accessible = event.accessible;
747 if (accessible !is null) {
748 accessible.AddRef();
749 pvarChild.vt = COM.VT_DISPATCH;
750 pvarChild.byRef = cast(void*)cast(IDispatch)accessible.objIAccessible;
751 return COM.S_OK;
752 }
753 int childID = event.childID;
754 if (childID is ACC.CHILDID_NONE) {
755 pvarChild.vt = COM.VT_EMPTY;
756 return COM.S_FALSE;
757 }
758 if (childID is ACC.CHILDID_SELF) {
759 AddRef();
760 pvarChild.vt = COM.VT_DISPATCH;
761 pvarChild.byRef = cast(void*)cast(IDispatch)objIAccessible;
762 return COM.S_OK;
763 }
764 pvarChild.vt = COM.VT_I4;
765 pvarChild.lVal = childIDToOs(childID);
766 return COM.S_OK;
767 }
768
769 HRESULT get_accHelp(VARIANT variant, BSTR* pszHelp) {
770 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
771 VARIANT* v = &variant;
772 //COM.MoveMemory(v, variant, VARIANT.sizeof);
773 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
774
775 /* Get the default help string from the OS. */
776 String osHelp = null;
777 int code = iaccessible.get_accHelp(variant, pszHelp);
778 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
779 if (accessibleListeners.length is 0) return code;
780 if (code is COM.S_OK) {
781 // the original SysString is clearuped and bstr set to null
782 osHelp = BSTRToStr(*pszHelp, true);
783 }
784
785 AccessibleEvent event = new AccessibleEvent(this);
786 event.childID = osToChildID(v.lVal);
787 event.result = osHelp;
788 for (int i = 0; i < accessibleListeners.length; i++) {
789 AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
790 listener.getHelp(event);
791 }
792 if (event.result is null) return code;
793 auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
794 *pszHelp = ptr;
795 return COM.S_OK;
796 }
797
798 HRESULT get_accHelpTopic(BSTR* pszHelpFile, VARIANT variant, LONG* pidTopic) {
799 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
800 // Currently, we don't let the application override this. Forward to the proxy.
801 int code = iaccessible.get_accHelpTopic(pszHelpFile, variant, pidTopic);
802 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
803 return code;
804 }
805
806 HRESULT get_accKeyboardShortcut(VARIANT variant, BSTR* pszKeyboardShortcut) {
807 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
808 VARIANT* v = &variant;
809 //COM.MoveMemory(v, variant, VARIANT.sizeof);
810 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
811
812 /* Get the default keyboard shortcut from the OS. */
813 String osKeyboardShortcut = null;
814 int code = iaccessible.get_accKeyboardShortcut(variant, pszKeyboardShortcut);
815 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
816 if (accessibleListeners.length is 0) return code;
817 if (code is COM.S_OK) {
818 // the original SysString is clearuped and bstr set to null
819 osKeyboardShortcut = BSTRToStr(*pszKeyboardShortcut, true);
820 }
821
822 AccessibleEvent event = new AccessibleEvent(this);
823 event.childID = osToChildID(v.lVal);
824 event.result = osKeyboardShortcut;
825 for (int i = 0; i < accessibleListeners.length; i++) {
826 AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
827 listener.getKeyboardShortcut(event);
828 }
829 if (event.result is null) return code;
830 auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
831 *pszKeyboardShortcut = ptr;
832 return COM.S_OK;
833 }
834
835 HRESULT get_accName(VARIANT variant, BSTR* pszName) {
836 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
837 VARIANT* v = &variant;
838 //COM.MoveMemory(v, variant, VARIANT.sizeof);
839 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
840
841 /* Get the default name from the OS. */
842 String osName = null;
843 int code = iaccessible.get_accName(variant, pszName);
844 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
845 if (accessibleListeners.length is 0) return code;
846 if (code is COM.S_OK) {
847 // the original SysString is clearuped and bstr set to null
848 osName = BSTRToStr(*pszName, true);
849 }
850
851 AccessibleEvent event = new AccessibleEvent(this);
852 event.childID = osToChildID(v.lVal);
853 event.result = osName;
854 for (int i = 0; i < accessibleListeners.length; i++) {
855 AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
856 listener.getName(event);
857 }
858 if (event.result is null) return code;
859 auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
860 *pszName = ptr;
861 return COM.S_OK;
862 }
863
864 /* get_accParent([out] ppdispParent)
865 * Ownership of ppdispParent transfers from callee to caller so reference count on ppdispParent
866 * must be incremented before returning. The caller is responsible for releasing ppdispParent.
867 */
868 HRESULT get_accParent(LPDISPATCH* ppdispParent) {
869 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
870 // Currently, we don't let the application override this. Forward to the proxy.
871 return iaccessible.get_accParent(ppdispParent);
872 }
873
874 HRESULT get_accRole(VARIANT variant, VARIANT* pvarRole) {
875 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
876 VARIANT* v = &variant;
877 //COM.MoveMemory(v, variant, VARIANT.sizeof);
878 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
879
880 /* Get the default role from the OS. */
881 int osRole = COM.ROLE_SYSTEM_CLIENT;
882 int code = iaccessible.get_accRole(variant, pvarRole);
883 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
884 // TEMPORARY CODE - process tree and table even if there are no apps listening
885 if (accessibleControlListeners.length is 0 && !( null !is cast(Tree)control || null !is cast(Table)control )) return code;
886 if (code is COM.S_OK) {
887 //TODO - use VARIANT structure
888 short[1] pvt;
889 COM.MoveMemory(pvt.ptr, pvarRole, 2);
890 if (pvt[0] is COM.VT_I4) {
891 int[1] pRole;
892 COM.MoveMemory(pRole.ptr, pvarRole + 8, 4);
893 osRole = pRole[0];
894 }
895 }
896
897 AccessibleControlEvent event = new AccessibleControlEvent(this);
898 event.childID = osToChildID(v.lVal);
899 event.detail = osToRole(osRole);
900 // TEMPORARY CODE
901 /* Currently our checkbox table and tree are emulated using state mask
902 * images, so we need to specify 'checkbox' role for the items. */
903 if (v.lVal !is COM.CHILDID_SELF) {
904 if ( null !is cast(Tree)control || null !is cast(Table)control ) {
905 if ((control.getStyle() & SWT.CHECK) !is 0) event.detail = ACC.ROLE_CHECKBUTTON;
906 }
907 }
908 for (int i = 0; i < accessibleControlListeners.length; i++) {
909 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
910 listener.getRole(event);
911 }
912 int role = roleToOs(event.detail);
913 pvarRole.vt = COM.VT_I4;
914 pvarRole.lVal = role;
915 return COM.S_OK;
916 }
917
918 /* get_accSelection([out] pvarChildren)
919 * Ownership of pvarChildren transfers from callee to caller so reference count on pvarChildren
920 * must be incremented before returning. The caller is responsible for releasing pvarChildren.
921 */
922 HRESULT get_accSelection(VARIANT* pvarChildren) {
923 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
924
925 /* Get the default selection from the OS. */
926 int osChild = ACC.CHILDID_NONE;
927 int code = iaccessible.get_accSelection(pvarChildren);
928 if (accessibleControlListeners.length is 0) return code;
929 if (code is COM.S_OK) {
930 //TODO - use VARIANT structure
931 short[1] pvt;
932 COM.MoveMemory(pvt.ptr, pvarChildren, 2);
933 if (pvt[0] is COM.VT_I4) {
934 int[1] pChild;
935 COM.MoveMemory(pChild.ptr, pvarChildren + 8, 4);
936 osChild = osToChildID(pChild[0]);
937 } else if (pvt[0] is COM.VT_UNKNOWN) {
938 osChild = ACC.CHILDID_MULTIPLE;
939 /* Should get IEnumVARIANT from punkVal field, and enumerate children... */
940 }
941 }
942
943 AccessibleControlEvent event = new AccessibleControlEvent(this);
944 event.childID = osChild;
945 for (int i = 0; i < accessibleControlListeners.length; i++) {
946 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
947 listener.getSelection(event);
948 }
949 Accessible accessible = event.accessible;
950 if (accessible !is null) {
951 accessible.AddRef();
952 pvarChildren.vt = COM.VT_DISPATCH;
953 pvarChildren.byRef = cast(void*)cast(IDispatch)accessible.objIAccessible;
954 return COM.S_OK;
955 }
956 int childID = event.childID;
957 if (childID is ACC.CHILDID_NONE) {
958 pvarChildren.vt = COM.VT_EMPTY;
959 return COM.S_FALSE;
960 }
961 if (childID is ACC.CHILDID_MULTIPLE) {
962 AddRef();
963 pvarChildren.vt = COM.VT_UNKNOWN;
964 pvarChildren.byRef = cast(void*)cast(IUnknown)objIAccessible;
965 return COM.S_OK;
966 }
967 if (childID is ACC.CHILDID_SELF) {
968 AddRef();
969 pvarChildren.vt = COM.VT_DISPATCH;
970 pvarChildren.byRef = cast(void*)cast(IDispatch)objIAccessible;
971 return COM.S_OK;
972 }
973 pvarChildren.vt = COM.VT_I4;
974 pvarChildren.lVal = childIDToOs(childID);
975 return COM.S_OK;
976 }
977
978 HRESULT get_accState(VARIANT variant, VARIANT* pvarState) {
979 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
980 VARIANT* v = &variant;
981 //COM.MoveMemory(v, variant, VARIANT.sizeof);
982 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
983
984 /* Get the default state from the OS. */
985 int osState = 0;
986 int code = iaccessible.get_accState(variant, pvarState);
987 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
988 // TEMPORARY CODE - process tree and table even if there are no apps listening
989 if (accessibleControlListeners.length is 0 && !( null !is cast(Tree)control || null !is cast(Table)control )) return code;
990 if (code is COM.S_OK) {
991 //TODO - use VARIANT structure
992 short[1] pvt;
993 COM.MoveMemory(pvt.ptr, pvarState, 2);
994 if (pvt[0] is COM.VT_I4) {
995 int[1] pState;
996 COM.MoveMemory(pState.ptr, pvarState + 8, 4);
997 osState = pState[0];
998 }
999 }
1000 bool grayed = false;
1001 AccessibleControlEvent event = new AccessibleControlEvent(this);
1002 event.childID = osToChildID(v.lVal);
1003 event.detail = osToState(osState);
1004 // TEMPORARY CODE
1005 /* Currently our checkbox table and tree are emulated using state mask
1006 * images, so we need to determine if the item state is 'checked'. */
1007 if (v.lVal !is COM.CHILDID_SELF) {
1008 if (null !is cast(Tree)control && (control.getStyle() & SWT.CHECK) !is 0) {
1009 auto hwnd = control.handle;
1010 TVITEM tvItem;
1011 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
1012 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
1013 if (OS.COMCTL32_MAJOR >= 6) {
1014 tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
1015 } else {
1016 tvItem.hItem = cast(HTREEITEM) v.lVal;
1017 }
1018 auto result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
1019 bool checked = (result !is 0) && (((tvItem.state >> 12) & 1) is 0);
1020 if (checked) event.detail |= ACC.STATE_CHECKED;
1021 grayed = tvItem.state >> 12 > 2;
1022 } else if (null !is cast(Table)control && (control.getStyle() & SWT.CHECK) !is 0) {
1023 Table table = cast(Table) control;
1024 int index = event.childID;
1025 if (0 <= index && index < table.getItemCount()) {
1026 TableItem item = table.getItem(index);
1027 if (item.getChecked()) event.detail |= ACC.STATE_CHECKED;
1028 if (item.getGrayed()) grayed = true;
1029 }
1030 }
1031 }
1032 for (int i = 0; i < accessibleControlListeners.length; i++) {
1033 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
1034 listener.getState(event);
1035 }
1036 int state = stateToOs(event.detail);
1037 if ((state & ACC.STATE_CHECKED) !is 0 && grayed) {
1038 state &= ~ COM.STATE_SYSTEM_CHECKED;
1039 state |= COM.STATE_SYSTEM_MIXED;
1040 }
1041 pvarState.vt = COM.VT_I4;
1042 pvarState.lVal = state;
1043 return COM.S_OK;
1044 }
1045
1046 HRESULT get_accValue(VARIANT variant, BSTR* pszValue) {
1047 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
1048 VARIANT* v = &variant;
1049 //COM.MoveMemory(v, variant, VARIANT.sizeof);
1050 if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
1051
1052 /* Get the default value string from the OS. */
1053 String osValue = null;
1054 int code = iaccessible.get_accValue(variant, pszValue);
1055 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
1056 if (accessibleControlListeners.length is 0) return code;
1057 if (code is COM.S_OK) {
1058 int size = COM.SysStringByteLen(*pszValue);
1059 if (size > 0) {
1060 osValue = WCHARsToStr((*pszValue)[ 0 .. size ]);
1061 }
1062 }
1063
1064 AccessibleControlEvent event = new AccessibleControlEvent(this);
1065 event.childID = osToChildID(v.lVal);
1066 event.result = osValue;
1067 for (int i = 0; i < accessibleControlListeners.length; i++) {
1068 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
1069 listener.getValue(event);
1070 }
1071 if (event.result is null) return code;
1072 auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
1073 *pszValue = ptr;
1074 return COM.S_OK;
1075 }
1076
1077 HRESULT put_accName(VARIANT variant, BSTR* szName) {
1078 // MSAA: this method is no longer supported
1079 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
1080 // We don't implement this. Forward to the proxy.
1081 int code = iaccessible.put_accName(variant, szName);
1082 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
1083 return code;
1084 }
1085
1086 HRESULT put_accValue(VARIANT variant, BSTR* szValue) {
1087 // MSAA: this method is typically only used for edit controls
1088 if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
1089 // We don't implement this. Forward to the proxy.
1090 int code = iaccessible.put_accValue(variant, szValue);
1091 if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
1092 return code;
1093 }
1094
1095 /* IEnumVARIANT methods: Next, Skip, Reset, Clone */
1096 /* Retrieve the next celt items in the enumeration sequence.
1097 * If there are fewer than the requested number of elements left
1098 * in the sequence, retrieve the remaining elements.
1099 * The number of elements actually retrieved is returned in pceltFetched
1100 * (unless the caller passed in NULL for that parameter).
1101 */
1102
1103 /* Next([in] celt, [out] rgvar, [in, out] pceltFetched)
1104 * Ownership of rgvar transfers from callee to caller so reference count on rgvar
1105 * must be incremented before returning. The caller is responsible for releasing rgvar.
1106 */
1107 HRESULT Next(ULONG celt, VARIANT *rgvar, ULONG *pceltFetched) {
1108 /* If there are no listeners, query the proxy for
1109 * its IEnumVariant, and get the Next items from it.
1110 */
1111 if (accessibleControlListeners.length is 0) {
1112 IEnumVARIANT ienumvariant;
1113 int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
1114 if (code !is COM.S_OK) return code;
1115 uint[1] celtFetched;
1116 code = ienumvariant.Next(celt, rgvar, celtFetched.ptr);
1117 ienumvariant.Release();
1118 COM.MoveMemory(pceltFetched, celtFetched.ptr, 4);
1119 return code;
1120 }
1121
1122 if (rgvar is null) return COM.E_INVALIDARG;
1123 if (pceltFetched is null && celt !is 1) return COM.E_INVALIDARG;
1124 if (enumIndex is 0) {
1125 AccessibleControlEvent event = new AccessibleControlEvent(this);
1126 event.childID = ACC.CHILDID_SELF;
1127 for (int i = 0; i < accessibleControlListeners.length; i++) {
1128 AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
1129 listener.getChildren(event);
1130 }
1131 variants = event.children;
1132 }
1133 Object[] nextItems = null;
1134 if (variants !is null && celt >= 1) {
1135 int endIndex = enumIndex + celt - 1;
1136 if (endIndex > (variants.length - 1)) endIndex = variants.length - 1;
1137 if (enumIndex <= endIndex) {
1138 nextItems = new Object[endIndex - enumIndex + 1];
1139 for (int i = 0; i < nextItems.length; i++) {
1140 Object child = variants[enumIndex];
1141 if (auto val = cast(ValueWrapperInt)child ) {
1142 nextItems[i] = new ValueWrapperInt(childIDToOs(val.value));
1143 } else {
1144 nextItems[i] = child;
1145 }
1146 enumIndex++;
1147 }
1148 }
1149 }
1150 if (nextItems !is null) {
1151 for (int i = 0; i < nextItems.length; i++) {
1152 Object nextItem = nextItems[i];
1153 if (auto val = cast(ValueWrapperInt)nextItem ) {
1154 int item = val.value;
1155 rgvar[i].vt = COM.VT_I4;
1156 rgvar[i].byRef = cast(void*)item;
1157 COM.MoveMemory(rgvar + i * VARIANT.sizeof + 8, &item, 4);
1158 } else {
1159 Accessible accessible = cast(Accessible) nextItem;
1160 accessible.AddRef();
1161 rgvar[i].vt = COM.VT_DISPATCH;
1162 rgvar[i].byRef = cast(void*)accessible.objIAccessible;
1163 }
1164 }
1165 if (pceltFetched !is null)
1166 *pceltFetched = nextItems.length;
1167 if (nextItems.length is celt) return COM.S_OK;
1168 } else {
1169 if (pceltFetched !is null){
1170 int zero = 0;
1171 *pceltFetched = 0;
1172 }
1173 }
1174 return COM.S_FALSE;
1175 }
1176
1177 /* Skip over the specified number of elements in the enumeration sequence. */
1178 HRESULT Skip(ULONG celt) {
1179 /* If there are no listeners, query the proxy
1180 * for its IEnumVariant, and tell it to Skip.
1181 */
1182 if (accessibleControlListeners.length is 0) {
1183 IEnumVARIANT ienumvariant;
1184 int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
1185 if (code !is COM.S_OK) return code;
1186 code = ienumvariant.Skip(celt);
1187 ienumvariant.Release();
1188 return code;
1189 }
1190
1191 if (celt < 1 ) return COM.E_INVALIDARG;
1192 enumIndex += celt;
1193 if (enumIndex > (variants.length - 1)) {
1194 enumIndex = variants.length - 1;
1195 return COM.S_FALSE;
1196 }
1197 return COM.S_OK;
1198 }
1199
1200 /* Reset the enumeration sequence to the beginning. */
1201 HRESULT Reset() {
1202 /* If there are no listeners, query the proxy
1203 * for its IEnumVariant, and tell it to Reset.
1204 */
1205 if (accessibleControlListeners.length is 0) {
1206 IEnumVARIANT ienumvariant;
1207 int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
1208 if (code !is COM.S_OK) return code;
1209 code = ienumvariant.Reset();
1210 ienumvariant.Release();
1211 return code;
1212 }
1213
1214 enumIndex = 0;
1215 return COM.S_OK;
1216 }
1217
1218 /* Clone([out] ppEnum)
1219 * Ownership of ppEnum transfers from callee to caller so reference count on ppEnum
1220 * must be incremented before returning. The caller is responsible for releasing ppEnum.
1221 */
1222 int Clone(IEnumVARIANT* ppEnum) {
1223 /* If there are no listeners, query the proxy for
1224 * its IEnumVariant, and get the Clone from it.
1225 */
1226 if (accessibleControlListeners.length is 0) {
1227 IEnumVARIANT ienumvariant;
1228 int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
1229 if (code !is COM.S_OK) return code;
1230 IEnumVARIANT[1] pEnum;
1231 code = ienumvariant.Clone(pEnum.ptr);
1232 ienumvariant.Release();
1233 COM.MoveMemory(ppEnum, pEnum.ptr, (void*).sizeof);
1234 return code;
1235 }
1236
1237 if (ppEnum is null) return COM.E_INVALIDARG;
1238 *ppEnum = objIEnumVARIANT;
1239 AddRef();
1240 return COM.S_OK;
1241 }
1242
1243 int childIDToOs(int childID) {
1244 if (childID is ACC.CHILDID_SELF) return COM.CHILDID_SELF;
1245 /*
1246 * Feature of Windows:
1247 * In Windows XP, tree item ids are 1-based indices. Previous versions
1248 * of Windows use the tree item handle for the accessible child ID.
1249 * For backward compatibility, we still take a handle childID for tree
1250 * items on XP. All other childIDs are 1-based indices.
1251 */
1252 if (!(cast(Tree)control )) return childID + 1;
1253 if (OS.COMCTL32_MAJOR < 6) return childID;
1254 return OS.SendMessage (control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0);
1255 }
1256
1257 int osToChildID(int osChildID) {
1258 if (osChildID is COM.CHILDID_SELF) return ACC.CHILDID_SELF;
1259 /*
1260 * Feature of Windows:
1261 * In Windows XP, tree item ids are 1-based indices. Previous versions
1262 * of Windows use the tree item handle for the accessible child ID.
1263 * For backward compatibility, we still take a handle childID for tree
1264 * items on XP. All other childIDs are 1-based indices.
1265 */
1266 if (!(cast(Tree)control )) return osChildID - 1;
1267 if (OS.COMCTL32_MAJOR < 6) return osChildID;
1268 return OS.SendMessage (control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0);
1269 }
1270
1271 int stateToOs(int state) {
1272 int osState = 0;
1273 if ((state & ACC.STATE_SELECTED) !is 0) osState |= COM.STATE_SYSTEM_SELECTED;
1274 if ((state & ACC.STATE_SELECTABLE) !is 0) osState |= COM.STATE_SYSTEM_SELECTABLE;
1275 if ((state & ACC.STATE_MULTISELECTABLE) !is 0) osState |= COM.STATE_SYSTEM_MULTISELECTABLE;
1276 if ((state & ACC.STATE_FOCUSED) !is 0) osState |= COM.STATE_SYSTEM_FOCUSED;
1277 if ((state & ACC.STATE_FOCUSABLE) !is 0) osState |= COM.STATE_SYSTEM_FOCUSABLE;
1278 if ((state & ACC.STATE_PRESSED) !is 0) osState |= COM.STATE_SYSTEM_PRESSED;
1279 if ((state & ACC.STATE_CHECKED) !is 0) osState |= COM.STATE_SYSTEM_CHECKED;
1280 if ((state & ACC.STATE_EXPANDED) !is 0) osState |= COM.STATE_SYSTEM_EXPANDED;
1281 if ((state & ACC.STATE_COLLAPSED) !is 0) osState |= COM.STATE_SYSTEM_COLLAPSED;
1282 if ((state & ACC.STATE_HOTTRACKED) !is 0) osState |= COM.STATE_SYSTEM_HOTTRACKED;
1283 if ((state & ACC.STATE_BUSY) !is 0) osState |= COM.STATE_SYSTEM_BUSY;
1284 if ((state & ACC.STATE_READONLY) !is 0) osState |= COM.STATE_SYSTEM_READONLY;
1285 if ((state & ACC.STATE_INVISIBLE) !is 0) osState |= COM.STATE_SYSTEM_INVISIBLE;
1286 if ((state & ACC.STATE_OFFSCREEN) !is 0) osState |= COM.STATE_SYSTEM_OFFSCREEN;
1287 if ((state & ACC.STATE_SIZEABLE) !is 0) osState |= COM.STATE_SYSTEM_SIZEABLE;
1288 if ((state & ACC.STATE_LINKED) !is 0) osState |= COM.STATE_SYSTEM_LINKED;
1289 return osState;
1290 }
1291
1292 int osToState(int osState) {
1293 int state = ACC.STATE_NORMAL;
1294 if ((osState & COM.STATE_SYSTEM_SELECTED) !is 0) state |= ACC.STATE_SELECTED;
1295 if ((osState & COM.STATE_SYSTEM_SELECTABLE) !is 0) state |= ACC.STATE_SELECTABLE;
1296 if ((osState & COM.STATE_SYSTEM_MULTISELECTABLE) !is 0) state |= ACC.STATE_MULTISELECTABLE;
1297 if ((osState & COM.STATE_SYSTEM_FOCUSED) !is 0) state |= ACC.STATE_FOCUSED;
1298 if ((osState & COM.STATE_SYSTEM_FOCUSABLE) !is 0) state |= ACC.STATE_FOCUSABLE;
1299 if ((osState & COM.STATE_SYSTEM_PRESSED) !is 0) state |= ACC.STATE_PRESSED;
1300 if ((osState & COM.STATE_SYSTEM_CHECKED) !is 0) state |= ACC.STATE_CHECKED;
1301 if ((osState & COM.STATE_SYSTEM_EXPANDED) !is 0) state |= ACC.STATE_EXPANDED;
1302 if ((osState & COM.STATE_SYSTEM_COLLAPSED) !is 0) state |= ACC.STATE_COLLAPSED;
1303 if ((osState & COM.STATE_SYSTEM_HOTTRACKED) !is 0) state |= ACC.STATE_HOTTRACKED;
1304 if ((osState & COM.STATE_SYSTEM_BUSY) !is 0) state |= ACC.STATE_BUSY;
1305 if ((osState & COM.STATE_SYSTEM_READONLY) !is 0) state |= ACC.STATE_READONLY;
1306 if ((osState & COM.STATE_SYSTEM_INVISIBLE) !is 0) state |= ACC.STATE_INVISIBLE;
1307 if ((osState & COM.STATE_SYSTEM_OFFSCREEN) !is 0) state |= ACC.STATE_OFFSCREEN;
1308 if ((osState & COM.STATE_SYSTEM_SIZEABLE) !is 0) state |= ACC.STATE_SIZEABLE;
1309 if ((osState & COM.STATE_SYSTEM_LINKED) !is 0) state |= ACC.STATE_LINKED;
1310 return state;
1311 }
1312
1313 int roleToOs(int role) {
1314 switch (role) {
1315 case ACC.ROLE_CLIENT_AREA: return COM.ROLE_SYSTEM_CLIENT;
1316 case ACC.ROLE_WINDOW: return COM.ROLE_SYSTEM_WINDOW;
1317 case ACC.ROLE_MENUBAR: return COM.ROLE_SYSTEM_MENUBAR;
1318 case ACC.ROLE_MENU: return COM.ROLE_SYSTEM_MENUPOPUP;
1319 case ACC.ROLE_MENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
1320 case ACC.ROLE_SEPARATOR: return COM.ROLE_SYSTEM_SEPARATOR;
1321 case ACC.ROLE_TOOLTIP: return COM.ROLE_SYSTEM_TOOLTIP;
1322 case ACC.ROLE_SCROLLBAR: return COM.ROLE_SYSTEM_SCROLLBAR;
1323 case ACC.ROLE_DIALOG: return COM.ROLE_SYSTEM_DIALOG;
1324 case ACC.ROLE_LABEL: return COM.ROLE_SYSTEM_STATICTEXT;
1325 case ACC.ROLE_PUSHBUTTON: return COM.ROLE_SYSTEM_PUSHBUTTON;
1326 case ACC.ROLE_CHECKBUTTON: return COM.ROLE_SYSTEM_CHECKBUTTON;
1327 case ACC.ROLE_RADIOBUTTON: return COM.ROLE_SYSTEM_RADIOBUTTON;
1328 case ACC.ROLE_COMBOBOX: return COM.ROLE_SYSTEM_COMBOBOX;
1329 case ACC.ROLE_TEXT: return COM.ROLE_SYSTEM_TEXT;
1330 case ACC.ROLE_TOOLBAR: return COM.ROLE_SYSTEM_TOOLBAR;
1331 case ACC.ROLE_LIST: return COM.ROLE_SYSTEM_LIST;
1332 case ACC.ROLE_LISTITEM: return COM.ROLE_SYSTEM_LISTITEM;
1333 case ACC.ROLE_TABLE: return COM.ROLE_SYSTEM_TABLE;
1334 case ACC.ROLE_TABLECELL: return COM.ROLE_SYSTEM_CELL;
1335 case ACC.ROLE_TABLECOLUMNHEADER: return COM.ROLE_SYSTEM_COLUMNHEADER;
1336 case ACC.ROLE_TABLEROWHEADER: return COM.ROLE_SYSTEM_ROWHEADER;
1337 case ACC.ROLE_TREE: return COM.ROLE_SYSTEM_OUTLINE;
1338 case ACC.ROLE_TREEITEM: return COM.ROLE_SYSTEM_OUTLINEITEM;
1339 case ACC.ROLE_TABFOLDER: return COM.ROLE_SYSTEM_PAGETABLIST;
1340 case ACC.ROLE_TABITEM: return COM.ROLE_SYSTEM_PAGETAB;
1341 case ACC.ROLE_PROGRESSBAR: return COM.ROLE_SYSTEM_PROGRESSBAR;
1342 case ACC.ROLE_SLIDER: return COM.ROLE_SYSTEM_SLIDER;
1343 case ACC.ROLE_LINK: return COM.ROLE_SYSTEM_LINK;
1344 default:
1345 }
1346 return COM.ROLE_SYSTEM_CLIENT;
1347 }
1348
1349 int osToRole(int osRole) {
1350 switch (osRole) {
1351 case COM.ROLE_SYSTEM_CLIENT: return ACC.ROLE_CLIENT_AREA;
1352 case COM.ROLE_SYSTEM_WINDOW: return ACC.ROLE_WINDOW;
1353 case COM.ROLE_SYSTEM_MENUBAR: return ACC.ROLE_MENUBAR;
1354 case COM.ROLE_SYSTEM_MENUPOPUP: return ACC.ROLE_MENU;
1355 case COM.ROLE_SYSTEM_MENUITEM: return ACC.ROLE_MENUITEM;
1356 case COM.ROLE_SYSTEM_SEPARATOR: return ACC.ROLE_SEPARATOR;
1357 case COM.ROLE_SYSTEM_TOOLTIP: return ACC.ROLE_TOOLTIP;
1358 case COM.ROLE_SYSTEM_SCROLLBAR: return ACC.ROLE_SCROLLBAR;
1359 case COM.ROLE_SYSTEM_DIALOG: return ACC.ROLE_DIALOG;
1360 case COM.ROLE_SYSTEM_STATICTEXT: return ACC.ROLE_LABEL;
1361 case COM.ROLE_SYSTEM_PUSHBUTTON: return ACC.ROLE_PUSHBUTTON;
1362 case COM.ROLE_SYSTEM_CHECKBUTTON: return ACC.ROLE_CHECKBUTTON;
1363 case COM.ROLE_SYSTEM_RADIOBUTTON: return ACC.ROLE_RADIOBUTTON;
1364 case COM.ROLE_SYSTEM_COMBOBOX: return ACC.ROLE_COMBOBOX;
1365 case COM.ROLE_SYSTEM_TEXT: return ACC.ROLE_TEXT;
1366 case COM.ROLE_SYSTEM_TOOLBAR: return ACC.ROLE_TOOLBAR;
1367 case COM.ROLE_SYSTEM_LIST: return ACC.ROLE_LIST;
1368 case COM.ROLE_SYSTEM_LISTITEM: return ACC.ROLE_LISTITEM;
1369 case COM.ROLE_SYSTEM_TABLE: return ACC.ROLE_TABLE;
1370 case COM.ROLE_SYSTEM_CELL: return ACC.ROLE_TABLECELL;
1371 case COM.ROLE_SYSTEM_COLUMNHEADER: return ACC.ROLE_TABLECOLUMNHEADER;
1372 case COM.ROLE_SYSTEM_ROWHEADER: return ACC.ROLE_TABLEROWHEADER;
1373 case COM.ROLE_SYSTEM_OUTLINE: return ACC.ROLE_TREE;
1374 case COM.ROLE_SYSTEM_OUTLINEITEM: return ACC.ROLE_TREEITEM;
1375 case COM.ROLE_SYSTEM_PAGETABLIST: return ACC.ROLE_TABFOLDER;
1376 case COM.ROLE_SYSTEM_PAGETAB: return ACC.ROLE_TABITEM;
1377 case COM.ROLE_SYSTEM_PROGRESSBAR: return ACC.ROLE_PROGRESSBAR;
1378 case COM.ROLE_SYSTEM_SLIDER: return ACC.ROLE_SLIDER;
1379 case COM.ROLE_SYSTEM_LINK: return ACC.ROLE_LINK;
1380 default:
1381 }
1382 return ACC.ROLE_CLIENT_AREA;
1383 }
1384
1385 /* checkWidget was copied from Widget, and rewritten to work in this package */
1386 void checkWidget () {
1387 if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
1388 if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
1389 }
1390
1391 /* isValidThread was copied from Widget, and rewritten to work in this package */
1392 WINBOOL isValidThread () {
1393 return control.getDisplay ().getThread () is Thread.getThis ();
1394 }
1395 }
1396
1397 class _IAccessibleImpl : IAccessible {
1398
1399 Accessible parent;
1400 this(Accessible p) { parent = p; }
1401 extern (Windows):
1402 // interface of IUnknown
1403 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
1404 ULONG AddRef() { return parent.AddRef(); }
1405 ULONG Release() { return parent.Release(); }
1406
1407 // interface of IDispatch
1408 HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
1409 HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
1410 HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
1411 HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr) { return COM.E_NOTIMPL; }
1412
1413 // interface of IAccessible
1414 HRESULT get_accParent(LPDISPATCH * ppdispParent) { return parent.get_accParent(ppdispParent); }
1415 HRESULT get_accChildCount(LONG* pcountChildren) { return parent.get_accChildCount(pcountChildren); }
1416 HRESULT get_accChild(VARIANT varChildID, LPDISPATCH* ppdispChild) {
1417 return parent.get_accChild(varChildID, ppdispChild);
1418 }
1419 HRESULT get_accName(VARIANT varID, BSTR* pszName) {
1420 return parent.get_accName(varID, pszName);
1421 }
1422 HRESULT get_accValue(VARIANT varID, BSTR* pszValue) {
1423 return parent.get_accValue(varID, pszValue);
1424 }
1425 HRESULT get_accDescription(VARIANT varID,BSTR* pszDescription) {
1426 return parent.get_accDescription(varID, pszDescription);
1427 }
1428 HRESULT get_accRole(VARIANT varID, VARIANT* pvarRole) {
1429 return parent.get_accRole(varID, pvarRole);
1430 }
1431 HRESULT get_accState(VARIANT varID, VARIANT* pvarState) {
1432 return parent.get_accState(varID, pvarState);
1433 }
1434 HRESULT get_accHelp(VARIANT varID, BSTR* pszHelp) {
1435 return parent.get_accHelp(varID, pszHelp);
1436 }
1437 HRESULT get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild, LONG* pidTopic) {
1438 return parent.get_accHelpTopic(pszHelpFile, varChild, pidTopic);
1439 }
1440 HRESULT get_accKeyboardShortcut(VARIANT varID, BSTR* pszKeyboardShortcut) {
1441 return parent.get_accKeyboardShortcut(varID, pszKeyboardShortcut);
1442 }
1443 HRESULT get_accFocus(VARIANT* pvarID) { return parent.get_accFocus(pvarID); }
1444 HRESULT get_accSelection(VARIANT* pvarChildren) { return parent.get_accSelection(pvarChildren); }
1445 HRESULT get_accDefaultAction(VARIANT varID,BSTR* pszDefaultAction) {
1446 return parent.get_accDefaultAction(varID, pszDefaultAction);
1447 }
1448 HRESULT accSelect(LONG flagsSelect, VARIANT varID) {
1449 return parent.accSelect(flagsSelect, varID);
1450 }
1451 HRESULT accLocation(LONG* pxLeft, LONG* pyTop, LONG* pcxWidth, LONG* pcyHeight, VARIANT varID) {
1452 return parent.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID);
1453 }
1454 HRESULT accNavigate(LONG navDir, VARIANT varStart, VARIANT* pvarEnd) {
1455 return parent.accNavigate(navDir, varStart, pvarEnd);
1456 }
1457 HRESULT accHitTest(LONG xLeft, LONG yTop, VARIANT* pvarID) {
1458 return parent.accHitTest(xLeft, yTop, pvarID);
1459 }
1460 HRESULT accDoDefaultAction(VARIANT varID) {
1461 return parent.accDoDefaultAction(varID);
1462 }
1463 HRESULT put_accName(VARIANT varID, BSTR* szName) {
1464 return parent.put_accName(varID, szName);
1465 }
1466 HRESULT put_accValue(VARIANT varID, BSTR* szValue) {
1467 return parent.put_accValue(varID, szValue);
1468 }
1469 }
1470
1471 class _IEnumVARIANTImpl : IEnumVARIANT {
1472
1473 Accessible parent;
1474 this(Accessible a) { parent = a; }
1475 extern (Windows):
1476 // interface of IUnknown
1477 HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
1478 ULONG AddRef() { return parent.AddRef(); }
1479 ULONG Release() { return parent.Release(); }
1480
1481 // interface of IEnumVARIANT
1482 HRESULT Next(ULONG celt, VARIANT *rgvar, ULONG *pceltFetched) { return parent.Next(celt, rgvar, pceltFetched); }
1483 HRESULT Skip(ULONG celt) { return parent.Skip(celt); }
1484 HRESULT Reset() { return parent.Reset(); }
1485 HRESULT Clone(LPENUMVARIANT * ppenum) { return COM.E_NOTIMPL;}
1486 }
1487