]> git.saurik.com Git - wxWidgets.git/blame - samples/access/accesstest.cpp
Added list of possible slogans for wxWindows stuff
[wxWidgets.git] / samples / access / accesstest.cpp
CommitLineData
ae23a52a
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: accesstest.cpp
3// Purpose: wxWindows accessibility sample
4// Author: Julian Smart
5// Modified by:
6// Created: 2002-02-12
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx/wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27// for all others, include the necessary headers (this file is usually all you
28// need because it includes almost all "standard" wxWindows headers)
29#ifndef WX_PRECOMP
30 #include "wx/wx.h"
31#endif
32
33#include "wx/access.h"
8586126c
JS
34#include "wx/splitter.h"
35
36#ifdef __WXMSW__
37#include "windows.h"
38#include <ole2.h>
39#include <oleauto.h>
40#include <oleacc.h>
41#include "wx/msw/ole/oleutils.h"
42#include "wx/msw/winundef.h"
43
44#ifndef OBJID_CLIENT
45#define OBJID_CLIENT 0xFFFFFFFC
46#endif
47
48#endif
ae23a52a
JS
49
50// ----------------------------------------------------------------------------
51// resources
52// ----------------------------------------------------------------------------
53
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"
57#endif
58
59// ----------------------------------------------------------------------------
60// private classes
61// ----------------------------------------------------------------------------
62
63// Define a new application type, each program should derive a class from wxApp
64class MyApp : public wxApp
65{
66public:
67 // override base class virtuals
68 // ----------------------------
69
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();
8586126c 74
ae23a52a
JS
75};
76
77// Define a new frame type: this is going to be our main frame
78class MyFrame : public wxFrame
79{
80public:
81 // ctor(s)
82 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
83 long style = wxDEFAULT_FRAME_STYLE);
84
85 // event handlers (these functions should _not_ be virtual)
86 void OnQuit(wxCommandEvent& event);
8586126c 87 void OnQuery(wxCommandEvent& event);
ae23a52a
JS
88 void OnAbout(wxCommandEvent& event);
89
8586126c
JS
90 // Log messages to the text control
91 void Log(const wxString& text);
92
93 // Recursively give information about an object
94 void LogObject(int indent, IAccessible* obj);
95
2aefc528
JS
96 // Get info for a child (id > 0) or object (id == 0)
97 void GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role);
ae23a52a 98private:
8586126c
JS
99 wxTextCtrl* m_textCtrl;
100
ae23a52a
JS
101 // any class wishing to process wxWindows events must use this macro
102 DECLARE_EVENT_TABLE()
103};
104
105// ----------------------------------------------------------------------------
106// constants
107// ----------------------------------------------------------------------------
108
109// IDs for the controls and the menu commands
110enum
111{
112 // menu items
113 AccessTest_Quit = 1,
114
8586126c
JS
115 // query the hierarchy
116 AccessTest_Query,
117
ae23a52a
JS
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
122};
123
124// ----------------------------------------------------------------------------
125// event tables and other macros for wxWindows
126// ----------------------------------------------------------------------------
127
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.
131BEGIN_EVENT_TABLE(MyFrame, wxFrame)
132 EVT_MENU(AccessTest_Quit, MyFrame::OnQuit)
8586126c 133 EVT_MENU(AccessTest_Query, MyFrame::OnQuery)
ae23a52a
JS
134 EVT_MENU(AccessTest_About, MyFrame::OnAbout)
135END_EVENT_TABLE()
136
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
141// not wxApp)
142IMPLEMENT_APP(MyApp)
143
144// ============================================================================
145// implementation
146// ============================================================================
147
148// ----------------------------------------------------------------------------
149// the application class
150// ----------------------------------------------------------------------------
151
152// 'Main program' equivalent: the program execution "starts" here
153bool MyApp::OnInit()
154{
155 // create the main application window
156 MyFrame *frame = new MyFrame(_T("AccessTest wxWindows App"),
157 wxPoint(50, 50), wxSize(450, 340));
158
159 // and show it (the frames, unlike simple controls, are not shown when
160 // created initially)
161 frame->Show(TRUE);
162
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.
166 return TRUE;
167}
168
169class FrameAccessible: public wxWindowAccessible
170{
171public:
172 FrameAccessible(wxWindow* win): wxWindowAccessible(win) {}
173
174 // Gets the name of the specified object.
175 virtual wxAccStatus GetName(int childId, wxString* name)
176 {
177#if 1
178 if (childId == wxACC_SELF)
179 {
180 * name = wxT("Julian's Frame");
181 return wxACC_OK;
182 }
183 else
184#endif
185 return wxACC_NOT_IMPLEMENTED;
186 }
187};
188
189class ScrolledWindowAccessible: public wxWindowAccessible
190{
191public:
192 ScrolledWindowAccessible(wxWindow* win): wxWindowAccessible(win) {}
193
194 // Gets the name of the specified object.
195 virtual wxAccStatus GetName(int childId, wxString* name)
196 {
197 if (childId == wxACC_SELF)
198 {
199 * name = wxT("My scrolled window");
200 return wxACC_OK;
201 }
202 else
203 return wxACC_NOT_IMPLEMENTED;
204 }
205};
206
84969af7
JS
207class SplitterWindowAccessible: public wxWindowAccessible
208{
209public:
210 SplitterWindowAccessible(wxWindow* win): wxWindowAccessible(win) {}
211
212 // Gets the name of the specified object.
213 virtual wxAccStatus GetName(int childId, wxString* name)
214 {
215 if (childId == wxACC_SELF)
216 {
217 * name = wxT("Splitter window");
218 return wxACC_OK;
219 }
220 else
221 return wxACC_NOT_IMPLEMENTED;
222 }
223
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; }
228
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; }
232
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; }
237
238 // Gets the number of children.
239 virtual wxAccStatus GetChildCount(int* WXUNUSED(childId))
240 { return wxACC_NOT_IMPLEMENTED; }
241
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; }
248
249 // Gets the parent, or NULL.
250 virtual wxAccStatus GetParent(wxAccessible** WXUNUSED(parent))
251 { return wxACC_NOT_IMPLEMENTED; }
252
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; }
259
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; }
268
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; }
272
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; }
276
277 // Returns the keyboard shortcut for this object or child.
278 // Return e.g. ALT+K
279 virtual wxAccStatus GetKeyboardShortcut(int WXUNUSED(childId), wxString* WXUNUSED(shortcut))
280 { return wxACC_NOT_IMPLEMENTED; }
281
282 // Returns a role constant.
283 virtual wxAccStatus GetRole(int WXUNUSED(childId), wxAccRole* WXUNUSED(role))
284 { return wxACC_NOT_IMPLEMENTED; }
285
286 // Returns a state constant.
287 virtual wxAccStatus GetState(int WXUNUSED(childId), long* WXUNUSED(state))
288 { return wxACC_NOT_IMPLEMENTED; }
289
290 // Returns a localized string representing the value for the object
291 // or child.
292 virtual wxAccStatus GetValue(int WXUNUSED(childId), wxString* WXUNUSED(strValue))
293 { return wxACC_NOT_IMPLEMENTED; }
294
295 // Selects the object or child.
296 virtual wxAccStatus Select(int WXUNUSED(childId), wxAccSelectionFlags WXUNUSED(selectFlags))
297 { return wxACC_NOT_IMPLEMENTED; }
298
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; }
305
306 // Gets a variant representing the selected children
307 // of this object.
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; }
316
317};
318
ae23a52a
JS
319// ----------------------------------------------------------------------------
320// main frame
321// ----------------------------------------------------------------------------
322
323// frame constructor
324MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
325 : wxFrame(NULL, -1, title, pos, size, style)
326{
8586126c
JS
327 m_textCtrl = NULL;
328
2aefc528 329// SetAccessible(new FrameAccessible(this));
ae23a52a
JS
330
331 // set the frame icon
332 SetIcon(wxICON(mondrian));
333
334#if wxUSE_MENUS
335 // create a menu bar
336 wxMenu *menuFile = new wxMenu;
337
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"));
341
8586126c
JS
342 menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
343 menuFile->AppendSeparator();
ae23a52a
JS
344 menuFile->Append(AccessTest_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
345
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"));
350
351 // ... and attach this menu bar to the frame
352 SetMenuBar(menuBar);
353#endif // wxUSE_MENUS
354
2aefc528 355#if 0 // wxUSE_STATUSBAR
ae23a52a
JS
356 // create a status bar just for fun (by default with 1 pane only)
357 CreateStatusBar(2);
358 SetStatusText(_T("Welcome to wxWindows!"));
359#endif // wxUSE_STATUSBAR
360
2aefc528 361#if 1
8586126c
JS
362 wxSplitterWindow* splitter = new wxSplitterWindow(this, -1);
363 splitter->CreateAccessible();
364
365 wxListBox* listBox = new wxListBox(splitter, -1);
366 listBox->CreateAccessible();
367
368 m_textCtrl = new wxTextCtrl(splitter, -1, wxT(""), wxDefaultPosition,
369 wxDefaultSize, wxTE_MULTILINE);
370 m_textCtrl->CreateAccessible();
371
372 splitter->SplitHorizontally(listBox, m_textCtrl, 150);
2aefc528 373#endif
8586126c
JS
374
375#if 0
ae23a52a
JS
376#if 1
377 wxListBox* listBox = new wxListBox(this, -1);
8586126c 378 //listBox->SetAccessible(new wxAccessible(listBox));
ae23a52a
JS
379#else
380 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, -1);
381 scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
382#endif
8586126c 383#endif
ae23a52a
JS
384}
385
386
387// event handlers
388
389void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
390{
391 // TRUE is to force the frame to close
392 Close(TRUE);
393}
394
395void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
396{
397 wxString msg;
398 msg.Printf( _T("This is the About dialog of the AccessTest sample.\n")
399 _T("Welcome to %s"), wxVERSION_STRING);
400
401 wxMessageBox(msg, _T("About AccessTest"), wxOK | wxICON_INFORMATION, this);
402}
8586126c
JS
403
404void MyFrame::OnQuery(wxCommandEvent& WXUNUSED(event))
405{
406 m_textCtrl->Clear();
407 IAccessible* accessibleFrame = NULL;
408 if (S_OK != AccessibleObjectFromWindow((HWND) GetHWND(), OBJID_CLIENT,
409 IID_IAccessible, (void**) & accessibleFrame))
410 {
411 Log(wxT("Could not get object."));
412 return;
413 }
414 if (accessibleFrame)
415 {
2aefc528 416 //Log(wxT("Got an IAccessible for the frame."));
8586126c 417 LogObject(0, accessibleFrame);
2aefc528
JS
418 Log(wxT("Checking children using AccessibleChildren()..."));
419
420 // Now check the AccessibleChildren function works OK
421 long childCount = 0;
422 if (S_OK != accessibleFrame->get_accChildCount(& childCount))
423 {
424 Log(wxT("Could not get number of children."));
425 accessibleFrame->Release();
426 return;
427 }
428 else if (childCount == 0)
429 {
430 Log(wxT("No children."));
431 accessibleFrame->Release();
432 return;
433 }
434
435
436 long obtained = 0;
437 VARIANT *var = new VARIANT[childCount];
438 int i;
439 for (i = 0; i < childCount; i++)
440 {
441 VariantInit(& (var[i]));
442 var[i].vt = VT_DISPATCH;
443 }
444
445 if (S_OK == AccessibleChildren(accessibleFrame, 0, childCount, var, &obtained))
446 {
447 for (i = 0; i < childCount; i++)
448 {
449 IAccessible* childAccessible = NULL;
450 if (var[i].pdispVal)
451 {
452 if (var[i].pdispVal->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
453 {
454 var[i].pdispVal->Release();
455
456 wxString name, role;
457 GetInfo(childAccessible, 0, name, role);
458 wxString str;
459 str.Printf(wxT("Found child %s/%s"), name.c_str(), role.c_str());
460 Log(str);
461 childAccessible->Release();
462 }
463 else
464 {
465 var[i].pdispVal->Release();
466 }
467 }
468 }
469 }
470 else
471 {
472 Log(wxT("AccessibleChildren failed."));
473 }
474 delete[] var;
475
476
8586126c
JS
477 accessibleFrame->Release();
478 }
479}
480
481// Log messages to the text control
482void MyFrame::Log(const wxString& text)
483{
484 if (m_textCtrl)
485 {
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"));
491 }
492}
493
494// Recursively give information about an object
495void MyFrame::LogObject(int indent, IAccessible* obj)
496{
2aefc528
JS
497 wxString name, role;
498 if (indent == 0)
8586126c 499 {
2aefc528
JS
500 GetInfo(obj, 0, name, role);
501
8586126c 502 wxString str;
2aefc528 503 str.Printf(wxT("Name = %s; Role = %s"), name.c_str(), role.c_str());
8586126c
JS
504 str.Pad(indent, wxT(' '), FALSE);
505 Log(str);
506 }
8586126c
JS
507
508 long childCount = 0;
509 if (S_OK == obj->get_accChildCount(& childCount))
510 {
511 wxString str;
512 str.Printf(wxT("There are %d children."), (int) childCount);
513 str.Pad(indent, wxT(' '), FALSE);
514 Log(str);
2aefc528 515 Log(wxT(""));
8586126c
JS
516 }
517
518 int i;
519 for (i = 1; i <= childCount; i++)
520 {
2aefc528
JS
521 GetInfo(obj, i, name, role);
522
523 wxString str;
524 str.Printf(wxT("%d) Name = %s; Role = %s"), i, name.c_str(), role.c_str());
525 str.Pad(indent, wxT(' '), FALSE);
526 Log(str);
527
8586126c
JS
528 VARIANT var;
529 VariantInit(& var);
530 var.vt = VT_I4;
531 var.lVal = i;
532 IDispatch* pDisp = NULL;
533 IAccessible* childObject = NULL;
534
8586126c
JS
535 if (S_OK == obj->get_accChild(var, & pDisp) && pDisp)
536 {
537 wxString str;
538 str.Printf(wxT("This is a real object."));
539 str.Pad(indent+4, wxT(' '), FALSE);
540 Log(str);
541
542 if (pDisp->QueryInterface(IID_IAccessible, (LPVOID*) & childObject) == S_OK)
543 {
544 LogObject(indent + 4, childObject);
545 childObject->Release();
546 }
547 pDisp->Release();
548 }
549 else
550 {
551 wxString str;
552 str.Printf(wxT("This is an element."));
553 str.Pad(indent+4, wxT(' '), FALSE);
554 Log(str);
555 }
2aefc528 556 // Log(wxT(""));
8586126c
JS
557 }
558
559}
560
2aefc528
JS
561// Get info for a child (id > 0) or object (id == 0)
562void MyFrame::GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role)
563{
564 VARIANT var;
565 VariantInit(& var);
566 var.vt = VT_I4;
567 var.lVal = id;
568
569 BSTR bStrName = 0;
570 HRESULT hResult = accessible->get_accName(var, & bStrName);
571
572 if (hResult == S_OK)
573 {
574 name = wxConvertStringFromOle(bStrName);
575 SysFreeString(bStrName);
576 }
577 else
578 {
579 name = wxT("NO NAME");
580 }
581
582 VARIANT varRole;
583 VariantInit(& varRole);
584
585 hResult = accessible->get_accRole(var, & varRole);
586
587 if (hResult == S_OK && varRole.vt == VT_I4)
588 {
589 wxChar buf[256];
590 GetRoleText(varRole.lVal, buf, 256);
591
592 role = buf;
593 }
594 else
595 {
596 role = wxT("NO ROLE");
597 }
598}