From: Julian Smart Date: Wed, 19 Feb 2003 16:31:28 +0000 (+0000) Subject: Further tweaks to accessibility code X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/2aefc52854807189d44dfe6a9513b99932cabc51?ds=sidebyside Further tweaks to accessibility code git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@19256 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/samples/access/accesstest.cpp b/samples/access/accesstest.cpp index 0d7ee018ca..4fcfa8cf7a 100644 --- a/samples/access/accesstest.cpp +++ b/samples/access/accesstest.cpp @@ -93,6 +93,8 @@ public: // Recursively give information about an object void LogObject(int indent, IAccessible* obj); + // Get info for a child (id > 0) or object (id == 0) + void GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role); private: wxTextCtrl* m_textCtrl; @@ -212,7 +214,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, { m_textCtrl = NULL; - SetAccessible(new FrameAccessible(this)); +// SetAccessible(new FrameAccessible(this)); // set the frame icon SetIcon(wxICON(mondrian)); @@ -238,12 +240,13 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, SetMenuBar(menuBar); #endif // wxUSE_MENUS -#if 1 // wxUSE_STATUSBAR +#if 0 // wxUSE_STATUSBAR // create a status bar just for fun (by default with 1 pane only) CreateStatusBar(2); SetStatusText(_T("Welcome to wxWindows!")); #endif // wxUSE_STATUSBAR +#if 1 wxSplitterWindow* splitter = new wxSplitterWindow(this, -1); splitter->CreateAccessible(); @@ -255,6 +258,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, m_textCtrl->CreateAccessible(); splitter->SplitHorizontally(listBox, m_textCtrl, 150); +#endif #if 0 #if 1 @@ -297,8 +301,67 @@ void MyFrame::OnQuery(wxCommandEvent& WXUNUSED(event)) } if (accessibleFrame) { - Log(wxT("Got an IAccessible for the frame.")); + //Log(wxT("Got an IAccessible for the frame.")); LogObject(0, accessibleFrame); + Log(wxT("Checking children using AccessibleChildren()...")); + + // Now check the AccessibleChildren function works OK + long childCount = 0; + if (S_OK != accessibleFrame->get_accChildCount(& childCount)) + { + Log(wxT("Could not get number of children.")); + accessibleFrame->Release(); + return; + } + else if (childCount == 0) + { + Log(wxT("No children.")); + accessibleFrame->Release(); + return; + } + + + long obtained = 0; + VARIANT *var = new VARIANT[childCount]; + int i; + for (i = 0; i < childCount; i++) + { + VariantInit(& (var[i])); + var[i].vt = VT_DISPATCH; + } + + if (S_OK == AccessibleChildren(accessibleFrame, 0, childCount, var, &obtained)) + { + for (i = 0; i < childCount; i++) + { + IAccessible* childAccessible = NULL; + if (var[i].pdispVal) + { + if (var[i].pdispVal->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK) + { + var[i].pdispVal->Release(); + + wxString name, role; + GetInfo(childAccessible, 0, name, role); + wxString str; + str.Printf(wxT("Found child %s/%s"), name.c_str(), role.c_str()); + Log(str); + childAccessible->Release(); + } + else + { + var[i].pdispVal->Release(); + } + } + } + } + else + { + Log(wxT("AccessibleChildren failed.")); + } + delete[] var; + + accessibleFrame->Release(); } } @@ -319,56 +382,16 @@ void MyFrame::Log(const wxString& text) // Recursively give information about an object void MyFrame::LogObject(int indent, IAccessible* obj) { - VARIANT var; - VariantInit(& var); - var.vt = VT_I4; - var.lVal = 0; - - BSTR bStrName = 0; - HRESULT hResult = obj->get_accName(var, & bStrName); - - if (hResult == S_OK) - { - wxString strName(wxConvertStringFromOle(bStrName)); - SysFreeString(bStrName); - - wxString str; - str.Printf(wxT("Name: %s"), strName.c_str()); - str.Pad(indent, wxT(' '), FALSE); - Log(str); - } - else - { - wxString str; - str.Printf(wxT("NO NAME")); - str.Pad(indent, wxT(' '), FALSE); - Log(str); - } - - VARIANT varRole; - VariantInit(& varRole); - - hResult = obj->get_accRole(var, & varRole); - - if (hResult == S_OK && varRole.vt == VT_I4) + wxString name, role; + if (indent == 0) { - wxChar buf[256]; - GetRoleText(varRole.lVal, buf, 256); - - wxString strRole(buf); - + GetInfo(obj, 0, name, role); + wxString str; - str.Printf(wxT("Role: %s"), strRole.c_str()); + str.Printf(wxT("Name = %s; Role = %s"), name.c_str(), role.c_str()); str.Pad(indent, wxT(' '), FALSE); Log(str); } - else - { - wxString str; - str.Printf(wxT("NO ROLE")); - str.Pad(indent, wxT(' '), FALSE); - Log(str); - } long childCount = 0; if (S_OK == obj->get_accChildCount(& childCount)) @@ -377,11 +400,19 @@ void MyFrame::LogObject(int indent, IAccessible* obj) str.Printf(wxT("There are %d children."), (int) childCount); str.Pad(indent, wxT(' '), FALSE); Log(str); + Log(wxT("")); } int i; for (i = 1; i <= childCount; i++) { + GetInfo(obj, i, name, role); + + wxString str; + str.Printf(wxT("%d) Name = %s; Role = %s"), i, name.c_str(), role.c_str()); + str.Pad(indent, wxT(' '), FALSE); + Log(str); + VARIANT var; VariantInit(& var); var.vt = VT_I4; @@ -389,52 +420,6 @@ void MyFrame::LogObject(int indent, IAccessible* obj) IDispatch* pDisp = NULL; IAccessible* childObject = NULL; - BSTR bStrName = 0; - HRESULT hResult = obj->get_accName(var, & bStrName); - - if (hResult == S_OK) - { - wxString strName(wxConvertStringFromOle(bStrName)); - SysFreeString(bStrName); - - wxString str; - str.Printf(wxT("Name: %s"), strName.c_str()); - str.Pad(indent+4, wxT(' '), FALSE); - Log(str); - } - else - { - wxString str; - str.Printf(wxT("NO NAME")); - str.Pad(indent+4, wxT(' '), FALSE); - Log(str); - } - - VARIANT varRole; - VariantInit(& varRole); - - hResult = obj->get_accRole(var, & varRole); - - if (hResult == S_OK && varRole.vt == VT_I4) - { - wxChar buf[256]; - GetRoleText(varRole.lVal, buf, 256); - - wxString strRole(buf); - - wxString str; - str.Printf(wxT("Role: %s"), strRole.c_str()); - str.Pad(indent+4, wxT(' '), FALSE); - Log(str); - } - else - { - wxString str; - str.Printf(wxT("NO ROLE")); - str.Pad(indent+4, wxT(' '), FALSE); - Log(str); - } - if (S_OK == obj->get_accChild(var, & pDisp) && pDisp) { wxString str; @@ -456,8 +441,46 @@ void MyFrame::LogObject(int indent, IAccessible* obj) str.Pad(indent+4, wxT(' '), FALSE); Log(str); } - Log(wxT("")); + // Log(wxT("")); } } +// Get info for a child (id > 0) or object (id == 0) +void MyFrame::GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role) +{ + VARIANT var; + VariantInit(& var); + var.vt = VT_I4; + var.lVal = id; + + BSTR bStrName = 0; + HRESULT hResult = accessible->get_accName(var, & bStrName); + + if (hResult == S_OK) + { + name = wxConvertStringFromOle(bStrName); + SysFreeString(bStrName); + } + else + { + name = wxT("NO NAME"); + } + + VARIANT varRole; + VariantInit(& varRole); + + hResult = accessible->get_accRole(var, & varRole); + + if (hResult == S_OK && varRole.vt == VT_I4) + { + wxChar buf[256]; + GetRoleText(varRole.lVal, buf, 256); + + role = buf; + } + else + { + role = wxT("NO ROLE"); + } +} diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 4b96081219..2d41293237 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -1959,7 +1959,7 @@ void wxWindowBase::OnMiddleClick( wxMouseEvent& event ) #if wxUSE_ACCESSIBILITY void wxWindowBase::SetAccessible(wxAccessible* accessible) { - if (m_accessible) + if (m_accessible && (accessible != m_accessible)) delete m_accessible; m_accessible = accessible; if (m_accessible) @@ -2251,7 +2251,21 @@ wxAccStatus wxWindowAccessible::GetName(int childId, wxString* name) if (!GetWindow()) return wxACC_FAIL; - wxString title(GetWindow()->GetTitle()); + wxString title; + + // If a child, leave wxWindows to call the function on the actual + // child object. + if (childId > 0) + return wxACC_NOT_IMPLEMENTED; + + // This will eventually be replaced by specialised + // accessible classes, one for each kind of wxWindows + // control or window. + if (GetWindow()->IsKindOf(CLASSINFO(wxButton))) + title = ((wxButton*) GetWindow())->GetLabel(); + else + title = GetWindow()->GetName(); + if (!title.IsEmpty()) { *name = title; @@ -2357,6 +2371,12 @@ wxAccStatus wxWindowAccessible::GetDescription(int childId, wxString* descriptio if (!GetWindow()) return wxACC_FAIL; + wxString ht(GetWindow()->GetHelpText()); + if (!ht.IsEmpty()) + { + *description = ht; + return wxACC_OK; + } return wxACC_NOT_IMPLEMENTED; } @@ -2394,6 +2414,26 @@ wxAccStatus wxWindowAccessible::GetRole(int childId, wxAccRole* role) if (!GetWindow()) return wxACC_FAIL; + // If a child, leave wxWindows to call the function on the actual + // child object. + if (childId > 0) + return wxACC_NOT_IMPLEMENTED; + + if (GetWindow()->IsKindOf(CLASSINFO(wxControl))) + return wxACC_NOT_IMPLEMENTED; +#if wxUSE_STATUSBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar))) + return wxACC_NOT_IMPLEMENTED; +#endif +#if wxUSE_TOOLBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar))) + return wxACC_NOT_IMPLEMENTED; +#endif + + //*role = wxROLE_SYSTEM_CLIENT; + *role = wxROLE_SYSTEM_CLIENT; + return wxACC_OK; + return wxACC_NOT_IMPLEMENTED; } @@ -2404,6 +2444,26 @@ wxAccStatus wxWindowAccessible::GetState(int childId, long* state) if (!GetWindow()) return wxACC_FAIL; + // If a child, leave wxWindows to call the function on the actual + // child object. + if (childId > 0) + return wxACC_NOT_IMPLEMENTED; + + if (GetWindow()->IsKindOf(CLASSINFO(wxControl))) + return wxACC_NOT_IMPLEMENTED; + +#if wxUSE_STATUSBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar))) + return wxACC_NOT_IMPLEMENTED; +#endif +#if wxUSE_TOOLBAR + if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar))) + return wxACC_NOT_IMPLEMENTED; +#endif + + *state = 0; + return wxACC_OK; + return wxACC_NOT_IMPLEMENTED; } diff --git a/src/msw/ole/access.cpp b/src/msw/ole/access.cpp index 834751f4ee..d75b8abc43 100644 --- a/src/msw/ole/access.cpp +++ b/src/msw/ole/access.cpp @@ -332,6 +332,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 @@ -384,7 +388,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 +405,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 +426,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 @@ -444,12 +447,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 +473,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. @@ -554,12 +567,22 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT { wxLogDebug("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 { @@ -582,7 +605,6 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT wxLogDebug("Called QueryInterface for Navigate"); pVarEnd->vt = VT_DISPATCH; -// pVarEnd->pdispVal->AddRef(); return S_OK; } else if (elementId > 0) @@ -601,7 +623,7 @@ STDMETHODIMP wxIAccessible::accNavigate ( long navDir, VARIANT varStart, VARIANT } wxLogDebug("Failing Navigate"); - return E_FAIL; + return E_NOTIMPL; } // Retrieves the address of an IDispatch interface for the specified child. @@ -641,7 +663,7 @@ 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"); @@ -654,7 +676,7 @@ 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) { @@ -662,7 +684,6 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis return E_FAIL; } -// (*ppDispChild)->AddRef(); return S_OK; } else @@ -672,7 +693,7 @@ STDMETHODIMP wxIAccessible::get_accChild ( VARIANT varChildID, IDispatch** ppDis } } - return E_FAIL; + return E_NOTIMPL; } // Retrieves the number of children that belong to this object. @@ -695,7 +716,7 @@ 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"); @@ -712,7 +733,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. @@ -740,7 +761,7 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) // Use standard interface instead. IAccessible* stdInterface = (IAccessible*)m_pAccessible->GetIAccessibleStd(); if (!stdInterface) - return E_FAIL; + return E_NOTIMPL; else return stdInterface->get_accParent (ppDispParent); } @@ -759,17 +780,8 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) return E_FAIL; } -// (*ppDispParent)->AddRef(); wxLogDebug("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 { @@ -781,7 +793,7 @@ STDMETHODIMP wxIAccessible::get_accParent ( IDispatch** ppDispParent) } } - return E_FAIL; + return E_NOTIMPL; } // Performs the object's default action. Not all objects have a default @@ -809,12 +821,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; } @@ -845,12 +867,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 { @@ -892,12 +924,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 +955,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. @@ -939,12 +981,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 +1012,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 @@ -988,14 +1040,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 @@ -1024,12 +1086,22 @@ STDMETHODIMP wxIAccessible::get_accKeyboardShortcut ( VARIANT varID, BSTR* pszKe 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 +1117,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. @@ -1075,25 +1147,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 +1170,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. @@ -1131,12 +1200,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 +1230,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. @@ -1164,7 +1243,7 @@ STDMETHODIMP wxIAccessible::get_accState ( VARIANT varID, VARIANT* pVarState) 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"); return E_INVALIDARG; @@ -1178,12 +1257,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 +1281,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. @@ -1220,12 +1309,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 +1332,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 @@ -1261,17 +1360,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 @@ -1297,7 +1406,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 +1421,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 +1442,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 @@ -1359,7 +1467,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 +1485,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 +1508,7 @@ STDMETHODIMP wxIAccessible::get_accSelection ( VARIANT * pVarChildren) } } - return E_FAIL; + return E_NOTIMPL; } // Get type info @@ -1438,7 +1545,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 +1623,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 +1693,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