]> git.saurik.com Git - wxWidgets.git/blame - samples/access/accesstest.cpp
prevent from setting min[WH] > max[WH] because this leads to an infinite loop later...
[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
ae23a52a 96private:
8586126c
JS
97 wxTextCtrl* m_textCtrl;
98
ae23a52a
JS
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
108enum
109{
110 // menu items
111 AccessTest_Quit = 1,
112
8586126c
JS
113 // query the hierarchy
114 AccessTest_Query,
115
ae23a52a
JS
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.
129BEGIN_EVENT_TABLE(MyFrame, wxFrame)
130 EVT_MENU(AccessTest_Quit, MyFrame::OnQuit)
8586126c 131 EVT_MENU(AccessTest_Query, MyFrame::OnQuery)
ae23a52a
JS
132 EVT_MENU(AccessTest_About, MyFrame::OnAbout)
133END_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)
140IMPLEMENT_APP(MyApp)
141
142// ============================================================================
143// implementation
144// ============================================================================
145
146// ----------------------------------------------------------------------------
147// the application class
148// ----------------------------------------------------------------------------
149
150// 'Main program' equivalent: the program execution "starts" here
151bool 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
167class FrameAccessible: public wxWindowAccessible
168{
169public:
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
187class ScrolledWindowAccessible: public wxWindowAccessible
188{
189public:
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
210MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
211 : wxFrame(NULL, -1, title, pos, size, style)
212{
8586126c
JS
213 m_textCtrl = NULL;
214
ae23a52a
JS
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
8586126c
JS
228 menuFile->Append(AccessTest_Query, _T("Query"), _T("Query the window hierarchy"));
229 menuFile->AppendSeparator();
ae23a52a
JS
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
8586126c 241#if 1 // wxUSE_STATUSBAR
ae23a52a
JS
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
8586126c
JS
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
ae23a52a
JS
260#if 1
261 wxListBox* listBox = new wxListBox(this, -1);
8586126c 262 //listBox->SetAccessible(new wxAccessible(listBox));
ae23a52a
JS
263#else
264 wxScrolledWindow* scrolledWindow = new wxScrolledWindow(this, -1);
265 scrolledWindow->SetAccessible(new ScrolledWindowAccessible(scrolledWindow));
266#endif
8586126c 267#endif
ae23a52a
JS
268}
269
270
271// event handlers
272
273void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
274{
275 // TRUE is to force the frame to close
276 Close(TRUE);
277}
278
279void 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}
8586126c
JS
287
288void 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
307void 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
320void 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