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