]> git.saurik.com Git - wxWidgets.git/blob - samples/access/accesstest.cpp
0d7ee018ca5d11eedbf2ce605468f280dbab161e
[wxWidgets.git] / samples / access / accesstest.cpp
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"
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
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
64 class MyApp : public wxApp
65 {
66 public:
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();
74
75 };
76
77 // Define a new frame type: this is going to be our main frame
78 class MyFrame : public wxFrame
79 {
80 public:
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);
87 void OnQuery(wxCommandEvent& event);
88 void OnAbout(wxCommandEvent& event);
89
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
96 private:
97 wxTextCtrl* m_textCtrl;
98
99 // any class wishing to process wxWindows events must use this macro
100 DECLARE_EVENT_TABLE()
101 };
102
103 // ----------------------------------------------------------------------------
104 // constants
105 // ----------------------------------------------------------------------------
106
107 // IDs for the controls and the menu commands
108 enum
109 {
110 // menu items
111 AccessTest_Quit = 1,
112
113 // query the hierarchy
114 AccessTest_Query,
115
116 // it is important for the id corresponding to the "About" command to have
117 // this standard value as otherwise it won't be handled properly under Mac
118 // (where it is special and put into the "Apple" menu)
119 AccessTest_About = wxID_ABOUT
120 };
121
122 // ----------------------------------------------------------------------------
123 // event tables and other macros for wxWindows
124 // ----------------------------------------------------------------------------
125
126 // the event tables connect the wxWindows events with the functions (event
127 // handlers) which process them. It can be also done at run-time, but for the
128 // simple menu events like this the static method is much simpler.
129 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
130 EVT_MENU(AccessTest_Quit, MyFrame::OnQuit)
131 EVT_MENU(AccessTest_Query, MyFrame::OnQuery)
132 EVT_MENU(AccessTest_About, MyFrame::OnAbout)
133 END_EVENT_TABLE()
134
135 // Create a new application object: this macro will allow wxWindows to create
136 // the application object during program execution (it's better than using a
137 // static object for many reasons) and also declares the accessor function
138 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
139 // not wxApp)
140 IMPLEMENT_APP(MyApp)
141
142 // ============================================================================
143 // implementation
144 // ============================================================================
145
146 // ----------------------------------------------------------------------------
147 // the application class
148 // ----------------------------------------------------------------------------
149
150 // 'Main program' equivalent: the program execution "starts" here
151 bool MyApp::OnInit()
152 {
153 // create the main application window
154 MyFrame *frame = new MyFrame(_T("AccessTest wxWindows App"),
155 wxPoint(50, 50), wxSize(450, 340));
156
157 // and show it (the frames, unlike simple controls, are not shown when
158 // created initially)
159 frame->Show(TRUE);
160
161 // success: wxApp::OnRun() will be called which will enter the main message
162 // loop and the application will run. If we returned FALSE here, the
163 // application would exit immediately.
164 return TRUE;
165 }
166
167 class FrameAccessible: public wxWindowAccessible
168 {
169 public:
170 FrameAccessible(wxWindow* win): wxWindowAccessible(win) {}
171
172 // Gets the name of the specified object.
173 virtual wxAccStatus GetName(int childId, wxString* name)
174 {
175 #if 1
176 if (childId == wxACC_SELF)
177 {
178 * name = wxT("Julian's Frame");
179 return wxACC_OK;
180 }
181 else
182 #endif
183 return wxACC_NOT_IMPLEMENTED;
184 }
185 };
186
187 class ScrolledWindowAccessible: public wxWindowAccessible
188 {
189 public:
190 ScrolledWindowAccessible(wxWindow* win): wxWindowAccessible(win) {}
191
192 // Gets the name of the specified object.
193 virtual wxAccStatus GetName(int childId, wxString* name)
194 {
195 if (childId == wxACC_SELF)
196 {
197 * name = wxT("My scrolled window");
198 return wxACC_OK;
199 }
200 else
201 return wxACC_NOT_IMPLEMENTED;
202 }
203 };
204
205 // ----------------------------------------------------------------------------
206 // main frame
207 // ----------------------------------------------------------------------------
208
209 // frame constructor
210 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
211 : wxFrame(NULL, -1, title, pos, size, style)
212 {
213 m_textCtrl = NULL;
214
215 SetAccessible(new FrameAccessible(this));
216
217 // set the frame icon
218 SetIcon(wxICON(mondrian));
219
220 #if wxUSE_MENUS
221 // create a menu bar
222 wxMenu *menuFile = new wxMenu;
223
224 // the "About" item should be in the help menu
225 wxMenu *helpMenu = new wxMenu;
226 helpMenu->Append(AccessTest_About, _T("&About...\tF1"), _T("Show about dialog"));
227
228 menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
229 menuFile->AppendSeparator();
230 menuFile->Append(AccessTest_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
231
232 // now append the freshly created menu to the menu bar...
233 wxMenuBar *menuBar = new wxMenuBar();
234 menuBar->Append(menuFile, _T("&File"));
235 menuBar->Append(helpMenu, _T("&Help"));
236
237 // ... and attach this menu bar to the frame
238 SetMenuBar(menuBar);
239 #endif // wxUSE_MENUS
240
241 #if 1 // wxUSE_STATUSBAR
242 // create a status bar just for fun (by default with 1 pane only)
243 CreateStatusBar(2);
244 SetStatusText(_T("Welcome to wxWindows!"));
245 #endif // wxUSE_STATUSBAR
246
247 wxSplitterWindow* splitter = new wxSplitterWindow(this, -1);
248 splitter->CreateAccessible();
249
250 wxListBox* listBox = new wxListBox(splitter, -1);
251 listBox->CreateAccessible();
252
253 m_textCtrl = new wxTextCtrl(splitter, -1, wxT(""), wxDefaultPosition,
254 wxDefaultSize, wxTE_MULTILINE);
255 m_textCtrl->CreateAccessible();
256
257 splitter->SplitHorizontally(listBox, m_textCtrl, 150);
258
259 #if 0
260 #if 1
261 wxListBox* listBox = new wxListBox(this, -1);
262 //listBox->SetAccessible(new wxAccessible(listBox));
263 #else
264 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, -1);
265 scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
266 #endif
267 #endif
268 }
269
270
271 // event handlers
272
273 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
274 {
275 // TRUE is to force the frame to close
276 Close(TRUE);
277 }
278
279 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
280 {
281 wxString msg;
282 msg.Printf( _T("This is the About dialog of the AccessTest sample.\n")
283 _T("Welcome to %s"), wxVERSION_STRING);
284
285 wxMessageBox(msg, _T("About AccessTest"), wxOK | wxICON_INFORMATION, this);
286 }
287
288 void MyFrame::OnQuery(wxCommandEvent& WXUNUSED(event))
289 {
290 m_textCtrl->Clear();
291 IAccessible* accessibleFrame = NULL;
292 if (S_OK != AccessibleObjectFromWindow((HWND) GetHWND(), OBJID_CLIENT,
293 IID_IAccessible, (void**) & accessibleFrame))
294 {
295 Log(wxT("Could not get object."));
296 return;
297 }
298 if (accessibleFrame)
299 {
300 Log(wxT("Got an IAccessible for the frame."));
301 LogObject(0, accessibleFrame);
302 accessibleFrame->Release();
303 }
304 }
305
306 // Log messages to the text control
307 void MyFrame::Log(const wxString& text)
308 {
309 if (m_textCtrl)
310 {
311 wxString text2(text);
312 text2.Replace(wxT("\n"), wxT(" "));
313 text2.Replace(wxT("\r"), wxT(" "));
314 m_textCtrl->SetInsertionPointEnd();
315 m_textCtrl->WriteText(text2 + wxT("\n"));
316 }
317 }
318
319 // Recursively give information about an object
320 void MyFrame::LogObject(int indent, IAccessible* obj)
321 {
322 VARIANT var;
323 VariantInit(& var);
324 var.vt = VT_I4;
325 var.lVal = 0;
326
327 BSTR bStrName = 0;
328 HRESULT hResult = obj->get_accName(var, & bStrName);
329
330 if (hResult == S_OK)
331 {
332 wxString strName(wxConvertStringFromOle(bStrName));
333 SysFreeString(bStrName);
334
335 wxString str;
336 str.Printf(wxT("Name: %s"), strName.c_str());
337 str.Pad(indent, wxT(' '), FALSE);
338 Log(str);
339 }
340 else
341 {
342 wxString str;
343 str.Printf(wxT("NO NAME"));
344 str.Pad(indent, wxT(' '), FALSE);
345 Log(str);
346 }
347
348 VARIANT varRole;
349 VariantInit(& varRole);
350
351 hResult = obj->get_accRole(var, & varRole);
352
353 if (hResult == S_OK && varRole.vt == VT_I4)
354 {
355 wxChar buf[256];
356 GetRoleText(varRole.lVal, buf, 256);
357
358 wxString strRole(buf);
359
360 wxString str;
361 str.Printf(wxT("Role: %s"), strRole.c_str());
362 str.Pad(indent, wxT(' '), FALSE);
363 Log(str);
364 }
365 else
366 {
367 wxString str;
368 str.Printf(wxT("NO ROLE"));
369 str.Pad(indent, wxT(' '), FALSE);
370 Log(str);
371 }
372
373 long childCount = 0;
374 if (S_OK == obj->get_accChildCount(& childCount))
375 {
376 wxString str;
377 str.Printf(wxT("There are %d children."), (int) childCount);
378 str.Pad(indent, wxT(' '), FALSE);
379 Log(str);
380 }
381
382 int i;
383 for (i = 1; i <= childCount; i++)
384 {
385 VARIANT var;
386 VariantInit(& var);
387 var.vt = VT_I4;
388 var.lVal = i;
389 IDispatch* pDisp = NULL;
390 IAccessible* childObject = NULL;
391
392 BSTR bStrName = 0;
393 HRESULT hResult = obj->get_accName(var, & bStrName);
394
395 if (hResult == S_OK)
396 {
397 wxString strName(wxConvertStringFromOle(bStrName));
398 SysFreeString(bStrName);
399
400 wxString str;
401 str.Printf(wxT("Name: %s"), strName.c_str());
402 str.Pad(indent+4, wxT(' '), FALSE);
403 Log(str);
404 }
405 else
406 {
407 wxString str;
408 str.Printf(wxT("NO NAME"));
409 str.Pad(indent+4, wxT(' '), FALSE);
410 Log(str);
411 }
412
413 VARIANT varRole;
414 VariantInit(& varRole);
415
416 hResult = obj->get_accRole(var, & varRole);
417
418 if (hResult == S_OK && varRole.vt == VT_I4)
419 {
420 wxChar buf[256];
421 GetRoleText(varRole.lVal, buf, 256);
422
423 wxString strRole(buf);
424
425 wxString str;
426 str.Printf(wxT("Role: %s"), strRole.c_str());
427 str.Pad(indent+4, wxT(' '), FALSE);
428 Log(str);
429 }
430 else
431 {
432 wxString str;
433 str.Printf(wxT("NO ROLE"));
434 str.Pad(indent+4, wxT(' '), FALSE);
435 Log(str);
436 }
437
438 if (S_OK == obj->get_accChild(var, & pDisp) && pDisp)
439 {
440 wxString str;
441 str.Printf(wxT("This is a real object."));
442 str.Pad(indent+4, wxT(' '), FALSE);
443 Log(str);
444
445 if (pDisp->QueryInterface(IID_IAccessible, (LPVOID*) & childObject) == S_OK)
446 {
447 LogObject(indent + 4, childObject);
448 childObject->Release();
449 }
450 pDisp->Release();
451 }
452 else
453 {
454 wxString str;
455 str.Printf(wxT("This is an element."));
456 str.Pad(indent+4, wxT(' '), FALSE);
457 Log(str);
458 }
459 Log(wxT(""));
460 }
461
462 }
463