X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ae23a52a16b11c47e8ffdac93fb61de1cda4cedc..9dff85155625b6cc35b719b6460a28f977dccb4c:/samples/access/accesstest.cpp diff --git a/samples/access/accesstest.cpp b/samples/access/accesstest.cpp index 9c21331683..4fcfa8cf7a 100644 --- a/samples/access/accesstest.cpp +++ b/samples/access/accesstest.cpp @@ -31,6 +31,21 @@ #endif #include "wx/access.h" +#include "wx/splitter.h" + +#ifdef __WXMSW__ +#include "windows.h" +#include +#include +#include +#include "wx/msw/ole/oleutils.h" +#include "wx/msw/winundef.h" + +#ifndef OBJID_CLIENT +#define OBJID_CLIENT 0xFFFFFFFC +#endif + +#endif // ---------------------------------------------------------------------------- // resources @@ -56,6 +71,7 @@ public: // 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 @@ -68,9 +84,20 @@ public: // 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() }; @@ -85,6 +112,9 @@ enum // 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) @@ -100,6 +130,7 @@ enum // 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() @@ -181,7 +212,9 @@ public: 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)); @@ -194,6 +227,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, 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... @@ -205,19 +240,35 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, 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 } @@ -237,3 +288,199 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) 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"); + } +}