X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c6e2af4570ee868c93fc504b02f321efe5d5acee..789f8e6ad40488d2dd5f5f4d87e195d0f1e23422:/src/msw/ole/access.cpp?ds=sidebyside diff --git a/src/msw/ole/access.cpp b/src/msw/ole/access.cpp index 834751f4ee..22251ebae9 100644 --- a/src/msw/ole/access.cpp +++ b/src/msw/ole/access.cpp @@ -17,7 +17,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "access.h" #endif @@ -38,7 +38,7 @@ #include "wx/log.h" #include "wx/access.h" -#include +#include "wx/msw/wrapwin.h" // for some compilers, the entire ole2.h must be included, not only oleauto.h #if wxUSE_NORLANDER_HEADERS || defined(__WATCOMC__) @@ -47,6 +47,7 @@ #include #include +#include #include "wx/msw/ole/oleutils.h" @@ -78,7 +79,7 @@ class wxIEnumVARIANT : public IEnumVARIANT { public: wxIEnumVARIANT(const wxVariant& variant); - ~wxIEnumVARIANT() { } + virtual ~wxIEnumVARIANT() { } DECLARE_IUNKNOWN_METHODS; @@ -332,6 +333,10 @@ public: // Call Release if this is non-NULL. IAccessible* GetChildStdAccessible(int id); + // Gets the IAccessible interface for the given child or object. + // Call Release if this is non-NULL. + IAccessible* GetChildAccessible(int id); + private: wxAccessible *m_pAccessible; // pointer to C++ class we belong to @@ -365,7 +370,7 @@ wxIAccessible::wxIAccessible(wxAccessible *pAccessible) STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID) { - wxLogDebug("accHitTest"); + wxLogTrace(wxT("access"), "accHitTest"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; @@ -384,7 +389,7 @@ STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID) // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else return stdInterface->accHitTest(xLeft, yLeft, pVarID); } @@ -401,13 +406,12 @@ STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID) { wxIAccessible* childIA = childObject->GetIAccessible(); if (!childIA) - return E_FAIL; + return E_NOTIMPL; if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarID->pdispVal) != S_OK) return E_FAIL; pVarID->vt = VT_DISPATCH; -// pVarID->pdispVal->AddRef(); return S_OK; } } @@ -423,7 +427,7 @@ STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID) return S_FALSE; } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the specified object's current screen location. All visual objects must @@ -431,7 +435,7 @@ STDMETHODIMP wxIAccessible::accHitTest(long xLeft, long yLeft, VARIANT* pVarID) STDMETHODIMP wxIAccessible::accLocation ( long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varID) { - wxLogDebug("accLocation"); + wxLogTrace(wxT("access"), "accLocation"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; @@ -444,12 +448,22 @@ STDMETHODIMP wxIAccessible::accLocation ( long* pxLeft, long* pyTop, long* pcxWi if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID); } else { @@ -460,7 +474,7 @@ STDMETHODIMP wxIAccessible::accLocation ( long* pxLeft, long* pyTop, long* pcxWi return S_OK; } - return E_FAIL; + return E_NOTIMPL; } // Traverses to another user interface element within a container and retrieves the object. @@ -471,11 +485,11 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; - wxLogDebug(wxString(wxT("accNavigate for ")) + m_pAccessible->GetWindow()->GetClassInfo()->GetClassName()); + wxLogTrace(wxT("access"), wxString(wxT("accNavigate for ")) + m_pAccessible->GetWindow()->GetClassInfo()->GetClassName()); if ((varStart.vt != VT_I4 && varStart.vt != VT_EMPTY) || varStart.vt < 0) { - wxLogDebug("Invalid arg for accNavigate"); + wxLogTrace(wxT("access"), "Invalid arg for accNavigate"); return E_INVALIDARG; } @@ -529,79 +543,88 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT break; default: { - wxLogDebug(wxT("Unknown NAVDIR symbol")); + wxLogTrace(wxT("access"), wxT("Unknown NAVDIR symbol")); break; } } - wxLogDebug(navStr); + wxLogTrace(wxT("access"), navStr); wxAccStatus status = m_pAccessible->Navigate(navDirWX, varStart.lVal, & elementId, & elementObject); if (status == wxACC_FAIL) { - wxLogDebug("wxAccessible::Navigate failed"); + wxLogTrace(wxT("access"), "wxAccessible::Navigate failed"); return E_FAIL; } if (status == wxACC_FALSE) { - wxLogDebug("wxAccessible::Navigate found no object in this direction"); + wxLogTrace(wxT("access"), "wxAccessible::Navigate found no object in this direction"); return S_FALSE; } if (status == wxACC_NOT_IMPLEMENTED) { - wxLogDebug("Navigate not implemented"); + wxLogTrace(wxT("access"), "Navigate not implemented"); - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->accNavigate ( navDir, varStart, pVarEnd); + // Try to use child object directly. + if (varStart.vt == VT_I4 && varStart.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varStart.lVal); + if (childAccessible) + { + varStart.lVal = 0; + HRESULT hResult = childAccessible->accNavigate(navDir, varStart, pVarEnd); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accNavigate(navDir, varStart, pVarEnd); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accNavigate(navDir, varStart, pVarEnd); } else { if (elementObject) { - wxLogDebug("Getting wxIAccessible and calling QueryInterface for Navigate"); + wxLogTrace(wxT("access"), "Getting wxIAccessible and calling QueryInterface for Navigate"); wxIAccessible* objectIA = elementObject->GetIAccessible(); if (!objectIA) { - wxLogDebug("No wxIAccessible"); + wxLogTrace(wxT("access"), "No wxIAccessible"); return E_FAIL; } HRESULT hResult = objectIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarEnd->pdispVal); if (hResult != S_OK) { - wxLogDebug("QueryInterface failed"); + wxLogTrace(wxT("access"), "QueryInterface failed"); return E_FAIL; } - wxLogDebug("Called QueryInterface for Navigate"); + wxLogTrace(wxT("access"), "Called QueryInterface for Navigate"); pVarEnd->vt = VT_DISPATCH; -// pVarEnd->pdispVal->AddRef(); return S_OK; } else if (elementId > 0) { - wxLogDebug("Returning element id from Navigate"); + wxLogTrace(wxT("access"), "Returning element id from Navigate"); pVarEnd->vt = VT_I4; pVarEnd->lVal = elementId; return S_OK; } else { - wxLogDebug("No object in accNavigate"); + wxLogTrace(wxT("access"), "No object in accNavigate"); pVarEnd->vt = VT_EMPTY; return S_FALSE; } } - wxLogDebug("Failing Navigate"); - return E_FAIL; + wxLogTrace(wxT("access"), "Failing Navigate"); + return E_NOTIMPL; } // Retrieves the address of an IDispatch interface for the specified child. @@ -609,14 +632,14 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDispChild) { - wxLogDebug("get_accChild"); + wxLogTrace(wxT("access"), "get_accChild"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varChildID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accChild"); + wxLogTrace(wxT("access"), "Invalid arg for get_accChild"); return E_INVALIDARG; } @@ -632,7 +655,7 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis wxAccStatus status = m_pAccessible->GetChild(varChildID.lVal, & child); if (status == wxACC_FAIL) { - wxLogDebug("GetChild failed"); + wxLogTrace(wxT("access"), "GetChild failed"); return E_FAIL; } @@ -641,10 +664,10 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else { - wxLogDebug("Using standard interface for get_accChild"); + wxLogTrace(wxT("access"), "Using standard interface for get_accChild"); return stdInterface->get_accChild (varChildID, ppDispChild); } } @@ -654,25 +677,24 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis { wxIAccessible* objectIA = child->GetIAccessible(); if (!objectIA) - return E_FAIL; + return E_NOTIMPL; if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) ppDispChild) != S_OK) { - wxLogDebug("QueryInterface failed in get_accChild"); + wxLogTrace(wxT("access"), "QueryInterface failed in get_accChild"); return E_FAIL; } -// (*ppDispChild)->AddRef(); return S_OK; } else { - wxLogDebug("Not an accessible object"); + wxLogTrace(wxT("access"), "Not an accessible object"); return S_FALSE; // Indicates it's not an accessible object } } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the number of children that belong to this object. @@ -680,7 +702,7 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren) { - wxLogDebug("get_accChildCount"); + wxLogTrace(wxT("access"), "get_accChildCount"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; @@ -695,14 +717,14 @@ STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren) // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else { - wxLogDebug("Using standard interface for get_accChildCount"); + wxLogTrace(wxT("access"), "Using standard interface for get_accChildCount"); HRESULT res = stdInterface->get_accChildCount (pCountChildren); wxString str; str.Printf(wxT("Number of children was %d"), (int) (*pCountChildren)); - wxLogDebug(str); + wxLogTrace(wxT("access"), str); return res; } } @@ -712,7 +734,7 @@ STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren) return S_OK; } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the IDispatch interface of the object's parent. @@ -720,7 +742,7 @@ STDMETHODIMP wxIAccessible::get_accChildCount ( long* pCountChildren) STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) { - wxLogDebug("get_accParent"); + wxLogTrace(wxT("access"), "get_accParent"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; @@ -736,11 +758,11 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) // it to the standard interface. if (status == wxACC_NOT_IMPLEMENTED || !parent) { - wxLogDebug("Using standard interface to get the parent."); + wxLogTrace(wxT("access"), "Using standard interface to get the parent."); // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else return stdInterface->get_accParent (ppDispParent); } @@ -752,36 +774,27 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) if (!objectIA) return E_FAIL; - wxLogDebug("About to call QueryInterface"); + wxLogTrace(wxT("access"), "About to call QueryInterface"); if (objectIA->QueryInterface(IID_IDispatch, (LPVOID*) ppDispParent) != S_OK) { - wxLogDebug("Failed QueryInterface"); + wxLogTrace(wxT("access"), "Failed QueryInterface"); return E_FAIL; } -// (*ppDispParent)->AddRef(); - wxLogDebug("Returning S_OK for get_accParent"); + wxLogTrace(wxT("access"), "Returning S_OK for get_accParent"); return S_OK; -/* - wxIAccessible* objectIA = parent->GetIAccessible(); - if (!objectIA) - return E_FAIL; - objectIA->AddRef(); - *ppDispParent = objectIA; - return S_OK; -*/ } else { // This doesn't seem to be allowed, despite the documentation, // so we handle it higher up by using the standard interface. - wxLogDebug("Returning NULL parent because there was none"); + wxLogTrace(wxT("access"), "Returning NULL parent because there was none"); *ppDispParent = NULL; return S_FALSE; } } - return E_FAIL; + return E_NOTIMPL; } // Performs the object's default action. Not all objects have a default @@ -789,14 +802,14 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) STDMETHODIMP wxIAccessible::accDoDefaultAction(VARIANT varID) { - wxLogDebug("accDoDefaultAction"); + wxLogTrace(wxT("access"), "accDoDefaultAction"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for accDoDefaultAction"); + wxLogTrace(wxT("access"), "Invalid arg for accDoDefaultAction"); return E_INVALIDARG; } @@ -809,12 +822,22 @@ STDMETHODIMP wxIAccessible::accDoDefaultAction(VARIANT varID) if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->accDoDefaultAction(varID); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->accDoDefaultAction(varID); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accDoDefaultAction(varID); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accDoDefaultAction(varID); } return E_FAIL; } @@ -824,14 +847,14 @@ STDMETHODIMP wxIAccessible::accDoDefaultAction(VARIANT varID) STDMETHODIMP wxIAccessible::get_accDefaultAction ( VARIANT varID, BSTR* pszDefaultAction) { - wxLogDebug("get_accDefaultAction"); + wxLogTrace(wxT("access"), "get_accDefaultAction"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accDefaultAction"); + wxLogTrace(wxT("access"), "Invalid arg for get_accDefaultAction"); return E_INVALIDARG; } @@ -845,12 +868,22 @@ STDMETHODIMP wxIAccessible::get_accDefaultAction ( VARIANT varID, BSTR* pszDefau if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accDefaultAction (varID, pszDefaultAction); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accDefaultAction(varID, pszDefaultAction); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDefaultAction(varID, pszDefaultAction); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDefaultAction(varID, pszDefaultAction); } else { @@ -874,14 +907,14 @@ STDMETHODIMP wxIAccessible::get_accDefaultAction ( VARIANT varID, BSTR* pszDefau STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescription) { - wxLogDebug("get_accDescription"); + wxLogTrace(wxT("access"), "get_accDescription"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accDescription"); + wxLogTrace(wxT("access"), "Invalid arg for get_accDescription"); return E_INVALIDARG; } @@ -892,12 +925,22 @@ STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescrip if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accDescription (varID, pszDescription); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accDescription(varID, pszDescription); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDescription(varID, pszDescription); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accDescription(varID, pszDescription); } else { @@ -913,7 +956,7 @@ STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescrip return S_OK; } } - return E_FAIL; + return E_NOTIMPL; } // Retrieves an object's Help property string. @@ -921,14 +964,14 @@ STDMETHODIMP wxIAccessible::get_accDescription ( VARIANT varID, BSTR* pszDescrip STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp) { - wxLogDebug("get_accHelp"); + wxLogTrace(wxT("access"), "get_accHelp"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accHelp"); + wxLogTrace(wxT("access"), "Invalid arg for get_accHelp"); return E_INVALIDARG; } @@ -939,12 +982,22 @@ STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp) if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accHelp (varID, pszHelp); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accHelp(varID, pszHelp); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelp(varID, pszHelp); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelp (varID, pszHelp); } else { @@ -960,7 +1013,7 @@ STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp) return S_OK; } } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the full path of the WinHelp file associated with the specified @@ -971,14 +1024,14 @@ STDMETHODIMP wxIAccessible::get_accHelp ( VARIANT varID, BSTR* pszHelp) STDMETHODIMP wxIAccessible::get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChild, long* pidTopic) { - wxLogDebug("get_accHelpTopic"); + wxLogTrace(wxT("access"), "get_accHelpTopic"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varChild.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accHelpTopic"); + wxLogTrace(wxT("access"), "Invalid arg for get_accHelpTopic"); return E_INVALIDARG; } @@ -988,14 +1041,24 @@ STDMETHODIMP wxIAccessible::get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChi if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accHelpTopic (pszHelpFile, varChild, pidTopic); + // Try to use child object directly. + if (varChild.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varChild.lVal); + if (childAccessible) + { + varChild.lVal = 0; + HRESULT hResult = childAccessible->get_accHelpTopic(pszHelpFile, varChild, pidTopic); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelpTopic(pszHelpFile, varChild, pidTopic); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accHelpTopic (pszHelpFile, varChild, pidTopic); } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the specified object's shortcut key or access key, also known as @@ -1004,7 +1067,7 @@ STDMETHODIMP wxIAccessible::get_accHelpTopic ( BSTR* pszHelpFile, VARIANT varChi STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKeyboardShortcut) { - wxLogDebug("get_accKeyboardShortcut"); + wxLogTrace(wxT("access"), "get_accKeyboardShortcut"); *pszKeyboardShortcut = NULL; wxASSERT (m_pAccessible != NULL); @@ -1013,23 +1076,33 @@ STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKe if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accKeyboardShortcut"); + wxLogTrace(wxT("access"), "Invalid arg for get_accKeyboardShortcut"); return E_INVALIDARG; } wxString keyboardShortcut; - wxAccStatus status = m_pAccessible->GetHelpText(varID.lVal, & keyboardShortcut); + wxAccStatus status = m_pAccessible->GetKeyboardShortcut(varID.lVal, & keyboardShortcut); if (status == wxACC_FAIL) return E_FAIL; if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accKeyboardShortcut(varID, pszKeyboardShortcut); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accKeyboardShortcut(varID, pszKeyboardShortcut); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accKeyboardShortcut(varID, pszKeyboardShortcut); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accKeyboardShortcut (varID, pszKeyboardShortcut); } else { @@ -1045,7 +1118,7 @@ STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKe return S_OK; } } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the name of the specified object. @@ -1053,7 +1126,7 @@ STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKe STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName) { - wxLogDebug("get_accName"); + wxLogTrace(wxT("access"), "get_accName"); *pszName = NULL; wxASSERT (m_pAccessible != NULL); @@ -1062,7 +1135,7 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName) if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accName"); + wxLogTrace(wxT("access"), "Invalid arg for get_accName"); return E_INVALIDARG; } @@ -1075,25 +1148,22 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName) if (status == wxACC_NOT_IMPLEMENTED) { -#if 0 - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accName (varID, pszName); -#endif - // Turn child reference into object reference. - IAccessible* stdInterface = GetChildStdAccessible(varID.lVal); - if (stdInterface) + // Try to use child object directly. + if (varID.lVal > 0) { - varID.lVal = 0; - HRESULT hResult = stdInterface->get_accName(varID, pszName); - stdInterface->Release(); - return hResult; + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accName(varID, pszName); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accName(varID, pszName); } - else - return E_FAIL; + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accName (varID, pszName); } else { @@ -1101,7 +1171,7 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName) *pszName = basicString.Get(); return S_OK; } - return E_FAIL; + return E_NOTIMPL; } // Retrieves information that describes the role of the specified object. @@ -1109,14 +1179,14 @@ STDMETHODIMP wxIAccessible::get_accName ( VARIANT varID, BSTR* pszName) STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole) { - wxLogDebug("get_accRole"); + wxLogTrace(wxT("access"), "get_accRole"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accRole"); + wxLogTrace(wxT("access"), "Invalid arg for get_accRole"); return E_INVALIDARG; } @@ -1131,12 +1201,22 @@ STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole) if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accRole (varID, pVarRole); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accRole(varID, pVarRole); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accRole(varID, pVarRole); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accRole (varID, pVarRole); } else { @@ -1151,7 +1231,7 @@ STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole) return S_OK; } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the current state of the specified object. @@ -1159,14 +1239,14 @@ STDMETHODIMP wxIAccessible::get_accRole ( VARIANT varID, VARIANT* pVarRole) STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState) { - wxLogDebug("get_accState"); + wxLogTrace(wxT("access"), "get_accState"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; - if (varID.vt != VT_I4) + if (varID.vt != VT_I4 && varID.vt != VT_EMPTY) { - wxLogDebug("Invalid arg for get_accState"); + wxLogTrace(wxT("access"), "Invalid arg for get_accState"); return E_INVALIDARG; } @@ -1178,12 +1258,22 @@ STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState) if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accState (varID, pVarState); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accState(varID, pVarState); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accState(varID, pVarState); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accState (varID, pVarState); } else { @@ -1192,7 +1282,7 @@ STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState) pVarState->vt = VT_I4; return S_OK; } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the value of the specified object. @@ -1200,14 +1290,14 @@ STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState) STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue) { - wxLogDebug("get_accValue"); + wxLogTrace(wxT("access"), "get_accValue"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4) { - wxLogDebug("Invalid arg for get_accValue"); + wxLogTrace(wxT("access"), "Invalid arg for get_accValue"); return E_INVALIDARG; } @@ -1220,12 +1310,22 @@ STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue) if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->get_accValue (varID, pszValue); + // Try to use child object directly. + if (varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->get_accValue(varID, pszValue); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accValue(varID, pszValue); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->get_accValue (varID, pszValue); } else { @@ -1233,7 +1333,7 @@ STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue) * pszValue = basicString.Get(); return S_OK; } - return E_FAIL; + return E_NOTIMPL; } // Modifies the selection or moves the keyboard focus of the @@ -1242,14 +1342,14 @@ STDMETHODIMP wxIAccessible::get_accValue ( VARIANT varID, BSTR* pszValue) STDMETHODIMP wxIAccessible::accSelect ( long flagsSelect, VARIANT varID ) { - wxLogDebug("get_accSelect"); + wxLogTrace(wxT("access"), "get_accSelect"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; if (varID.vt != VT_I4 && varID.vt != VT_EMPTY) { - wxLogDebug("Invalid arg for accSelect"); + wxLogTrace(wxT("access"), "Invalid arg for accSelect"); return E_INVALIDARG; } @@ -1261,17 +1361,27 @@ STDMETHODIMP wxIAccessible::accSelect ( long flagsSelect, VARIANT varID ) if (status == wxACC_NOT_IMPLEMENTED) { - // Use standard interface instead. - IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); - if (!stdInterface) - return E_FAIL; - else - return stdInterface->accSelect ( flagsSelect, varID ); + // Try to use child object directly. + if (varID.lVal > 0 && varID.lVal > 0) + { + IAccessible* childAccessible = GetChildAccessible(varID.lVal); + if (childAccessible) + { + varID.lVal = 0; + HRESULT hResult = childAccessible->accSelect(flagsSelect, varID); + childAccessible->Release(); + return hResult; + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accSelect(flagsSelect, varID); + } + else if (m_pAccessible->GetIAccessibleStd()) + return ((IAccessible*) m_pAccessible->GetIAccessibleStd())->accSelect(flagsSelect, varID); } else return S_OK; - return E_FAIL; + return E_NOTIMPL; } // Retrieves the object that has the keyboard focus. All objects @@ -1279,7 +1389,7 @@ STDMETHODIMP wxIAccessible::accSelect ( long flagsSelect, VARIANT varID ) STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID) { - wxLogDebug("get_accFocus"); + wxLogTrace(wxT("access"), "get_accFocus"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; @@ -1297,7 +1407,7 @@ STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID) // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else return stdInterface->get_accFocus (pVarID); } @@ -1312,13 +1422,12 @@ STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID) { wxIAccessible* childIA = childObject->GetIAccessible(); if (!childIA) - return E_FAIL; + return E_NOTIMPL; if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarID->pdispVal) != S_OK) return E_FAIL; pVarID->vt = VT_DISPATCH; -// pVarID->pdispVal->AddRef(); return S_OK; } } @@ -1334,7 +1443,7 @@ STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID) return S_FALSE; } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the selected children of this object. All objects @@ -1342,7 +1451,7 @@ STDMETHODIMP wxIAccessible::get_accFocus ( VARIANT* pVarID) STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren) { - wxLogDebug("get_accSelection"); + wxLogTrace(wxT("access"), "get_accSelection"); wxASSERT (m_pAccessible != NULL); if (!m_pAccessible) return E_FAIL; @@ -1359,7 +1468,7 @@ STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren) // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else return stdInterface->get_accSelection (pVarChildren); } @@ -1377,13 +1486,12 @@ STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren) wxAccessible* childObject = (wxAccessible*) selections.GetVoidPtr(); wxIAccessible* childIA = childObject->GetIAccessible(); if (!childIA) - return E_FAIL; + return E_NOTIMPL; if (childIA->QueryInterface(IID_IDispatch, (LPVOID*) & pVarChildren->pdispVal) != S_OK) return E_FAIL; pVarChildren->vt = VT_DISPATCH; -// pVarChildren->pdispVal->AddRef(); return S_OK; } @@ -1401,7 +1509,7 @@ STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren) } } - return E_FAIL; + return E_NOTIMPL; } // Get type info @@ -1438,7 +1546,7 @@ STDMETHODIMP wxIAccessible::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, return E_NOTIMPL; } -// Gets the IAccessible interface for the given child or object. +// Gets the standard IAccessible interface for the given child or object. // Call Release if this is non-NULL. IAccessible* wxIAccessible::GetChildStdAccessible(int id) { @@ -1516,6 +1624,40 @@ IAccessible* wxIAccessible::GetChildStdAccessible(int id) return NULL; } +// Gets the IAccessible interface for the given child or object. +// Call Release if this is non-NULL. +IAccessible* wxIAccessible::GetChildAccessible(int id) +{ + if (id == 0) + { + IAccessible* obj = this; + + obj->AddRef(); + return obj; + } + else + { + VARIANT var; + VariantInit(& var); + var.vt = VT_I4; + var.lVal = id; + IDispatch* pDispatch = NULL; + if (S_OK == get_accChild ( var, & pDispatch)) + { + IAccessible* childAccessible = NULL; + if (pDispatch->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK) + { + pDispatch->Release(); + return childAccessible; + } + else + { + pDispatch->Release(); + } + } + } + return NULL; +} // ---------------------------------------------------------------------------- // wxAccessible implementation @@ -1552,13 +1694,8 @@ void* wxAccessible::GetIAccessibleStd() if (GetWindow()) { -#if 0 - HRESULT retCode = ::CreateStdAccessibleProxy((HWND) GetWindow()->GetHWND(), - wxT("wxWindowClass"), OBJID_CLIENT, IID_IAccessible, (void**) & m_pIAccessibleStd); -#else HRESULT retCode = ::CreateStdAccessibleObject((HWND) GetWindow()->GetHWND(), OBJID_CLIENT, IID_IAccessible, (void**) & m_pIAccessibleStd); -#endif if (retCode == S_OK) return m_pIAccessibleStd; else @@ -1570,6 +1707,14 @@ void* wxAccessible::GetIAccessibleStd() return NULL; } +// Sends an event when something changes in an accessible object. +void wxAccessible::NotifyEvent(int eventType, wxWindow* window, wxAccObject objectType, + int objectId) +{ + ::NotifyWinEvent((DWORD) eventType, (HWND) window->GetHWND(), + (LONG) objectType, (LONG) objectId); +} + // Utilities // Convert to Windows role