]>
git.saurik.com Git - wxWidgets.git/blob - samples/access/accesstest.cpp
285edb016c18b67a8cca4cfe400018ee9f44bb35
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: accesstest.cpp
3 // Purpose: wxWindows accessibility sample
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWindows headers)
33 #include "wx/access.h"
34 #include "wx/splitter.h"
41 #include "wx/msw/ole/oleutils.h"
42 #include "wx/msw/winundef.h"
45 #define OBJID_CLIENT 0xFFFFFFFC
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // the application icon (under Windows and OS/2 it is in resources)
55 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
56 #include "mondrian.xpm"
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 // Define a new application type, each program should derive a class from wxApp
64 class MyApp
: public wxApp
67 // override base class virtuals
68 // ----------------------------
70 // this one is called on application startup and is a good place for the app
71 // initialization (doing it here and not in the ctor allows to have an error
72 // return: if OnInit() returns false, the application terminates)
73 virtual bool OnInit();
77 // Define a new frame type: this is going to be our main frame
78 class MyFrame
: public wxFrame
82 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
,
83 long style
= wxDEFAULT_FRAME_STYLE
);
85 // event handlers (these functions should _not_ be virtual)
86 void OnQuit(wxCommandEvent
& event
);
87 void OnQuery(wxCommandEvent
& event
);
88 void OnAbout(wxCommandEvent
& event
);
90 // Log messages to the text control
91 void Log(const wxString
& text
);
93 // Recursively give information about an object
94 void LogObject(int indent
, IAccessible
* obj
);
96 // Get info for a child (id > 0) or object (id == 0)
97 void GetInfo(IAccessible
* accessible
, int id
, wxString
& name
, wxString
& role
);
99 wxTextCtrl
* m_textCtrl
;
101 // any class wishing to process wxWindows events must use this macro
102 DECLARE_EVENT_TABLE()
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
109 // IDs for the controls and the menu commands
115 // query the hierarchy
118 // it is important for the id corresponding to the "About" command to have
119 // this standard value as otherwise it won't be handled properly under Mac
120 // (where it is special and put into the "Apple" menu)
121 AccessTest_About
= wxID_ABOUT
124 // ----------------------------------------------------------------------------
125 // event tables and other macros for wxWindows
126 // ----------------------------------------------------------------------------
128 // the event tables connect the wxWindows events with the functions (event
129 // handlers) which process them. It can be also done at run-time, but for the
130 // simple menu events like this the static method is much simpler.
131 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
132 EVT_MENU(AccessTest_Quit
, MyFrame::OnQuit
)
133 EVT_MENU(AccessTest_Query
, MyFrame::OnQuery
)
134 EVT_MENU(AccessTest_About
, MyFrame::OnAbout
)
137 // Create a new application object: this macro will allow wxWindows to create
138 // the application object during program execution (it's better than using a
139 // static object for many reasons) and also declares the accessor function
140 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
144 // ============================================================================
146 // ============================================================================
148 // ----------------------------------------------------------------------------
149 // the application class
150 // ----------------------------------------------------------------------------
152 // 'Main program' equivalent: the program execution "starts" here
155 // create the main application window
156 MyFrame
*frame
= new MyFrame(_T("AccessTest wxWindows App"),
157 wxPoint(50, 50), wxSize(450, 340));
159 // and show it (the frames, unlike simple controls, are not shown when
160 // created initially)
163 // success: wxApp::OnRun() will be called which will enter the main message
164 // loop and the application will run. If we returned FALSE here, the
165 // application would exit immediately.
169 class FrameAccessible
: public wxWindowAccessible
172 FrameAccessible(wxWindow
* win
): wxWindowAccessible(win
) {}
174 // Gets the name of the specified object.
175 virtual wxAccStatus
GetName(int childId
, wxString
* name
)
178 if (childId
== wxACC_SELF
)
180 * name
= wxT("Julian's Frame");
185 return wxACC_NOT_IMPLEMENTED
;
189 class ScrolledWindowAccessible
: public wxWindowAccessible
192 ScrolledWindowAccessible(wxWindow
* win
): wxWindowAccessible(win
) {}
194 // Gets the name of the specified object.
195 virtual wxAccStatus
GetName(int childId
, wxString
* name
)
197 if (childId
== wxACC_SELF
)
199 * name
= wxT("My scrolled window");
203 return wxACC_NOT_IMPLEMENTED
;
207 class SplitterWindowAccessible
: public wxWindowAccessible
210 SplitterWindowAccessible(wxWindow
* win
): wxWindowAccessible(win
) {}
212 // Gets the name of the specified object.
213 virtual wxAccStatus
GetName(int childId
, wxString
* name
)
215 if (childId
== wxACC_SELF
)
217 * name
= wxT("Splitter window");
221 return wxACC_NOT_IMPLEMENTED
;
224 // Can return either a child object, or an integer
225 // representing the child element, starting from 1.
226 virtual wxAccStatus
HitTest(const wxPoint
& pt
, int* childId
, wxAccessible
** childObject
)
227 { return wxACC_NOT_IMPLEMENTED
; }
229 // Returns the rectangle for this object (id = 0) or a child element (id > 0).
230 virtual wxAccStatus
GetLocation(wxRect
& WXUNUSED(rect
), int WXUNUSED(elementId
))
231 { return wxACC_NOT_IMPLEMENTED
; }
233 // Navigates from fromId to toId/toObject.
234 virtual wxAccStatus
Navigate(wxNavDir
WXUNUSED(navDir
), int WXUNUSED(fromId
),
235 int* WXUNUSED(toId
), wxAccessible
** WXUNUSED(toObject
))
236 { return wxACC_NOT_IMPLEMENTED
; }
238 // Gets the number of children.
239 virtual wxAccStatus
GetChildCount(int* WXUNUSED(childId
))
240 { return wxACC_NOT_IMPLEMENTED
; }
242 // Gets the specified child (starting from 1).
243 // If *child is NULL and return value is wxACC_OK,
244 // this means that the child is a simple element and
245 // not an accessible object.
246 virtual wxAccStatus
GetChild(int WXUNUSED(childId
), wxAccessible
** WXUNUSED(child
))
247 { return wxACC_NOT_IMPLEMENTED
; }
249 // Gets the parent, or NULL.
250 virtual wxAccStatus
GetParent(wxAccessible
** WXUNUSED(parent
))
251 { return wxACC_NOT_IMPLEMENTED
; }
253 // Performs the default action. childId is 0 (the action for this object)
254 // or > 0 (the action for a child).
255 // Return wxACC_NOT_SUPPORTED if there is no default action for this
256 // window (e.g. an edit control).
257 virtual wxAccStatus
DoDefaultAction(int WXUNUSED(childId
))
258 { return wxACC_NOT_IMPLEMENTED
; }
260 // Gets the default action for this object (0) or > 0 (the action for a child).
261 // Return wxACC_OK even if there is no action. actionName is the action, or the empty
262 // string if there is no action.
263 // The retrieved string describes the action that is performed on an object,
264 // not what the object does as a result. For example, a toolbar button that prints
265 // a document has a default action of "Press" rather than "Prints the current document."
266 virtual wxAccStatus
GetDefaultAction(int WXUNUSED(childId
), wxString
* WXUNUSED(actionName
))
267 { return wxACC_NOT_IMPLEMENTED
; }
269 // Returns the description for this object or a child.
270 virtual wxAccStatus
GetDescription(int WXUNUSED(childId
), wxString
* WXUNUSED(description
))
271 { return wxACC_NOT_IMPLEMENTED
; }
273 // Returns help text for this object or a child, similar to tooltip text.
274 virtual wxAccStatus
GetHelpText(int WXUNUSED(childId
), wxString
* WXUNUSED(helpText
))
275 { return wxACC_NOT_IMPLEMENTED
; }
277 // Returns the keyboard shortcut for this object or child.
279 virtual wxAccStatus
GetKeyboardShortcut(int WXUNUSED(childId
), wxString
* WXUNUSED(shortcut
))
280 { return wxACC_NOT_IMPLEMENTED
; }
282 // Returns a role constant.
283 virtual wxAccStatus
GetRole(int WXUNUSED(childId
), wxAccRole
* WXUNUSED(role
))
284 { return wxACC_NOT_IMPLEMENTED
; }
286 // Returns a state constant.
287 virtual wxAccStatus
GetState(int WXUNUSED(childId
), long* WXUNUSED(state
))
288 { return wxACC_NOT_IMPLEMENTED
; }
290 // Returns a localized string representing the value for the object
292 virtual wxAccStatus
GetValue(int WXUNUSED(childId
), wxString
* WXUNUSED(strValue
))
293 { return wxACC_NOT_IMPLEMENTED
; }
295 // Selects the object or child.
296 virtual wxAccStatus
Select(int WXUNUSED(childId
), wxAccSelectionFlags
WXUNUSED(selectFlags
))
297 { return wxACC_NOT_IMPLEMENTED
; }
299 // Gets the window with the keyboard focus.
300 // If childId is 0 and child is NULL, no object in
301 // this subhierarchy has the focus.
302 // If this object has the focus, child should be 'this'.
303 virtual wxAccStatus
GetFocus(int* WXUNUSED(childId
), wxAccessible
** WXUNUSED(child
))
304 { return wxACC_NOT_IMPLEMENTED
; }
306 // Gets a variant representing the selected children
308 // Acceptable values:
309 // - a null variant (IsNull() returns TRUE)
310 // - a list variant (GetType() == wxT("list"))
311 // - an integer representing the selected child element,
312 // or 0 if this object is selected (GetType() == wxT("long"))
313 // - a "void*" pointer to a wxAccessible child object
314 virtual wxAccStatus
GetSelections(wxVariant
* WXUNUSED(selections
))
315 { return wxACC_NOT_IMPLEMENTED
; }
319 // ----------------------------------------------------------------------------
321 // ----------------------------------------------------------------------------
324 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
, long style
)
325 : wxFrame(NULL
, -1, title
, pos
, size
, style
)
329 // SetAccessible(new FrameAccessible(this));
331 // set the frame icon
332 SetIcon(wxICON(mondrian
));
336 wxMenu
*menuFile
= new wxMenu
;
338 // the "About" item should be in the help menu
339 wxMenu
*helpMenu
= new wxMenu
;
340 helpMenu
->Append(AccessTest_About
, _T("&About...\tF1"), _T("Show about dialog"));
342 menuFile
->Append(AccessTest_Query
, _T("Query"), _T("Query the window hierarchy"));
343 menuFile
->AppendSeparator();
344 menuFile
->Append(AccessTest_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
346 // now append the freshly created menu to the menu bar...
347 wxMenuBar
*menuBar
= new wxMenuBar();
348 menuBar
->Append(menuFile
, _T("&File"));
349 menuBar
->Append(helpMenu
, _T("&Help"));
351 // ... and attach this menu bar to the frame
353 #endif // wxUSE_MENUS
355 #if 0 // wxUSE_STATUSBAR
356 // create a status bar just for fun (by default with 1 pane only)
358 SetStatusText(_T("Welcome to wxWindows!"));
359 #endif // wxUSE_STATUSBAR
362 wxSplitterWindow
* splitter
= new wxSplitterWindow(this, -1);
363 splitter
->CreateAccessible();
365 wxListBox
* listBox
= new wxListBox(splitter
, -1);
366 listBox
->CreateAccessible();
368 m_textCtrl
= new wxTextCtrl(splitter
, -1, wxT(""), wxDefaultPosition
,
369 wxDefaultSize
, wxTE_MULTILINE
);
370 m_textCtrl
->CreateAccessible();
372 splitter
->SplitHorizontally(listBox
, m_textCtrl
, 150);
377 wxListBox
* listBox
= new wxListBox(this, -1);
378 //listBox->SetAccessible(new wxAccessible(listBox));
380 wxScrolledWindow
* scrolledWindow
= new wxScrolledWindow(this, -1);
381 scrolledWindow
->SetAccessible(new ScrolledWindowAccessible(scrolledWindow
));
389 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
391 // TRUE is to force the frame to close
395 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
398 msg
.Printf( _T("This is the About dialog of the AccessTest sample.\n")
399 _T("Welcome to %s"), wxVERSION_STRING
);
401 wxMessageBox(msg
, _T("About AccessTest"), wxOK
| wxICON_INFORMATION
, this);
404 void MyFrame::OnQuery(wxCommandEvent
& WXUNUSED(event
))
407 IAccessible
* accessibleFrame
= NULL
;
408 if (S_OK
!= AccessibleObjectFromWindow((HWND
) GetHWND(), OBJID_CLIENT
,
409 IID_IAccessible
, (void**) & accessibleFrame
))
411 Log(wxT("Could not get object."));
416 //Log(wxT("Got an IAccessible for the frame."));
417 LogObject(0, accessibleFrame
);
418 Log(wxT("Checking children using AccessibleChildren()..."));
420 // Now check the AccessibleChildren function works OK
422 if (S_OK
!= accessibleFrame
->get_accChildCount(& childCount
))
424 Log(wxT("Could not get number of children."));
425 accessibleFrame
->Release();
428 else if (childCount
== 0)
430 Log(wxT("No children."));
431 accessibleFrame
->Release();
437 VARIANT
*var
= new VARIANT
[childCount
];
439 for (i
= 0; i
< childCount
; i
++)
441 VariantInit(& (var
[i
]));
442 var
[i
].vt
= VT_DISPATCH
;
445 if (S_OK
== AccessibleChildren(accessibleFrame
, 0, childCount
, var
, &obtained
))
447 for (i
= 0; i
< childCount
; i
++)
449 IAccessible
* childAccessible
= NULL
;
452 if (var
[i
].pdispVal
->QueryInterface(IID_IAccessible
, (LPVOID
*) & childAccessible
) == S_OK
)
454 var
[i
].pdispVal
->Release();
457 GetInfo(childAccessible
, 0, name
, role
);
459 str
.Printf(wxT("Found child %s/%s"), name
.c_str(), role
.c_str());
461 childAccessible
->Release();
465 var
[i
].pdispVal
->Release();
472 Log(wxT("AccessibleChildren failed."));
477 accessibleFrame
->Release();
481 // Log messages to the text control
482 void MyFrame::Log(const wxString
& text
)
486 wxString
text2(text
);
487 text2
.Replace(wxT("\n"), wxT(" "));
488 text2
.Replace(wxT("\r"), wxT(" "));
489 m_textCtrl
->SetInsertionPointEnd();
490 m_textCtrl
->WriteText(text2
+ wxT("\n"));
494 // Recursively give information about an object
495 void MyFrame::LogObject(int indent
, IAccessible
* obj
)
500 GetInfo(obj
, 0, name
, role
);
503 str
.Printf(wxT("Name = %s; Role = %s"), name
.c_str(), role
.c_str());
504 str
.Pad(indent
, wxT(' '), FALSE
);
509 if (S_OK
== obj
->get_accChildCount(& childCount
))
512 str
.Printf(wxT("There are %d children."), (int) childCount
);
513 str
.Pad(indent
, wxT(' '), FALSE
);
519 for (i
= 1; i
<= childCount
; i
++)
521 GetInfo(obj
, i
, name
, role
);
524 str
.Printf(wxT("%d) Name = %s; Role = %s"), i
, name
.c_str(), role
.c_str());
525 str
.Pad(indent
, wxT(' '), FALSE
);
532 IDispatch
* pDisp
= NULL
;
533 IAccessible
* childObject
= NULL
;
535 if (S_OK
== obj
->get_accChild(var
, & pDisp
) && pDisp
)
538 str
.Printf(wxT("This is a real object."));
539 str
.Pad(indent
+4, wxT(' '), FALSE
);
542 if (pDisp
->QueryInterface(IID_IAccessible
, (LPVOID
*) & childObject
) == S_OK
)
544 LogObject(indent
+ 4, childObject
);
545 childObject
->Release();
552 str
.Printf(wxT("This is an element."));
553 str
.Pad(indent
+4, wxT(' '), FALSE
);
561 // Get info for a child (id > 0) or object (id == 0)
562 void MyFrame::GetInfo(IAccessible
* accessible
, int id
, wxString
& name
, wxString
& role
)
570 HRESULT hResult
= accessible
->get_accName(var
, & bStrName
);
574 name
= wxConvertStringFromOle(bStrName
);
575 SysFreeString(bStrName
);
579 name
= wxT("NO NAME");
583 VariantInit(& varRole
);
585 hResult
= accessible
->get_accRole(var
, & varRole
);
587 if (hResult
== S_OK
&& varRole
.vt
== VT_I4
)
590 GetRoleText(varRole
.lVal
, buf
, 256);
596 role
= wxT("NO ROLE");