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