]> git.saurik.com Git - wxWidgets.git/blob - src/msw/ole/access.cpp
Better scrolling to cursor.
[wxWidgets.git] / src / msw / ole / access.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ole/access.cpp
3 // Purpose: implementation of wxIAccessible and wxAccessible
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2003-02-12
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "access.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #if defined(__BORLANDC__)
28 #pragma hdrstop
29 #endif
30 #ifndef WX_PRECOMP
31 #include "wx/window.h"
32 #endif
33
34 #include "wx/setup.h"
35
36 #if wxUSE_OLE && wxUSE_ACCESSIBILITY
37
38 #include "wx/log.h"
39 #include "wx/access.h"
40
41 #include <windows.h>
42
43 // for some compilers, the entire ole2.h must be included, not only oleauto.h
44 #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__)
45 #include <ole2.h>
46 #endif
47
48 #include <oleauto.h>
49 #include <oleacc.h>
50
51 #include "wx/msw/ole/oleutils.h"
52
53 #ifndef CHILDID_SELF
54 #define CHILDID_SELF 0
55 #endif
56
57 #ifndef OBJID_CLIENT
58 #define OBJID_CLIENT 0xFFFFFFFC
59 #endif
60
61 // Convert to Windows role
62 int wxConvertToWindowsRole(wxAccRole wxrole);
63
64 // Convert to Windows state
65 long wxConvertToWindowsState(long wxstate);
66
67 // Convert to Windows selection flag
68 int wxConvertToWindowsSelFlag(wxAccSelectionFlags sel);
69
70 // Convert from Windows selection flag
71 wxAccSelectionFlags wxConvertFromWindowsSelFlag(int sel);
72
73 // ----------------------------------------------------------------------------
74 // wxIEnumVARIANT interface implementation
75 // ----------------------------------------------------------------------------
76
77 class wxIEnumVARIANT : public IEnumVARIANT
78 {
79 public:
80 wxIEnumVARIANT(const wxVariant& variant);
81 ~wxIEnumVARIANT() { }
82
83 DECLARE_IUNKNOWN_METHODS;
84
85 // IEnumVARIANT
86 STDMETHODIMP Next(ULONG celt, VARIANT *rgelt, ULONG *pceltFetched);
87 STDMETHODIMP Skip(ULONG celt);
88 STDMETHODIMP Reset();
89 STDMETHODIMP Clone(IEnumVARIANT **ppenum);
90
91 private:
92 wxVariant m_variant; // List of further variants
93 int m_nCurrent; // Current enum position
94
95 DECLARE_NO_COPY_CLASS(wxIEnumVARIANT)
96 };
97
98 // ----------------------------------------------------------------------------
99 // wxIEnumVARIANT
100 // ----------------------------------------------------------------------------
101
102 BEGIN_IID_TABLE(wxIEnumVARIANT)
103 ADD_IID(Unknown)
104 ADD_IID(EnumVARIANT)
105 END_IID_TABLE;
106
107 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumVARIANT)
108
109 // wxVariant contains a list of further variants.
110 wxIEnumVARIANT::wxIEnumVARIANT(const wxVariant& variant)
111 {
112 m_variant = variant;
113 }
114
115 STDMETHODIMP wxIEnumVARIANT::Next(ULONG celt,
116 VARIANT *rgelt,
117 ULONG *pceltFetched)
118 {
119 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumVARIANT::Next"));
120
121 if ( celt > 1 ) {
122 // we only return 1 element at a time - mainly because I'm too lazy to
123 // implement something which you're never asked for anyhow
124 return S_FALSE;
125 }
126
127 if (m_variant.GetType() != wxT("list"))
128 return S_FALSE;
129
130 if ( m_nCurrent < (int) m_variant.GetList().GetCount() ) {
131 if (!wxConvertVariantToOle(m_variant[m_nCurrent++], rgelt[0]))
132 {
133 return S_FALSE;
134 }
135
136 // TODO: should we AddRef if this is an object?
137
138 * pceltFetched = 1;
139 return S_OK;
140 }
141 else {
142 // bad index
143 return S_FALSE;
144 }
145 }
146
147 STDMETHODIMP wxIEnumVARIANT::Skip(ULONG celt)
148 {
149 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumVARIANT::Skip"));
150
151 if (m_variant.GetType() != wxT("list"))
152 return S_FALSE;
153
154 m_nCurrent += celt;
155 if ( m_nCurrent < (int) m_variant.GetList().GetCount() )
156 return S_OK;
157
158 // no, can't skip this many elements
159 m_nCurrent -= celt;
160
161 return S_FALSE;
162 }
163
164 STDMETHODIMP wxIEnumVARIANT::Reset()
165 {
166 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumVARIANT::Reset"));
167
168 m_nCurrent = 0;
169
170 return S_OK;
171 }
172
173 STDMETHODIMP wxIEnumVARIANT::Clone(IEnumVARIANT **ppenum)
174 {
175 wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumVARIANT::Clone"));
176
177 wxIEnumVARIANT *pNew = new wxIEnumVARIANT(m_variant);
178 pNew->AddRef();
179 *ppenum = pNew;
180
181 return S_OK;
182 }
183
184
185 // ----------------------------------------------------------------------------
186 // wxIAccessible implementation of IAccessible interface
187 // ----------------------------------------------------------------------------
188
189 class wxIAccessible : public IAccessible
190 {
191 public:
192 wxIAccessible(wxAccessible *pAccessible);
193
194 DECLARE_IUNKNOWN_METHODS;
195
196 // IAccessible
197
198 // Navigation and Hierarchy
199
200 // Retrieves the child element or child object at a given point on the screen.
201 // All visual objects support this method; sound objects do not support it.
202
203 STDMETHODIMP accHitTest(long xLeft, long yLeft, VARIANT* pVarID);
204
205 // Retrieves the specified object's current screen location. All visual objects must
206 // support this method; sound objects do not support it.
207
208 STDMETHODIMP accLocation ( long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varID);
209
210 // Traverses to another user interface element within a container and retrieves the object.
211 // All visual objects must support this method.
212
213 STDMETHODIMP accNavigate ( long navDir, VARIANT varStart, VARIANT* pVarEnd);
214
215 // Retrieves the address of an IDispatch interface for the specified child.
216 // All objects must support this property.
217
218 STDMETHODIMP get_accChild ( VARIANT varChildID, IDispatch** ppDispChild);
219
220 // Retrieves the number of children that belong to this object.
221 // All objects must support this property.
222
223 STDMETHODIMP get_accChildCount ( long* pCountChildren);
224
225 // Retrieves the IDispatch interface of the object's parent.
226 // All objects support this property.
227
228 STDMETHODIMP get_accParent ( IDispatch** ppDispParent);
229
230 // Descriptive Properties and Methods
231
232 // Performs the object's default action. Not all objects have a default
233 // action.
234
235 STDMETHODIMP accDoDefaultAction(VARIANT varID);
236
237 // Retrieves a string that describes the object's default action.
238 // Not all objects have a default action.
239
240 STDMETHODIMP get_accDefaultAction ( VARIANT varID, BSTR* pszDefaultAction);
241
242 // Retrieves a string that describes the visual appearance of the specified object.
243 // Not all objects have a description.
244
245 STDMETHODIMP get_accDescription ( VARIANT varID, BSTR* pszDescription);
246
247 // Retrieves an object's Help property string.
248 // Not all objects support this property.
249
250 STDMETHODIMP get_accHelp ( VARIANT varID, BSTR* pszHelp);
251
252 // Retrieves the full path of the WinHelp file associated with the specified
253 // object and the identifier of the appropriate topic within that file.
254 // Not all objects support this property.
255
256 STDMETHODIMP get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChild, long* pidTopic);
257
258 // Retrieves the specified object's shortcut key or access key, also known as
259 // the mnemonic. All objects that have a shortcut key or access key support
260 // this property.
261
262 STDMETHODIMP get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKeyboardShortcut);
263
264 // Retrieves the name of the specified object.
265 // All objects support this property.
266
267 STDMETHODIMP get_accName ( VARIANT varID, BSTR* pszName);
268
269 // Retrieves information that describes the role of the specified object.
270 // All objects support this property.
271
272 STDMETHODIMP get_accRole ( VARIANT varID, VARIANT* pVarRole);
273
274 // Retrieves the current state of the specified object.
275 // All objects support this property.
276
277 STDMETHODIMP get_accState ( VARIANT varID, VARIANT* pVarState);
278
279 // Retrieves the value of the specified object.
280 // Not all objects have a value.
281
282 STDMETHODIMP get_accValue ( VARIANT varID, BSTR* pszValue);
283
284 // Selection and Focus
285
286 // Modifies the selection or moves the keyboard focus of the
287 // specified object. All objects that select or receive the
288 // keyboard focus must support this method.
289
290 STDMETHODIMP accSelect ( long flagsSelect, VARIANT varID );
291
292 // Retrieves the object that has the keyboard focus. All objects
293 // that receive the keyboard focus must support this property.
294
295 STDMETHODIMP get_accFocus ( VARIANT* pVarID);
296
297 // Retrieves the selected children of this object. All objects
298 // selected must support this property.
299
300 STDMETHODIMP get_accSelection ( VARIANT * pVarChildren);
301
302 // Obsolete
303
304 STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) { return E_FAIL; }
305 STDMETHODIMP put_accValue(VARIANT varChild, BSTR szName) { return E_FAIL; }
306
307 // IDispatch
308
309 // Get type info
310
311 STDMETHODIMP GetTypeInfo(unsigned int typeInfo, LCID lcid, ITypeInfo** ppTypeInfo);
312
313 // Get type info count
314
315 STDMETHODIMP GetTypeInfoCount(unsigned int* typeInfoCount);
316
317 // Get ids of names
318
319 STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR** names, unsigned int cNames,
320 LCID lcid, DISPID* dispId);
321
322 // Invoke
323
324 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
325 WORD wFlags, DISPPARAMS *pDispParams,
326 VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
327 unsigned int *puArgErr );
328
329 // Helpers
330
331 // Gets the standard IAccessible interface for the given child or object.
332 // Call Release if this is non-NULL.
333 IAccessible* GetChildStdAccessible(int id);
334
335 // Gets the IAccessible interface for the given child or object.
336 // Call Release if this is non-NULL.
337 IAccessible* GetChildAccessible(int id);
338
339 private:
340 wxAccessible *m_pAccessible; // pointer to C++ class we belong to
341
342 DECLARE_NO_COPY_CLASS(wxIAccessible)
343 };
344
345 // ============================================================================
346 // Implementation
347 // ============================================================================
348
349 // ----------------------------------------------------------------------------
350 // wxIAccessible implementation
351 // ----------------------------------------------------------------------------
352 BEGIN_IID_TABLE(wxIAccessible)
353 ADD_IID(Unknown)
354 ADD_IID(Accessible)
355 ADD_IID(Dispatch)
356 END_IID_TABLE;
357
358 IMPLEMENT_IUNKNOWN_METHODS(wxIAccessible)
359
360 wxIAccessible::wxIAccessible(wxAccessible *pAccessible)
361 {
362 wxASSERT( pAccessible != NULL );
363
364 m_pAccessible = pAccessible;
365 }
366
367 // Retrieves the child element or child object at a given point on the screen.
368 // All visual objects support this method; sound objects do not support it.
369
370 STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID)
371 {
372 wxLogDebug("accHitTest");
373 wxASSERT (m_pAccessible != NULL);
374 if (!m_pAccessible)
375 return E_FAIL;
376
377 wxAccessible* childObject = NULL;
378 int childId = 0;
379 VariantInit(pVarID);
380
381 wxAccStatus status = m_pAccessible->HitTest(wxPoint(xLeft, yLeft), & childId, & childObject);
382
383 if (status == wxACC_FAIL)
384 return E_FAIL;
385
386 if (status == wxACC_NOT_IMPLEMENTED)
387 {
388 // Use standard interface instead.
389 IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
390 if (!stdInterface)
391 return E_NOTIMPL;
392 else
393 return stdInterface->accHitTest(xLeft, yLeft, pVarID);
394 }
395
396 if (childObject)
397 {
398 if (childObject == m_pAccessible)
399 {
400 pVarID->vt = VT_I4;
401 pVarID->lVal = CHILDID_SELF;
402 return S_OK;
403 }
404 else
405 {
406 wxIAccessible* childIA = childObject->GetIAccessible();
407 if (!childIA)
408 return E_NOTIMPL;
409
410 if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarID->pdispVal) != S_OK)
411 return E_FAIL;
412
413 pVarID->vt = VT_DISPATCH;
414 return S_OK;
415 }
416 }
417 else if (childId > 0)
418 {
419 pVarID->vt = VT_I4;
420 pVarID->lVal = childId;
421 return S_OK;
422 }
423 else
424 {
425 pVarID->vt = VT_EMPTY;
426 return S_FALSE;
427 }
428
429 return E_NOTIMPL;
430 }
431
432 // Retrieves the specified object's current screen location. All visual objects must
433 // support this method; sound objects do not support it.
434
435 STDMETHODIMP wxIAccessible::accLocation ( long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varID)
436 {
437 wxLogDebug("accLocation");
438 wxASSERT (m_pAccessible != NULL);
439 if (!m_pAccessible)
440 return E_FAIL;
441
442 wxRect rect;
443
444 wxAccStatus status = m_pAccessible->GetLocation(rect, varID.lVal);
445 if (status == wxACC_FAIL)
446 return E_FAIL;
447
448 if (status == wxACC_NOT_IMPLEMENTED)
449 {
450 // Try to use child object directly.
451 if (varID.lVal > 0)
452 {
453 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
454 if (childAccessible)
455 {
456 varID.lVal = 0;
457 HRESULT hResult = childAccessible->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID);
458 childAccessible->Release();
459 return hResult;
460 }
461 else if (m_pAccessible->GetIAccessibleStd())
462 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID);
463 }
464 else if (m_pAccessible->GetIAccessibleStd())
465 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID);
466 }
467 else
468 {
469 *pxLeft = rect.x;
470 *pyTop = rect.y;
471 *pcxWidth = rect.width;
472 *pcyHeight = rect.height;
473 return S_OK;
474 }
475
476 return E_NOTIMPL;
477 }
478
479 // Traverses to another user interface element within a container and retrieves the object.
480 // All visual objects must support this method.
481
482 STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT* pVarEnd)
483 {
484 wxASSERT (m_pAccessible != NULL);
485 if (!m_pAccessible)
486 return E_FAIL;
487 wxLogDebug(wxString(wxT("accNavigate for ")) + m_pAccessible->GetWindow()->GetClassInfo()->GetClassName());
488
489 if ((varStart.vt != VT_I4 && varStart.vt != VT_EMPTY) || varStart.vt < 0)
490 {
491 wxLogDebug("Invalid arg for accNavigate");
492 return E_INVALIDARG;
493 }
494
495 wxAccessible* elementObject = NULL;
496 int elementId = 0;
497 VariantInit(pVarEnd);
498 wxNavDir navDirWX = wxNAVDIR_FIRSTCHILD;
499
500 wxString navStr;
501
502 switch (navDir)
503 {
504 case NAVDIR_DOWN:
505 navDirWX = wxNAVDIR_DOWN;
506 navStr = wxT("wxNAVDIR_DOWN");
507 break;
508
509 case NAVDIR_FIRSTCHILD:
510 navDirWX = wxNAVDIR_FIRSTCHILD;
511 navStr = wxT("wxNAVDIR_FIRSTCHILD");
512 break;
513
514 case NAVDIR_LASTCHILD:
515 navDirWX = wxNAVDIR_LASTCHILD;
516 navStr = wxT("wxNAVDIR_LASTCHILD");
517 break;
518
519 case NAVDIR_LEFT:
520 navDirWX = wxNAVDIR_LEFT;
521 navStr = wxT("wxNAVDIR_LEFT");
522 break;
523
524 case NAVDIR_NEXT:
525 navDirWX = wxNAVDIR_NEXT;
526 navStr = wxT("wxNAVDIR_NEXT");
527 break;
528
529 case NAVDIR_PREVIOUS:
530 navDirWX = wxNAVDIR_PREVIOUS;
531 navStr = wxT("wxNAVDIR_PREVIOUS");
532 break;
533
534 case NAVDIR_RIGHT:
535 navDirWX = wxNAVDIR_RIGHT;
536 navStr = wxT("wxNAVDIR_RIGHT");
537 break;
538
539 case NAVDIR_UP:
540 navDirWX = wxNAVDIR_UP;
541 navStr = wxT("wxNAVDIR_UP");
542 break;
543 default:
544 {
545 wxLogDebug(wxT("Unknown NAVDIR symbol"));
546 break;
547 }
548 }
549 wxLogDebug(navStr);
550
551 wxAccStatus status = m_pAccessible->Navigate(navDirWX, varStart.lVal, & elementId,
552 & elementObject);
553
554 if (status == wxACC_FAIL)
555 {
556 wxLogDebug("wxAccessible::Navigate failed");
557 return E_FAIL;
558 }
559
560 if (status == wxACC_FALSE)
561 {
562 wxLogDebug("wxAccessible::Navigate found no object in this direction");
563 return S_FALSE;
564 }
565
566 if (status == wxACC_NOT_IMPLEMENTED)
567 {
568 wxLogDebug("Navigate not implemented");
569
570 // Try to use child object directly.
571 if (varStart.vt == VT_I4 && varStart.lVal > 0)
572 {
573 IAccessible* childAccessible = GetChildAccessible(varStart.lVal);
574 if (childAccessible)
575 {
576 varStart.lVal = 0;
577 HRESULT hResult = childAccessible->accNavigate(navDir, varStart, pVarEnd);
578 childAccessible->Release();
579 return hResult;
580 }
581 else if (m_pAccessible->GetIAccessibleStd())
582 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accNavigate(navDir, varStart, pVarEnd);
583 }
584 else if (m_pAccessible->GetIAccessibleStd())
585 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accNavigate(navDir, varStart, pVarEnd);
586 }
587 else
588 {
589 if (elementObject)
590 {
591 wxLogDebug("Getting wxIAccessible and calling QueryInterface for Navigate");
592 wxIAccessible* objectIA = elementObject->GetIAccessible();
593 if (!objectIA)
594 {
595 wxLogDebug("No wxIAccessible");
596 return E_FAIL;
597 }
598
599 HRESULT hResult = objectIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarEnd->pdispVal);
600 if (hResult != S_OK)
601 {
602 wxLogDebug("QueryInterface failed");
603 return E_FAIL;
604 }
605
606 wxLogDebug("Called QueryInterface for Navigate");
607 pVarEnd->vt = VT_DISPATCH;
608 return S_OK;
609 }
610 else if (elementId > 0)
611 {
612 wxLogDebug("Returning element id from Navigate");
613 pVarEnd->vt = VT_I4;
614 pVarEnd->lVal = elementId;
615 return S_OK;
616 }
617 else
618 {
619 wxLogDebug("No object in accNavigate");
620 pVarEnd->vt = VT_EMPTY;
621 return S_FALSE;
622 }
623 }
624
625 wxLogDebug("Failing Navigate");
626 return E_NOTIMPL;
627 }
628
629 // Retrieves the address of an IDispatch interface for the specified child.
630 // All objects must support this property.
631
632 STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDispChild)
633 {
634 wxLogDebug("get_accChild");
635 wxASSERT (m_pAccessible != NULL);
636 if (!m_pAccessible)
637 return E_FAIL;
638
639 if (varChildID.vt != VT_I4)
640 {
641 wxLogDebug("Invalid arg for get_accChild");
642 return E_INVALIDARG;
643 }
644
645 if (varChildID.lVal == CHILDID_SELF)
646 {
647 *ppDispChild = this;
648 AddRef();
649 return S_OK;
650 }
651
652 wxAccessible* child = NULL;
653
654 wxAccStatus status = m_pAccessible->GetChild(varChildID.lVal, & child);
655 if (status == wxACC_FAIL)
656 {
657 wxLogDebug("GetChild failed");
658 return E_FAIL;
659 }
660
661 if (status == wxACC_NOT_IMPLEMENTED)
662 {
663 // Use standard interface instead.
664 IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
665 if (!stdInterface)
666 return E_NOTIMPL;
667 else
668 {
669 wxLogDebug("Using standard interface for get_accChild");
670 return stdInterface->get_accChild (varChildID, ppDispChild);
671 }
672 }
673 else
674 {
675 if (child)
676 {
677 wxIAccessible* objectIA = child->GetIAccessible();
678 if (!objectIA)
679 return E_NOTIMPL;
680
681 if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) ppDispChild) != S_OK)
682 {
683 wxLogDebug("QueryInterface failed in get_accChild");
684 return E_FAIL;
685 }
686
687 return S_OK;
688 }
689 else
690 {
691 wxLogDebug("Not an accessible object");
692 return S_FALSE; // Indicates it's not an accessible object
693 }
694 }
695
696 return E_NOTIMPL;
697 }
698
699 // Retrieves the number of children that belong to this object.
700 // All objects must support this property.
701
702 STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren)
703 {
704 wxLogDebug("get_accChildCount");
705 wxASSERT (m_pAccessible != NULL);
706 if (!m_pAccessible)
707 return E_FAIL;
708
709 int childCount = 0;
710 wxAccStatus status = m_pAccessible->GetChildCount(& childCount);
711 if (status == wxACC_FAIL)
712 return E_FAIL;
713
714 if (status == wxACC_NOT_IMPLEMENTED)
715 {
716 // Use standard interface instead.
717 IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
718 if (!stdInterface)
719 return E_NOTIMPL;
720 else
721 {
722 wxLogDebug("Using standard interface for get_accChildCount");
723 HRESULT res = stdInterface->get_accChildCount (pCountChildren);
724 wxString str;
725 str.Printf(wxT("Number of children was %d"), (int) (*pCountChildren));
726 wxLogDebug(str);
727 return res;
728 }
729 }
730 else
731 {
732 * pCountChildren = (long) childCount;
733 return S_OK;
734 }
735
736 return E_NOTIMPL;
737 }
738
739 // Retrieves the IDispatch interface of the object's parent.
740 // All objects support this property.
741
742 STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent)
743 {
744 wxLogDebug("get_accParent");
745 wxASSERT (m_pAccessible != NULL);
746 if (!m_pAccessible)
747 return E_FAIL;
748
749 wxAccessible* parent = NULL;
750 wxAccStatus status = m_pAccessible->GetParent(& parent);
751
752 if (status == wxACC_FAIL)
753 return E_FAIL;
754
755 // It doesn't seem acceptable to return S_FALSE with a NULL
756 // ppDispParent, so if we have no wxWindows parent, we leave
757 // it to the standard interface.
758 if (status == wxACC_NOT_IMPLEMENTED || !parent)
759 {
760 wxLogDebug("Using standard interface to get the parent.");
761 // Use standard interface instead.
762 IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
763 if (!stdInterface)
764 return E_NOTIMPL;
765 else
766 return stdInterface->get_accParent (ppDispParent);
767 }
768 else
769 {
770 if (parent)
771 {
772 wxIAccessible* objectIA = parent->GetIAccessible();
773 if (!objectIA)
774 return E_FAIL;
775
776 wxLogDebug("About to call QueryInterface");
777 if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) ppDispParent) != S_OK)
778 {
779 wxLogDebug("Failed QueryInterface");
780 return E_FAIL;
781 }
782
783 wxLogDebug("Returning S_OK for get_accParent");
784 return S_OK;
785 }
786 else
787 {
788 // This doesn't seem to be allowed, despite the documentation,
789 // so we handle it higher up by using the standard interface.
790 wxLogDebug("Returning NULL parent because there was none");
791 *ppDispParent = NULL;
792 return S_FALSE;
793 }
794 }
795
796 return E_NOTIMPL;
797 }
798
799 // Performs the object's default action. Not all objects have a default
800 // action.
801
802 STDMETHODIMP wxIAccessible::accDoDefaultAction(VARIANT varID)
803 {
804 wxLogDebug("accDoDefaultAction");
805 wxASSERT (m_pAccessible != NULL);
806 if (!m_pAccessible)
807 return E_FAIL;
808
809 if (varID.vt != VT_I4)
810 {
811 wxLogDebug("Invalid arg for accDoDefaultAction");
812 return E_INVALIDARG;
813 }
814
815 wxAccStatus status = m_pAccessible->DoDefaultAction(varID.lVal);
816 if (status == wxACC_FAIL)
817 return E_FAIL;
818
819 if (status == wxACC_NOT_SUPPORTED)
820 return DISP_E_MEMBERNOTFOUND;
821
822 if (status == wxACC_NOT_IMPLEMENTED)
823 {
824 // Try to use child object directly.
825 if (varID.lVal > 0)
826 {
827 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
828 if (childAccessible)
829 {
830 varID.lVal = 0;
831 HRESULT hResult = childAccessible->accDoDefaultAction(varID);
832 childAccessible->Release();
833 return hResult;
834 }
835 else if (m_pAccessible->GetIAccessibleStd())
836 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accDoDefaultAction(varID);
837 }
838 else if (m_pAccessible->GetIAccessibleStd())
839 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accDoDefaultAction(varID);
840 }
841 return E_FAIL;
842 }
843
844 // Retrieves a string that describes the object's default action.
845 // Not all objects have a default action.
846
847 STDMETHODIMP wxIAccessible::get_accDefaultAction ( VARIANT varID, BSTR* pszDefaultAction)
848 {
849 wxLogDebug("get_accDefaultAction");
850 wxASSERT (m_pAccessible != NULL);
851 if (!m_pAccessible)
852 return E_FAIL;
853
854 if (varID.vt != VT_I4)
855 {
856 wxLogDebug("Invalid arg for get_accDefaultAction");
857 return E_INVALIDARG;
858 }
859
860 wxString defaultAction;
861 wxAccStatus status = m_pAccessible->GetDefaultAction(varID.lVal, & defaultAction);
862 if (status == wxACC_FAIL)
863 return E_FAIL;
864
865 if (status == wxACC_NOT_SUPPORTED)
866 return DISP_E_MEMBERNOTFOUND;
867
868 if (status == wxACC_NOT_IMPLEMENTED)
869 {
870 // Try to use child object directly.
871 if (varID.lVal > 0)
872 {
873 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
874 if (childAccessible)
875 {
876 varID.lVal = 0;
877 HRESULT hResult = childAccessible->get_accDefaultAction(varID, pszDefaultAction);
878 childAccessible->Release();
879 return hResult;
880 }
881 else if (m_pAccessible->GetIAccessibleStd())
882 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDefaultAction(varID, pszDefaultAction);
883 }
884 else if (m_pAccessible->GetIAccessibleStd())
885 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDefaultAction(varID, pszDefaultAction);
886 }
887 else
888 {
889 if (defaultAction.IsEmpty())
890 {
891 * pszDefaultAction = NULL;
892 return S_FALSE;
893 }
894 else
895 {
896 wxBasicString basicString(defaultAction);
897 * pszDefaultAction = basicString.Get();
898 return S_OK;
899 }
900 }
901 return E_FAIL;
902 }
903
904 // Retrieves a string that describes the visual appearance of the specified object.
905 // Not all objects have a description.
906
907 STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescription)
908 {
909 wxLogDebug("get_accDescription");
910 wxASSERT (m_pAccessible != NULL);
911 if (!m_pAccessible)
912 return E_FAIL;
913
914 if (varID.vt != VT_I4)
915 {
916 wxLogDebug("Invalid arg for get_accDescription");
917 return E_INVALIDARG;
918 }
919
920 wxString description;
921 wxAccStatus status = m_pAccessible->GetDescription(varID.lVal, & description);
922 if (status == wxACC_FAIL)
923 return E_FAIL;
924
925 if (status == wxACC_NOT_IMPLEMENTED)
926 {
927 // Try to use child object directly.
928 if (varID.lVal > 0)
929 {
930 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
931 if (childAccessible)
932 {
933 varID.lVal = 0;
934 HRESULT hResult = childAccessible->get_accDescription(varID, pszDescription);
935 childAccessible->Release();
936 return hResult;
937 }
938 else if (m_pAccessible->GetIAccessibleStd())
939 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDescription(varID, pszDescription);
940 }
941 else if (m_pAccessible->GetIAccessibleStd())
942 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDescription(varID, pszDescription);
943 }
944 else
945 {
946 if (description.IsEmpty())
947 {
948 * pszDescription = NULL;
949 return S_FALSE;
950 }
951 else
952 {
953 wxBasicString basicString(description);
954 * pszDescription = basicString.Get();
955 return S_OK;
956 }
957 }
958 return E_NOTIMPL;
959 }
960
961 // Retrieves an object's Help property string.
962 // Not all objects support this property.
963
964 STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp)
965 {
966 wxLogDebug("get_accHelp");
967 wxASSERT (m_pAccessible != NULL);
968 if (!m_pAccessible)
969 return E_FAIL;
970
971 if (varID.vt != VT_I4)
972 {
973 wxLogDebug("Invalid arg for get_accHelp");
974 return E_INVALIDARG;
975 }
976
977 wxString helpString;
978 wxAccStatus status = m_pAccessible->GetHelpText(varID.lVal, & helpString);
979 if (status == wxACC_FAIL)
980 return E_FAIL;
981
982 if (status == wxACC_NOT_IMPLEMENTED)
983 {
984 // Try to use child object directly.
985 if (varID.lVal > 0)
986 {
987 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
988 if (childAccessible)
989 {
990 varID.lVal = 0;
991 HRESULT hResult = childAccessible->get_accHelp(varID, pszHelp);
992 childAccessible->Release();
993 return hResult;
994 }
995 else if (m_pAccessible->GetIAccessibleStd())
996 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelp(varID, pszHelp);
997 }
998 else if (m_pAccessible->GetIAccessibleStd())
999 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelp (varID, pszHelp);
1000 }
1001 else
1002 {
1003 if (helpString.IsEmpty())
1004 {
1005 * pszHelp = NULL;
1006 return S_FALSE;
1007 }
1008 else
1009 {
1010 wxBasicString basicString(helpString);
1011 * pszHelp = basicString.Get();
1012 return S_OK;
1013 }
1014 }
1015 return E_NOTIMPL;
1016 }
1017
1018 // Retrieves the full path of the WinHelp file associated with the specified
1019 // object and the identifier of the appropriate topic within that file.
1020 // Not all objects support this property.
1021 // NOTE: not supported by wxWindows at this time. Use
1022 // GetHelpText instead.
1023
1024 STDMETHODIMP wxIAccessible::get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChild, long* pidTopic)
1025 {
1026 wxLogDebug("get_accHelpTopic");
1027 wxASSERT (m_pAccessible != NULL);
1028 if (!m_pAccessible)
1029 return E_FAIL;
1030
1031 if (varChild.vt != VT_I4)
1032 {
1033 wxLogDebug("Invalid arg for get_accHelpTopic");
1034 return E_INVALIDARG;
1035 }
1036
1037 wxAccStatus status = wxACC_NOT_IMPLEMENTED;
1038 if (status == wxACC_FAIL)
1039 return E_FAIL;
1040
1041 if (status == wxACC_NOT_IMPLEMENTED)
1042 {
1043 // Try to use child object directly.
1044 if (varChild.lVal > 0)
1045 {
1046 IAccessible* childAccessible = GetChildAccessible(varChild.lVal);
1047 if (childAccessible)
1048 {
1049 varChild.lVal = 0;
1050 HRESULT hResult = childAccessible->get_accHelpTopic(pszHelpFile, varChild, pidTopic);
1051 childAccessible->Release();
1052 return hResult;
1053 }
1054 else if (m_pAccessible->GetIAccessibleStd())
1055 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelpTopic(pszHelpFile, varChild, pidTopic);
1056 }
1057 else if (m_pAccessible->GetIAccessibleStd())
1058 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelpTopic (pszHelpFile, varChild, pidTopic);
1059 }
1060 return E_NOTIMPL;
1061 }
1062
1063 // Retrieves the specified object's shortcut key or access key, also known as
1064 // the mnemonic. All objects that have a shortcut key or access key support
1065 // this property.
1066
1067 STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKeyboardShortcut)
1068 {
1069 wxLogDebug("get_accKeyboardShortcut");
1070 *pszKeyboardShortcut = NULL;
1071
1072 wxASSERT (m_pAccessible != NULL);
1073 if (!m_pAccessible)
1074 return E_FAIL;
1075
1076 if (varID.vt != VT_I4)
1077 {
1078 wxLogDebug("Invalid arg for get_accKeyboardShortcut");
1079 return E_INVALIDARG;
1080 }
1081
1082 wxString keyboardShortcut;
1083 wxAccStatus status = m_pAccessible->GetHelpText(varID.lVal, & keyboardShortcut);
1084 if (status == wxACC_FAIL)
1085 return E_FAIL;
1086
1087 if (status == wxACC_NOT_IMPLEMENTED)
1088 {
1089 // Try to use child object directly.
1090 if (varID.lVal > 0)
1091 {
1092 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
1093 if (childAccessible)
1094 {
1095 varID.lVal = 0;
1096 HRESULT hResult = childAccessible->get_accKeyboardShortcut(varID, pszKeyboardShortcut);
1097 childAccessible->Release();
1098 return hResult;
1099 }
1100 else if (m_pAccessible->GetIAccessibleStd())
1101 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accKeyboardShortcut(varID, pszKeyboardShortcut);
1102 }
1103 else if (m_pAccessible->GetIAccessibleStd())
1104 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accKeyboardShortcut (varID, pszKeyboardShortcut);
1105 }
1106 else
1107 {
1108 if (keyboardShortcut.IsEmpty())
1109 {
1110 * pszKeyboardShortcut = NULL;
1111 return S_FALSE;
1112 }
1113 else
1114 {
1115 wxBasicString basicString(keyboardShortcut);
1116 * pszKeyboardShortcut = basicString.Get();
1117 return S_OK;
1118 }
1119 }
1120 return E_NOTIMPL;
1121 }
1122
1123 // Retrieves the name of the specified object.
1124 // All objects support this property.
1125
1126 STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName)
1127 {
1128 wxLogDebug("get_accName");
1129 *pszName = NULL;
1130
1131 wxASSERT (m_pAccessible != NULL);
1132 if (!m_pAccessible)
1133 return E_FAIL;
1134
1135 if (varID.vt != VT_I4)
1136 {
1137 wxLogDebug("Invalid arg for get_accName");
1138 return E_INVALIDARG;
1139 }
1140
1141 wxString name;
1142
1143 wxAccStatus status = m_pAccessible->GetName(varID.lVal, & name);
1144
1145 if (status == wxACC_FAIL)
1146 return E_FAIL;
1147
1148 if (status == wxACC_NOT_IMPLEMENTED)
1149 {
1150 // Try to use child object directly.
1151 if (varID.lVal > 0)
1152 {
1153 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
1154 if (childAccessible)
1155 {
1156 varID.lVal = 0;
1157 HRESULT hResult = childAccessible->get_accName(varID, pszName);
1158 childAccessible->Release();
1159 return hResult;
1160 }
1161 else if (m_pAccessible->GetIAccessibleStd())
1162 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accName(varID, pszName);
1163 }
1164 else if (m_pAccessible->GetIAccessibleStd())
1165 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accName (varID, pszName);
1166 }
1167 else
1168 {
1169 wxBasicString basicString(name);
1170 *pszName = basicString.Get();
1171 return S_OK;
1172 }
1173 return E_NOTIMPL;
1174 }
1175
1176 // Retrieves information that describes the role of the specified object.
1177 // All objects support this property.
1178
1179 STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole)
1180 {
1181 wxLogDebug("get_accRole");
1182 wxASSERT (m_pAccessible != NULL);
1183 if (!m_pAccessible)
1184 return E_FAIL;
1185
1186 if (varID.vt != VT_I4)
1187 {
1188 wxLogDebug("Invalid arg for get_accRole");
1189 return E_INVALIDARG;
1190 }
1191
1192 VariantInit(pVarRole);
1193
1194 wxAccRole role = wxROLE_NONE;
1195
1196 wxAccStatus status = m_pAccessible->GetRole(varID.lVal, & role);
1197
1198 if (status == wxACC_FAIL)
1199 return E_FAIL;
1200
1201 if (status == wxACC_NOT_IMPLEMENTED)
1202 {
1203 // Try to use child object directly.
1204 if (varID.lVal > 0)
1205 {
1206 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
1207 if (childAccessible)
1208 {
1209 varID.lVal = 0;
1210 HRESULT hResult = childAccessible->get_accRole(varID, pVarRole);
1211 childAccessible->Release();
1212 return hResult;
1213 }
1214 else if (m_pAccessible->GetIAccessibleStd())
1215 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accRole(varID, pVarRole);
1216 }
1217 else if (m_pAccessible->GetIAccessibleStd())
1218 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accRole (varID, pVarRole);
1219 }
1220 else
1221 {
1222 if (role == wxROLE_NONE)
1223 {
1224 pVarRole->vt = VT_EMPTY;
1225 return S_OK;
1226 }
1227
1228 pVarRole->lVal = wxConvertToWindowsRole(role);
1229 pVarRole->vt = VT_I4;
1230
1231 return S_OK;
1232 }
1233 return E_NOTIMPL;
1234 }
1235
1236 // Retrieves the current state of the specified object.
1237 // All objects support this property.
1238
1239 STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState)
1240 {
1241 wxLogDebug("get_accState");
1242 wxASSERT (m_pAccessible != NULL);
1243 if (!m_pAccessible)
1244 return E_FAIL;
1245
1246 if (varID.vt != VT_I4 && varID.vt != VT_EMPTY)
1247 {
1248 wxLogDebug("Invalid arg for get_accState");
1249 return E_INVALIDARG;
1250 }
1251
1252 long wxstate = 0;
1253
1254 wxAccStatus status = m_pAccessible->GetState(varID.lVal, & wxstate);
1255 if (status == wxACC_FAIL)
1256 return E_FAIL;
1257
1258 if (status == wxACC_NOT_IMPLEMENTED)
1259 {
1260 // Try to use child object directly.
1261 if (varID.lVal > 0)
1262 {
1263 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
1264 if (childAccessible)
1265 {
1266 varID.lVal = 0;
1267 HRESULT hResult = childAccessible->get_accState(varID, pVarState);
1268 childAccessible->Release();
1269 return hResult;
1270 }
1271 else if (m_pAccessible->GetIAccessibleStd())
1272 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accState(varID, pVarState);
1273 }
1274 else if (m_pAccessible->GetIAccessibleStd())
1275 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accState (varID, pVarState);
1276 }
1277 else
1278 {
1279 long state = wxConvertToWindowsState(wxstate);
1280 pVarState->lVal = state;
1281 pVarState->vt = VT_I4;
1282 return S_OK;
1283 }
1284 return E_NOTIMPL;
1285 }
1286
1287 // Retrieves the value of the specified object.
1288 // Not all objects have a value.
1289
1290 STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue)
1291 {
1292 wxLogDebug("get_accValue");
1293 wxASSERT (m_pAccessible != NULL);
1294 if (!m_pAccessible)
1295 return E_FAIL;
1296
1297 if (varID.vt != VT_I4)
1298 {
1299 wxLogDebug("Invalid arg for get_accValue");
1300 return E_INVALIDARG;
1301 }
1302
1303 wxString strValue;
1304
1305 wxAccStatus status = m_pAccessible->GetValue(varID.lVal, & strValue);
1306
1307 if (status == wxACC_FAIL)
1308 return E_FAIL;
1309
1310 if (status == wxACC_NOT_IMPLEMENTED)
1311 {
1312 // Try to use child object directly.
1313 if (varID.lVal > 0)
1314 {
1315 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
1316 if (childAccessible)
1317 {
1318 varID.lVal = 0;
1319 HRESULT hResult = childAccessible->get_accValue(varID, pszValue);
1320 childAccessible->Release();
1321 return hResult;
1322 }
1323 else if (m_pAccessible->GetIAccessibleStd())
1324 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accValue(varID, pszValue);
1325 }
1326 else if (m_pAccessible->GetIAccessibleStd())
1327 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accValue (varID, pszValue);
1328 }
1329 else
1330 {
1331 wxBasicString basicString(strValue);
1332 * pszValue = basicString.Get();
1333 return S_OK;
1334 }
1335 return E_NOTIMPL;
1336 }
1337
1338 // Modifies the selection or moves the keyboard focus of the
1339 // specified object. All objects that select or receive the
1340 // keyboard focus must support this method.
1341
1342 STDMETHODIMP wxIAccessible::accSelect ( long flagsSelect, VARIANT varID )
1343 {
1344 wxLogDebug("get_accSelect");
1345 wxASSERT (m_pAccessible != NULL);
1346 if (!m_pAccessible)
1347 return E_FAIL;
1348
1349 if (varID.vt != VT_I4 && varID.vt != VT_EMPTY)
1350 {
1351 wxLogDebug("Invalid arg for accSelect");
1352 return E_INVALIDARG;
1353 }
1354
1355 wxAccSelectionFlags wxsel = wxConvertFromWindowsSelFlag(flagsSelect);
1356
1357 wxAccStatus status = m_pAccessible->Select(varID.lVal, wxsel);
1358 if (status == wxACC_FAIL)
1359 return E_FAIL;
1360
1361 if (status == wxACC_NOT_IMPLEMENTED)
1362 {
1363 // Try to use child object directly.
1364 if (varID.lVal > 0 && varID.lVal > 0)
1365 {
1366 IAccessible* childAccessible = GetChildAccessible(varID.lVal);
1367 if (childAccessible)
1368 {
1369 varID.lVal = 0;
1370 HRESULT hResult = childAccessible->accSelect(flagsSelect, varID);
1371 childAccessible->Release();
1372 return hResult;
1373 }
1374 else if (m_pAccessible->GetIAccessibleStd())
1375 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accSelect(flagsSelect, varID);
1376 }
1377 else if (m_pAccessible->GetIAccessibleStd())
1378 return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accSelect(flagsSelect, varID);
1379 }
1380 else
1381 return S_OK;
1382
1383 return E_NOTIMPL;
1384 }
1385
1386 // Retrieves the object that has the keyboard focus. All objects
1387 // that receive the keyboard focus must support this property.
1388
1389 STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID)
1390 {
1391 wxLogDebug("get_accFocus");
1392 wxASSERT (m_pAccessible != NULL);
1393 if (!m_pAccessible)
1394 return E_FAIL;
1395
1396 wxAccessible* childObject = NULL;
1397 int childId = 0;
1398 VariantInit(pVarID);
1399
1400 wxAccStatus status = m_pAccessible->GetFocus(& childId, & childObject);
1401 if (status == wxACC_FAIL)
1402 return E_FAIL;
1403
1404 if (status == wxACC_NOT_IMPLEMENTED)
1405 {
1406 // Use standard interface instead.
1407 IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
1408 if (!stdInterface)
1409 return E_NOTIMPL;
1410 else
1411 return stdInterface->get_accFocus (pVarID);
1412 }
1413 if (childObject)
1414 {
1415 if (childObject == m_pAccessible)
1416 {
1417 pVarID->vt = VT_I4;
1418 pVarID->lVal = CHILDID_SELF;
1419 return S_OK; }
1420 else
1421 {
1422 wxIAccessible* childIA = childObject->GetIAccessible();
1423 if (!childIA)
1424 return E_NOTIMPL;
1425
1426 if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarID->pdispVal) != S_OK)
1427 return E_FAIL;
1428
1429 pVarID->vt = VT_DISPATCH;
1430 return S_OK;
1431 }
1432 }
1433 else if (childId > 0)
1434 {
1435 pVarID->vt = VT_I4;
1436 pVarID->lVal = childId;
1437 return S_OK;
1438 }
1439 else
1440 {
1441 pVarID->vt = VT_EMPTY;
1442 return S_FALSE;
1443 }
1444
1445 return E_NOTIMPL;
1446 }
1447
1448 // Retrieves the selected children of this object. All objects
1449 // selected must support this property.
1450
1451 STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren)
1452 {
1453 wxLogDebug("get_accSelection");
1454 wxASSERT (m_pAccessible != NULL);
1455 if (!m_pAccessible)
1456 return E_FAIL;
1457
1458 VariantInit(pVarChildren);
1459
1460 wxVariant selections;
1461 wxAccStatus status = m_pAccessible->GetSelections(& selections);
1462 if (status == wxACC_FAIL)
1463 return E_FAIL;
1464
1465 if (status == wxACC_NOT_IMPLEMENTED)
1466 {
1467 // Use standard interface instead.
1468 IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd();
1469 if (!stdInterface)
1470 return E_NOTIMPL;
1471 else
1472 return stdInterface->get_accSelection (pVarChildren);
1473 }
1474 else
1475 {
1476 if (selections.GetType() == wxT("long"))
1477 {
1478 pVarChildren->vt = VT_I4;
1479 pVarChildren->lVal = selections.GetLong();
1480
1481 return S_OK;
1482 }
1483 else if (selections.GetType() == wxT("void*"))
1484 {
1485 wxAccessible* childObject = (wxAccessible*) selections.GetVoidPtr();
1486 wxIAccessible* childIA = childObject->GetIAccessible();
1487 if (!childIA)
1488 return E_NOTIMPL;
1489
1490 if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarChildren->pdispVal) != S_OK)
1491 return E_FAIL;
1492
1493 pVarChildren->vt = VT_DISPATCH;
1494
1495 return S_OK;
1496 }
1497 else if (selections.GetType() == wxT("list"))
1498 {
1499 // TODO: should we AddRef for every "void*" member??
1500
1501 wxIEnumVARIANT* enumVariant = new wxIEnumVARIANT(selections);
1502 enumVariant->AddRef();
1503
1504 pVarChildren->vt = VT_UNKNOWN;
1505 pVarChildren->punkVal = enumVariant;
1506
1507 return S_OK;
1508 }
1509 }
1510
1511 return E_NOTIMPL;
1512 }
1513
1514 // Get type info
1515
1516 STDMETHODIMP wxIAccessible::GetTypeInfo(unsigned int typeInfo, LCID lcid, ITypeInfo** ppTypeInfo)
1517 {
1518 *ppTypeInfo = NULL;
1519 return E_NOTIMPL;
1520 }
1521
1522 // Get type info count
1523
1524 STDMETHODIMP wxIAccessible::GetTypeInfoCount(unsigned int* typeInfoCount)
1525 {
1526 *typeInfoCount = 0;
1527 return E_NOTIMPL;
1528 }
1529
1530 // Get ids of names
1531
1532 STDMETHODIMP wxIAccessible::GetIDsOfNames(REFIID riid, OLECHAR** names, unsigned int cNames,
1533 LCID lcid, DISPID* dispId)
1534 {
1535 return E_NOTIMPL;
1536 }
1537
1538 // Invoke
1539
1540 STDMETHODIMP wxIAccessible::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
1541 WORD wFlags, DISPPARAMS *pDispParams,
1542 VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1543 unsigned int *puArgErr )
1544 {
1545 return E_NOTIMPL;
1546 }
1547
1548 // Gets the standard IAccessible interface for the given child or object.
1549 // Call Release if this is non-NULL.
1550 IAccessible* wxIAccessible::GetChildStdAccessible(int id)
1551 {
1552 if (id == 0)
1553 {
1554 IAccessible* obj = (IAccessible*)m_pAccessible->GetIAccessibleStd();
1555
1556 obj->AddRef();
1557 return obj;
1558 }
1559 else
1560 {
1561 VARIANT var;
1562 VariantInit(& var);
1563 var.vt = VT_I4;
1564 var.lVal = id;
1565 IDispatch* pDispatch = NULL;
1566 if (S_OK == get_accChild ( var, & pDispatch))
1567 {
1568 IAccessible* childAccessible = NULL;
1569 if (pDispatch->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
1570 {
1571 pDispatch->Release();
1572 wxIAccessible* c = (wxIAccessible*) childAccessible;
1573 IAccessible* stdChildAccessible = (IAccessible*) c->m_pAccessible->GetIAccessibleStd();
1574 stdChildAccessible->AddRef();
1575 childAccessible->Release();
1576 return stdChildAccessible;
1577 }
1578 else
1579 {
1580 pDispatch->Release();
1581 }
1582 }
1583 }
1584
1585 #if 0
1586 {
1587 // Loop until we find the right id
1588 long nChildren = 0;
1589 this->get_accChildCount(& nChildren);
1590
1591 int i;
1592 for (i = 0; i < nChildren; i++)
1593 {
1594 long obtained = 0;
1595 VARIANT var;
1596 VariantInit(& var);
1597 var.vt = VT_I4;
1598 if (S_OK == AccessibleChildren(this, i, 1, & var, &obtained))
1599 {
1600 if (var.lVal == id)
1601 {
1602 VariantInit(& var);
1603 var.vt = VT_DISPATCH;
1604 if (S_OK == AccessibleChildren(this, i, 1, & var, &obtained))
1605 {
1606 IAccessible* childAccessible = NULL;
1607 if (var.pdispVal->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
1608 {
1609 var.pdispVal->Release();
1610 return childAccessible;
1611 }
1612 else
1613 {
1614 var.pdispVal->Release();
1615 }
1616 }
1617 }
1618 break;
1619 }
1620 }
1621 }
1622 #endif
1623 return NULL;
1624 }
1625
1626 // Gets the IAccessible interface for the given child or object.
1627 // Call Release if this is non-NULL.
1628 IAccessible* wxIAccessible::GetChildAccessible(int id)
1629 {
1630 if (id == 0)
1631 {
1632 IAccessible* obj = this;
1633
1634 obj->AddRef();
1635 return obj;
1636 }
1637 else
1638 {
1639 VARIANT var;
1640 VariantInit(& var);
1641 var.vt = VT_I4;
1642 var.lVal = id;
1643 IDispatch* pDispatch = NULL;
1644 if (S_OK == get_accChild ( var, & pDispatch))
1645 {
1646 IAccessible* childAccessible = NULL;
1647 if (pDispatch->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
1648 {
1649 pDispatch->Release();
1650 return childAccessible;
1651 }
1652 else
1653 {
1654 pDispatch->Release();
1655 }
1656 }
1657 }
1658 return NULL;
1659 }
1660
1661 // ----------------------------------------------------------------------------
1662 // wxAccessible implementation
1663 // ----------------------------------------------------------------------------
1664
1665 // ctors
1666
1667 // common part of all ctors
1668 void wxAccessible::Init()
1669 {
1670 m_pIAccessibleStd = NULL;
1671 m_pIAccessible = new wxIAccessible(this);
1672 m_pIAccessible->AddRef();
1673 }
1674
1675 wxAccessible::wxAccessible(wxWindow* win)
1676 : wxAccessibleBase(win)
1677 {
1678 Init();
1679 }
1680
1681 wxAccessible::~wxAccessible()
1682 {
1683 m_pIAccessible->Release();
1684 if (m_pIAccessibleStd)
1685 ((IAccessible*)m_pIAccessibleStd)->Release();
1686 }
1687
1688 // Gets or creates a standard interface for this object.
1689 void* wxAccessible::GetIAccessibleStd()
1690 {
1691 if (m_pIAccessibleStd)
1692 return m_pIAccessibleStd;
1693
1694 if (GetWindow())
1695 {
1696 HRESULT retCode = ::CreateStdAccessibleObject((HWND) GetWindow()->GetHWND(),
1697 OBJID_CLIENT, IID_IAccessible, (void**) & m_pIAccessibleStd);
1698 if (retCode == S_OK)
1699 return m_pIAccessibleStd;
1700 else
1701 {
1702 m_pIAccessibleStd = NULL;
1703 return NULL;
1704 }
1705 }
1706 return NULL;
1707 }
1708
1709 // Utilities
1710
1711 // Convert to Windows role
1712 int wxConvertToWindowsRole(wxAccRole wxrole)
1713 {
1714 switch (wxrole)
1715 {
1716 case wxROLE_SYSTEM_ALERT:
1717 return ROLE_SYSTEM_ALERT;
1718 case wxROLE_SYSTEM_ANIMATION:
1719 return ROLE_SYSTEM_ANIMATION;
1720 case wxROLE_SYSTEM_APPLICATION:
1721 return ROLE_SYSTEM_APPLICATION;
1722 case wxROLE_SYSTEM_BORDER:
1723 return ROLE_SYSTEM_BORDER;
1724 case wxROLE_SYSTEM_BUTTONDROPDOWN:
1725 return ROLE_SYSTEM_BUTTONDROPDOWN;
1726 case wxROLE_SYSTEM_BUTTONDROPDOWNGRID:
1727 return ROLE_SYSTEM_BUTTONDROPDOWNGRID;
1728 case wxROLE_SYSTEM_BUTTONMENU:
1729 return ROLE_SYSTEM_BUTTONMENU;
1730 case wxROLE_SYSTEM_CARET:
1731 return ROLE_SYSTEM_CARET;
1732 case wxROLE_SYSTEM_CELL:
1733 return ROLE_SYSTEM_CELL;
1734 case wxROLE_SYSTEM_CHARACTER:
1735 return ROLE_SYSTEM_CHARACTER;
1736 case wxROLE_SYSTEM_CHART:
1737 return ROLE_SYSTEM_CHART;
1738 case wxROLE_SYSTEM_CHECKBUTTON:
1739 return ROLE_SYSTEM_CHECKBUTTON;
1740 case wxROLE_SYSTEM_CLIENT:
1741 return ROLE_SYSTEM_CLIENT;
1742 case wxROLE_SYSTEM_CLOCK:
1743 return ROLE_SYSTEM_CLOCK;
1744 case wxROLE_SYSTEM_COLUMN:
1745 return ROLE_SYSTEM_COLUMN;
1746 case wxROLE_SYSTEM_COLUMNHEADER:
1747 return ROLE_SYSTEM_COLUMNHEADER;
1748 case wxROLE_SYSTEM_COMBOBOX:
1749 return ROLE_SYSTEM_COMBOBOX;
1750 case wxROLE_SYSTEM_CURSOR:
1751 return ROLE_SYSTEM_CURSOR;
1752 case wxROLE_SYSTEM_DIAGRAM:
1753 return ROLE_SYSTEM_DIAGRAM;
1754 case wxROLE_SYSTEM_DIAL:
1755 return ROLE_SYSTEM_DIAL;
1756 case wxROLE_SYSTEM_DIALOG:
1757 return ROLE_SYSTEM_DIALOG;
1758 case wxROLE_SYSTEM_DOCUMENT:
1759 return ROLE_SYSTEM_DOCUMENT;
1760 case wxROLE_SYSTEM_DROPLIST:
1761 return ROLE_SYSTEM_DROPLIST;
1762 case wxROLE_SYSTEM_EQUATION:
1763 return ROLE_SYSTEM_EQUATION;
1764 case wxROLE_SYSTEM_GRAPHIC:
1765 return ROLE_SYSTEM_GRAPHIC;
1766 case wxROLE_SYSTEM_GRIP:
1767 return ROLE_SYSTEM_GRIP;
1768 case wxROLE_SYSTEM_GROUPING:
1769 return ROLE_SYSTEM_GROUPING;
1770 case wxROLE_SYSTEM_HELPBALLOON:
1771 return ROLE_SYSTEM_HELPBALLOON;
1772 case wxROLE_SYSTEM_HOTKEYFIELD:
1773 return ROLE_SYSTEM_HOTKEYFIELD;
1774 case wxROLE_SYSTEM_INDICATOR:
1775 return ROLE_SYSTEM_INDICATOR;
1776 case wxROLE_SYSTEM_LINK:
1777 return ROLE_SYSTEM_LINK;
1778 case wxROLE_SYSTEM_LIST:
1779 return ROLE_SYSTEM_LIST;
1780 case wxROLE_SYSTEM_LISTITEM:
1781 return ROLE_SYSTEM_LISTITEM;
1782 case wxROLE_SYSTEM_MENUBAR:
1783 return ROLE_SYSTEM_MENUBAR;
1784 case wxROLE_SYSTEM_MENUITEM:
1785 return ROLE_SYSTEM_MENUITEM;
1786 case wxROLE_SYSTEM_MENUPOPUP:
1787 return ROLE_SYSTEM_MENUPOPUP;
1788 case wxROLE_SYSTEM_OUTLINE:
1789 return ROLE_SYSTEM_OUTLINE;
1790 case wxROLE_SYSTEM_OUTLINEITEM:
1791 return ROLE_SYSTEM_OUTLINEITEM;
1792 case wxROLE_SYSTEM_PAGETAB:
1793 return ROLE_SYSTEM_PAGETAB;
1794 case wxROLE_SYSTEM_PAGETABLIST:
1795 return ROLE_SYSTEM_PAGETABLIST;
1796 case wxROLE_SYSTEM_PANE:
1797 return ROLE_SYSTEM_PANE;
1798 case wxROLE_SYSTEM_PROGRESSBAR:
1799 return ROLE_SYSTEM_PROGRESSBAR;
1800 case wxROLE_SYSTEM_PROPERTYPAGE:
1801 return ROLE_SYSTEM_PROPERTYPAGE;
1802 case wxROLE_SYSTEM_PUSHBUTTON:
1803 return ROLE_SYSTEM_PUSHBUTTON;
1804 case wxROLE_SYSTEM_RADIOBUTTON:
1805 return ROLE_SYSTEM_RADIOBUTTON;
1806 case wxROLE_SYSTEM_ROW:
1807 return ROLE_SYSTEM_ROW;
1808 case wxROLE_SYSTEM_ROWHEADER:
1809 return ROLE_SYSTEM_ROWHEADER;
1810 case wxROLE_SYSTEM_SCROLLBAR:
1811 return ROLE_SYSTEM_SCROLLBAR;
1812 case wxROLE_SYSTEM_SEPARATOR:
1813 return ROLE_SYSTEM_SEPARATOR;
1814 case wxROLE_SYSTEM_SLIDER:
1815 return ROLE_SYSTEM_SLIDER;
1816 case wxROLE_SYSTEM_SOUND:
1817 return ROLE_SYSTEM_SOUND;
1818 case wxROLE_SYSTEM_SPINBUTTON:
1819 return ROLE_SYSTEM_SPINBUTTON;
1820 case wxROLE_SYSTEM_STATICTEXT:
1821 return ROLE_SYSTEM_STATICTEXT;
1822 case wxROLE_SYSTEM_STATUSBAR:
1823 return ROLE_SYSTEM_STATUSBAR;
1824 case wxROLE_SYSTEM_TABLE:
1825 return ROLE_SYSTEM_TABLE;
1826 case wxROLE_SYSTEM_TEXT:
1827 return ROLE_SYSTEM_TEXT;
1828 case wxROLE_SYSTEM_TITLEBAR:
1829 return ROLE_SYSTEM_TITLEBAR;
1830 case wxROLE_SYSTEM_TOOLBAR:
1831 return ROLE_SYSTEM_TOOLBAR;
1832 case wxROLE_SYSTEM_TOOLTIP:
1833 return ROLE_SYSTEM_TOOLTIP;
1834 case wxROLE_SYSTEM_WHITESPACE:
1835 return ROLE_SYSTEM_WHITESPACE;
1836 case wxROLE_SYSTEM_WINDOW:
1837 return ROLE_SYSTEM_WINDOW;
1838 }
1839 return 0;
1840 }
1841
1842 // Convert to Windows state
1843 long wxConvertToWindowsState(long wxstate)
1844 {
1845 long state = 0;
1846 if (wxstate & wxACC_STATE_SYSTEM_ALERT_HIGH)
1847 state |= STATE_SYSTEM_ALERT_HIGH;
1848
1849 if (wxstate & wxACC_STATE_SYSTEM_ALERT_MEDIUM)
1850 state |= STATE_SYSTEM_ALERT_MEDIUM;
1851
1852 if (wxstate & wxACC_STATE_SYSTEM_ALERT_LOW)
1853 state |= STATE_SYSTEM_ALERT_LOW;
1854
1855 if (wxstate & wxACC_STATE_SYSTEM_ANIMATED)
1856 state |= STATE_SYSTEM_ANIMATED;
1857
1858 if (wxstate & wxACC_STATE_SYSTEM_BUSY)
1859 state |= STATE_SYSTEM_BUSY;
1860
1861 if (wxstate & wxACC_STATE_SYSTEM_CHECKED)
1862 state |= STATE_SYSTEM_CHECKED;
1863
1864 if (wxstate & wxACC_STATE_SYSTEM_COLLAPSED)
1865 state |= STATE_SYSTEM_COLLAPSED;
1866
1867 if (wxstate & wxACC_STATE_SYSTEM_DEFAULT)
1868 state |= STATE_SYSTEM_DEFAULT;
1869
1870 if (wxstate & wxACC_STATE_SYSTEM_EXPANDED)
1871 state |= STATE_SYSTEM_EXPANDED;
1872
1873 if (wxstate & wxACC_STATE_SYSTEM_EXTSELECTABLE)
1874 state |= STATE_SYSTEM_EXTSELECTABLE;
1875
1876 if (wxstate & wxACC_STATE_SYSTEM_FLOATING)
1877 state |= STATE_SYSTEM_FLOATING;
1878
1879 if (wxstate & wxACC_STATE_SYSTEM_FOCUSABLE)
1880 state |= STATE_SYSTEM_FOCUSABLE;
1881
1882 if (wxstate & wxACC_STATE_SYSTEM_FOCUSED)
1883 state |= STATE_SYSTEM_FOCUSED;
1884
1885 if (wxstate & wxACC_STATE_SYSTEM_HOTTRACKED)
1886 state |= STATE_SYSTEM_HOTTRACKED;
1887
1888 if (wxstate & wxACC_STATE_SYSTEM_INVISIBLE)
1889 state |= STATE_SYSTEM_INVISIBLE;
1890
1891 if (wxstate & wxACC_STATE_SYSTEM_INVISIBLE)
1892 state |= STATE_SYSTEM_INVISIBLE;
1893
1894 if (wxstate & wxACC_STATE_SYSTEM_MIXED)
1895 state |= STATE_SYSTEM_MIXED;
1896
1897 if (wxstate & wxACC_STATE_SYSTEM_MULTISELECTABLE)
1898 state |= STATE_SYSTEM_MULTISELECTABLE;
1899
1900 if (wxstate & wxACC_STATE_SYSTEM_OFFSCREEN)
1901 state |= STATE_SYSTEM_OFFSCREEN;
1902
1903 if (wxstate & wxACC_STATE_SYSTEM_PRESSED)
1904 state |= STATE_SYSTEM_PRESSED;
1905
1906 // if (wxstate & wxACC_STATE_SYSTEM_PROTECTED)
1907 // state |= STATE_SYSTEM_PROTECTED;
1908
1909 if (wxstate & wxACC_STATE_SYSTEM_READONLY)
1910 state |= STATE_SYSTEM_READONLY;
1911
1912 if (wxstate & wxACC_STATE_SYSTEM_SELECTABLE)
1913 state |= STATE_SYSTEM_SELECTABLE;
1914
1915 if (wxstate & wxACC_STATE_SYSTEM_SELECTED)
1916 state |= STATE_SYSTEM_SELECTED;
1917
1918 if (wxstate & wxACC_STATE_SYSTEM_SELFVOICING)
1919 state |= STATE_SYSTEM_SELFVOICING;
1920
1921 if (wxstate & wxACC_STATE_SYSTEM_UNAVAILABLE)
1922 state |= STATE_SYSTEM_UNAVAILABLE;
1923
1924 return state;
1925 }
1926
1927 // Convert to Windows selection flag
1928 int wxConvertToWindowsSelFlag(wxAccSelectionFlags wxsel)
1929 {
1930 int sel = 0;
1931
1932 if (sel & wxACC_SEL_TAKEFOCUS)
1933 sel |= SELFLAG_TAKEFOCUS;
1934 if (sel & wxACC_SEL_TAKESELECTION)
1935 sel |= SELFLAG_TAKESELECTION;
1936 if (sel & wxACC_SEL_EXTENDSELECTION)
1937 sel |= SELFLAG_EXTENDSELECTION;
1938 if (sel & wxACC_SEL_ADDSELECTION)
1939 sel |= SELFLAG_ADDSELECTION;
1940 if (sel & wxACC_SEL_REMOVESELECTION)
1941 sel |= SELFLAG_REMOVESELECTION;
1942 return sel;
1943 }
1944
1945 // Convert from Windows selection flag
1946 wxAccSelectionFlags wxConvertFromWindowsSelFlag(int sel)
1947 {
1948 int wxsel = 0;
1949
1950 if (sel & SELFLAG_TAKEFOCUS)
1951 wxsel |= wxACC_SEL_TAKEFOCUS;
1952 if (sel & SELFLAG_TAKESELECTION)
1953 wxsel |= wxACC_SEL_TAKESELECTION;
1954 if (sel & SELFLAG_EXTENDSELECTION)
1955 wxsel |= wxACC_SEL_EXTENDSELECTION;
1956 if (sel & SELFLAG_ADDSELECTION)
1957 wxsel |= wxACC_SEL_ADDSELECTION;
1958 if (sel & SELFLAG_REMOVESELECTION)
1959 wxsel |= wxACC_SEL_REMOVESELECTION;
1960 return (wxAccSelectionFlags) wxsel;
1961 }
1962
1963
1964 #endif //USE_ACCESSIBILITY