#endif
#include "wx/access.h"
+#include "wx/splitter.h"
+
+#ifdef __WXMSW__
+#include "windows.h"
+#include <ole2.h>
+#include <oleauto.h>
+#include <oleacc.h>
+#include "wx/msw/ole/oleutils.h"
+#include "wx/msw/winundef.h"
+
+#ifndef OBJID_CLIENT
+#define OBJID_CLIENT 0xFFFFFFFC
+#endif
+
+#endif
// ----------------------------------------------------------------------------
// resources
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit();
+
};
// Define a new frame type: this is going to be our main frame
// event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
+ void OnQuery(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
+ // Log messages to the text control
+ void Log(const wxString& text);
+
+ // 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;
+
// any class wishing to process wxWindows events must use this macro
DECLARE_EVENT_TABLE()
};
// menu items
AccessTest_Quit = 1,
+ // query the hierarchy
+ AccessTest_Query,
+
// it is important for the id corresponding to the "About" command to have
// this standard value as otherwise it won't be handled properly under Mac
// (where it is special and put into the "Apple" menu)
// simple menu events like this the static method is much simpler.
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(AccessTest_Quit, MyFrame::OnQuit)
+ EVT_MENU(AccessTest_Query, MyFrame::OnQuery)
EVT_MENU(AccessTest_About, MyFrame::OnAbout)
END_EVENT_TABLE()
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
: wxFrame(NULL, -1, title, pos, size, style)
{
- SetAccessible(new FrameAccessible(this));
+ m_textCtrl = NULL;
+
+// SetAccessible(new FrameAccessible(this));
// set the frame icon
SetIcon(wxICON(mondrian));
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(AccessTest_About, _T("&About...\tF1"), _T("Show about dialog"));
+ menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
+ menuFile->AppendSeparator();
menuFile->Append(AccessTest_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
// now append the freshly created menu to the menu bar...
SetMenuBar(menuBar);
#endif // wxUSE_MENUS
-#if 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();
+
+ wxListBox* listBox = new wxListBox(splitter, -1);
+ listBox->CreateAccessible();
+
+ m_textCtrl = new wxTextCtrl(splitter, -1, wxT(""), wxDefaultPosition,
+ wxDefaultSize, wxTE_MULTILINE);
+ m_textCtrl->CreateAccessible();
+
+ splitter->SplitHorizontally(listBox, m_textCtrl, 150);
+#endif
+
+#if 0
#if 1
wxListBox* listBox = new wxListBox(this, -1);
- listBox->SetAccessible(new ScrolledWindowAccessible(listBox));
+ //listBox->SetAccessible(new wxAccessible(listBox));
#else
wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, -1);
scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
#endif
+#endif
}
wxMessageBox(msg, _T("About AccessTest"), wxOK | wxICON_INFORMATION, this);
}
+
+void MyFrame::OnQuery(wxCommandEvent& WXUNUSED(event))
+{
+ m_textCtrl->Clear();
+ IAccessible* accessibleFrame = NULL;
+ if (S_OK != AccessibleObjectFromWindow((HWND) GetHWND(), OBJID_CLIENT,
+ IID_IAccessible, (void**) & accessibleFrame))
+ {
+ Log(wxT("Could not get object."));
+ return;
+ }
+ if (accessibleFrame)
+ {
+ //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();
+ }
+}
+
+// Log messages to the text control
+void MyFrame::Log(const wxString& text)
+{
+ if (m_textCtrl)
+ {
+ wxString text2(text);
+ text2.Replace(wxT("\n"), wxT(" "));
+ text2.Replace(wxT("\r"), wxT(" "));
+ m_textCtrl->SetInsertionPointEnd();
+ m_textCtrl->WriteText(text2 + wxT("\n"));
+ }
+}
+
+// Recursively give information about an object
+void MyFrame::LogObject(int indent, IAccessible* obj)
+{
+ wxString name, role;
+ if (indent == 0)
+ {
+ GetInfo(obj, 0, name, role);
+
+ wxString str;
+ str.Printf(wxT("Name = %s; Role = %s"), name.c_str(), role.c_str());
+ str.Pad(indent, wxT(' '), FALSE);
+ Log(str);
+ }
+
+ long childCount = 0;
+ if (S_OK == obj->get_accChildCount(& childCount))
+ {
+ wxString str;
+ 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;
+ var.lVal = i;
+ IDispatch* pDisp = NULL;
+ IAccessible* childObject = NULL;
+
+ if (S_OK == obj->get_accChild(var, & pDisp) && pDisp)
+ {
+ wxString str;
+ str.Printf(wxT("This is a real object."));
+ str.Pad(indent+4, wxT(' '), FALSE);
+ Log(str);
+
+ if (pDisp->QueryInterface(IID_IAccessible, (LPVOID*) & childObject) == S_OK)
+ {
+ LogObject(indent + 4, childObject);
+ childObject->Release();
+ }
+ pDisp->Release();
+ }
+ else
+ {
+ wxString str;
+ str.Printf(wxT("This is an element."));
+ str.Pad(indent+4, wxT(' '), FALSE);
+ Log(str);
+ }
+ // 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");
+ }
+}