]> git.saurik.com Git - wxWidgets.git/blame - samples/access/accesstest.cpp
Applied patch [ 708377 ] Make NET (smapi.cpp) UNICODE compatible
[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
207// ----------------------------------------------------------------------------
208// main frame
209// ----------------------------------------------------------------------------
210
211// frame constructor
212MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
213 : wxFrame(NULL, -1, title, pos, size, style)
214{
8586126c
JS
215 m_textCtrl = NULL;
216
2aefc528 217// SetAccessible(new FrameAccessible(this));
ae23a52a
JS
218
219 // set the frame icon
220 SetIcon(wxICON(mondrian));
221
222#if wxUSE_MENUS
223 // create a menu bar
224 wxMenu *menuFile = new wxMenu;
225
226 // the "About" item should be in the help menu
227 wxMenu *helpMenu = new wxMenu;
228 helpMenu->Append(AccessTest_About, _T("&About...\tF1"), _T("Show about dialog"));
229
8586126c
JS
230 menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
231 menuFile->AppendSeparator();
ae23a52a
JS
232 menuFile->Append(AccessTest_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
233
234 // now append the freshly created menu to the menu bar...
235 wxMenuBar *menuBar = new wxMenuBar();
236 menuBar->Append(menuFile, _T("&File"));
237 menuBar->Append(helpMenu, _T("&Help"));
238
239 // ... and attach this menu bar to the frame
240 SetMenuBar(menuBar);
241#endif // wxUSE_MENUS
242
2aefc528 243#if 0 // wxUSE_STATUSBAR
ae23a52a
JS
244 // create a status bar just for fun (by default with 1 pane only)
245 CreateStatusBar(2);
246 SetStatusText(_T("Welcome to wxWindows!"));
247#endif // wxUSE_STATUSBAR
248
2aefc528 249#if 1
8586126c
JS
250 wxSplitterWindow* splitter = new wxSplitterWindow(this, -1);
251 splitter->CreateAccessible();
252
253 wxListBox* listBox = new wxListBox(splitter, -1);
254 listBox->CreateAccessible();
255
256 m_textCtrl = new wxTextCtrl(splitter, -1, wxT(""), wxDefaultPosition,
257 wxDefaultSize, wxTE_MULTILINE);
258 m_textCtrl->CreateAccessible();
259
260 splitter->SplitHorizontally(listBox, m_textCtrl, 150);
2aefc528 261#endif
8586126c
JS
262
263#if 0
ae23a52a
JS
264#if 1
265 wxListBox* listBox = new wxListBox(this, -1);
8586126c 266 //listBox->SetAccessible(new wxAccessible(listBox));
ae23a52a
JS
267#else
268 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, -1);
269 scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
270#endif
8586126c 271#endif
ae23a52a
JS
272}
273
274
275// event handlers
276
277void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
278{
279 // TRUE is to force the frame to close
280 Close(TRUE);
281}
282
283void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
284{
285 wxString msg;
286 msg.Printf( _T("This is the About dialog of the AccessTest sample.\n")
287 _T("Welcome to %s"), wxVERSION_STRING);
288
289 wxMessageBox(msg, _T("About AccessTest"), wxOK | wxICON_INFORMATION, this);
290}
8586126c
JS
291
292void MyFrame::OnQuery(wxCommandEvent& WXUNUSED(event))
293{
294 m_textCtrl->Clear();
295 IAccessible* accessibleFrame = NULL;
296 if (S_OK != AccessibleObjectFromWindow((HWND) GetHWND(), OBJID_CLIENT,
297 IID_IAccessible, (void**) & accessibleFrame))
298 {
299 Log(wxT("Could not get object."));
300 return;
301 }
302 if (accessibleFrame)
303 {
2aefc528 304 //Log(wxT("Got an IAccessible for the frame."));
8586126c 305 LogObject(0, accessibleFrame);
2aefc528
JS
306 Log(wxT("Checking children using AccessibleChildren()..."));
307
308 // Now check the AccessibleChildren function works OK
309 long childCount = 0;
310 if (S_OK != accessibleFrame->get_accChildCount(& childCount))
311 {
312 Log(wxT("Could not get number of children."));
313 accessibleFrame->Release();
314 return;
315 }
316 else if (childCount == 0)
317 {
318 Log(wxT("No children."));
319 accessibleFrame->Release();
320 return;
321 }
322
323
324 long obtained = 0;
325 VARIANT *var = new VARIANT[childCount];
326 int i;
327 for (i = 0; i < childCount; i++)
328 {
329 VariantInit(& (var[i]));
330 var[i].vt = VT_DISPATCH;
331 }
332
333 if (S_OK == AccessibleChildren(accessibleFrame, 0, childCount, var, &obtained))
334 {
335 for (i = 0; i < childCount; i++)
336 {
337 IAccessible* childAccessible = NULL;
338 if (var[i].pdispVal)
339 {
340 if (var[i].pdispVal->QueryInterface(IID_IAccessible, (LPVOID*) & childAccessible) == S_OK)
341 {
342 var[i].pdispVal->Release();
343
344 wxString name, role;
345 GetInfo(childAccessible, 0, name, role);
346 wxString str;
347 str.Printf(wxT("Found child %s/%s"), name.c_str(), role.c_str());
348 Log(str);
349 childAccessible->Release();
350 }
351 else
352 {
353 var[i].pdispVal->Release();
354 }
355 }
356 }
357 }
358 else
359 {
360 Log(wxT("AccessibleChildren failed."));
361 }
362 delete[] var;
363
364
8586126c
JS
365 accessibleFrame->Release();
366 }
367}
368
369// Log messages to the text control
370void MyFrame::Log(const wxString& text)
371{
372 if (m_textCtrl)
373 {
374 wxString text2(text);
375 text2.Replace(wxT("\n"), wxT(" "));
376 text2.Replace(wxT("\r"), wxT(" "));
377 m_textCtrl->SetInsertionPointEnd();
378 m_textCtrl->WriteText(text2 + wxT("\n"));
379 }
380}
381
382// Recursively give information about an object
383void MyFrame::LogObject(int indent, IAccessible* obj)
384{
2aefc528
JS
385 wxString name, role;
386 if (indent == 0)
8586126c 387 {
2aefc528
JS
388 GetInfo(obj, 0, name, role);
389
8586126c 390 wxString str;
2aefc528 391 str.Printf(wxT("Name = %s; Role = %s"), name.c_str(), role.c_str());
8586126c
JS
392 str.Pad(indent, wxT(' '), FALSE);
393 Log(str);
394 }
8586126c
JS
395
396 long childCount = 0;
397 if (S_OK == obj->get_accChildCount(& childCount))
398 {
399 wxString str;
400 str.Printf(wxT("There are %d children."), (int) childCount);
401 str.Pad(indent, wxT(' '), FALSE);
402 Log(str);
2aefc528 403 Log(wxT(""));
8586126c
JS
404 }
405
406 int i;
407 for (i = 1; i <= childCount; i++)
408 {
2aefc528
JS
409 GetInfo(obj, i, name, role);
410
411 wxString str;
412 str.Printf(wxT("%d) Name = %s; Role = %s"), i, name.c_str(), role.c_str());
413 str.Pad(indent, wxT(' '), FALSE);
414 Log(str);
415
8586126c
JS
416 VARIANT var;
417 VariantInit(& var);
418 var.vt = VT_I4;
419 var.lVal = i;
420 IDispatch* pDisp = NULL;
421 IAccessible* childObject = NULL;
422
8586126c
JS
423 if (S_OK == obj->get_accChild(var, & pDisp) && pDisp)
424 {
425 wxString str;
426 str.Printf(wxT("This is a real object."));
427 str.Pad(indent+4, wxT(' '), FALSE);
428 Log(str);
429
430 if (pDisp->QueryInterface(IID_IAccessible, (LPVOID*) & childObject) == S_OK)
431 {
432 LogObject(indent + 4, childObject);
433 childObject->Release();
434 }
435 pDisp->Release();
436 }
437 else
438 {
439 wxString str;
440 str.Printf(wxT("This is an element."));
441 str.Pad(indent+4, wxT(' '), FALSE);
442 Log(str);
443 }
2aefc528 444 // Log(wxT(""));
8586126c
JS
445 }
446
447}
448
2aefc528
JS
449// Get info for a child (id > 0) or object (id == 0)
450void MyFrame::GetInfo(IAccessible* accessible, int id, wxString& name, wxString& role)
451{
452 VARIANT var;
453 VariantInit(& var);
454 var.vt = VT_I4;
455 var.lVal = id;
456
457 BSTR bStrName = 0;
458 HRESULT hResult = accessible->get_accName(var, & bStrName);
459
460 if (hResult == S_OK)
461 {
462 name = wxConvertStringFromOle(bStrName);
463 SysFreeString(bStrName);
464 }
465 else
466 {
467 name = wxT("NO NAME");
468 }
469
470 VARIANT varRole;
471 VariantInit(& varRole);
472
473 hResult = accessible->get_accRole(var, & varRole);
474
475 if (hResult == S_OK && varRole.vt == VT_I4)
476 {
477 wxChar buf[256];
478 GetRoleText(varRole.lVal, buf, 256);
479
480 role = buf;
481 }
482 else
483 {
484 role = wxT("NO ROLE");
485 }
486}