1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Keyboard wxWidgets sample
4 // Author: Vadim Zeitlin
5 // Modified by: Marcin Wojdyr
8 // Copyright: (c) 2002 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
21 #ifndef wxHAS_IMAGES_IN_RESOURCES
22 #include "../sample.xpm"
33 // These IDs must be in the same order as MyFrame::InputKind enum elements.
43 // Define a new frame type: this is going to be our main frame
44 class MyFrame
: public wxFrame
47 MyFrame(const wxString
& title
);
51 void OnQuit(wxCommandEvent
& WXUNUSED(event
)) { Close(true); }
52 void OnAbout(wxCommandEvent
& event
);
54 void OnInputWindowKind(wxCommandEvent
& event
);
56 void OnTestAccelA(wxCommandEvent
& WXUNUSED(event
))
57 { m_logText
->AppendText("Test accelerator \"A\" used.\n"); }
58 void OnTestAccelCtrlA(wxCommandEvent
& WXUNUSED(event
))
59 { m_logText
->AppendText("Test accelerator \"Ctrl-A\" used.\n"); }
60 void OnTestAccelEsc(wxCommandEvent
& WXUNUSED(event
))
61 { m_logText
->AppendText("Test accelerator \"Esc\" used.\n"); }
63 void OnClear(wxCommandEvent
& WXUNUSED(event
)) { m_logText
->Clear(); }
64 void OnSkipDown(wxCommandEvent
& event
) { m_skipDown
= event
.IsChecked(); }
65 void OnSkipHook(wxCommandEvent
& event
) { m_skipHook
= event
.IsChecked(); }
67 void OnKeyDown(wxKeyEvent
& event
)
69 LogEvent("KeyDown", event
);
73 void OnKeyUp(wxKeyEvent
& event
) { LogEvent("KeyUp", event
); }
74 void OnChar(wxKeyEvent
& event
) { LogEvent("Char", event
); event
.Skip(); }
75 void OnCharHook(wxKeyEvent
& event
)
77 // The logged messages can be confusing if the input window doesn't
78 // have focus so warn about this.
79 if ( !m_inputWin
->HasFocus() )
81 m_logText
->SetDefaultStyle(*wxRED
);
82 m_logText
->AppendText("WARNING: focus is not on input window, "
83 "non-hook events won't be logged.\n");
84 m_logText
->SetDefaultStyle(wxTextAttr());
87 LogEvent("Hook", event
);
92 void OnPaintInputWin(wxPaintEvent
& event
);
94 void LogEvent(const wxString
& name
, wxKeyEvent
& event
);
96 // Set m_inputWin to either a new window of the given kind:
99 Input_Custom
, // Just a plain wxWindow
100 Input_Entry
, // Single-line wxTextCtrl
101 Input_Text
// Multi-line wxTextCtrl
104 void DoCreateInputWindow(InputKind inputKind
);
106 wxTextCtrl
*m_logText
;
107 wxWindow
*m_inputWin
;
113 // Define a new application type, each program should derive a class from wxApp
114 class MyApp
: public wxApp
117 // 'Main program' equivalent: the program execution "starts" here
118 virtual bool OnInit()
120 // create the main application window
121 new MyFrame("Keyboard wxWidgets App");
123 // If we returned false here, the application would exit immediately.
128 // Create a new application object: this macro will allow wxWidgets to create
129 // the application object during program execution (it's better than using a
130 // static object for many reasons) and also declares the accessor function
131 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
136 // ============================================================================
138 // ============================================================================
141 MyFrame::MyFrame(const wxString
& title
)
142 : wxFrame(NULL
, wxID_ANY
, title
),
147 SetIcon(wxICON(sample
));
150 wxMenu
*menuFile
= new wxMenu
;
152 menuFile
->Append(ClearID
, "&Clear log\tCtrl-L");
153 menuFile
->AppendSeparator();
155 menuFile
->Append(TestAccelA
, "Test accelerator &1\tA");
156 menuFile
->Append(TestAccelCtrlA
, "Test accelerator &2\tCtrl-A");
157 menuFile
->Append(TestAccelEsc
, "Test accelerator &3\tEsc");
158 menuFile
->AppendSeparator();
160 menuFile
->AppendCheckItem(SkipHook
, "Skip CHAR_HOOK event",
161 "Not skipping this event disables both KEY_DOWN and CHAR events"
163 menuFile
->Check(SkipHook
, true);
164 menuFile
->AppendCheckItem(SkipDown
, "Skip KEY_DOWN event",
165 "Not skipping this event disables CHAR event generation"
167 menuFile
->Check(SkipDown
, true);
168 menuFile
->AppendSeparator();
170 menuFile
->AppendRadioItem(IDInputCustom
, "Use &custom control\tCtrl-C",
171 "Use custom wxWindow for input window"
173 menuFile
->AppendRadioItem(IDInputEntry
, "Use text &entry\tCtrl-E",
174 "Use single-line wxTextCtrl for input window"
176 menuFile
->AppendRadioItem(IDInputText
, "Use &text control\tCtrl-T",
177 "Use multi-line wxTextCtrl for input window"
179 menuFile
->AppendSeparator();
181 menuFile
->Append(QuitID
, "E&xit\tAlt-X", "Quit this program");
183 // the "About" item should be in the help menu
184 wxMenu
*menuHelp
= new wxMenu
;
185 menuHelp
->Append(wxID_ABOUT
, "&About\tF1", "Show about dialog");
187 // now append the freshly created menu to the menu bar...
188 wxMenuBar
*menuBar
= new wxMenuBar();
189 menuBar
->Append(menuFile
, "&File");
190 menuBar
->Append(menuHelp
, "&Help");
192 // ... and attach this menu bar to the frame
195 DoCreateInputWindow(Input_Custom
);
197 wxTextCtrl
*headerText
= new wxTextCtrl(this, wxID_ANY
, "",
198 wxDefaultPosition
, wxDefaultSize
,
200 headerText
->SetValue(
201 " event key KeyCode mod UnicodeKey "
202 " RawKeyCode RawKeyFlags Position");
205 m_logText
= new wxTextCtrl(this, wxID_ANY
, "",
206 wxDefaultPosition
, wxDefaultSize
,
207 wxTE_MULTILINE
|wxTE_READONLY
|wxTE_RICH
|wxHSCROLL
);
209 // set monospace font to have output in nice columns
210 wxFont
font(10, wxFONTFAMILY_TELETYPE
,
211 wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
);
212 headerText
->SetFont(font
);
213 m_logText
->SetFont(font
);
216 wxBoxSizer
*sizer
= new wxBoxSizer(wxVERTICAL
);
217 sizer
->Add(m_inputWin
, wxSizerFlags().Expand());
218 sizer
->Add(headerText
, wxSizerFlags().Expand());
219 sizer
->Add(m_logText
, wxSizerFlags(1).Expand());
220 SetSizerAndFit(sizer
);
222 // set size and position on screen
226 // connect menu event handlers
228 Connect(QuitID
, wxEVT_COMMAND_MENU_SELECTED
,
229 wxCommandEventHandler(MyFrame::OnQuit
));
231 Connect(wxID_ABOUT
, wxEVT_COMMAND_MENU_SELECTED
,
232 wxCommandEventHandler(MyFrame::OnAbout
));
234 Connect(ClearID
, wxEVT_COMMAND_MENU_SELECTED
,
235 wxCommandEventHandler(MyFrame::OnClear
));
237 Connect(SkipHook
, wxEVT_COMMAND_MENU_SELECTED
,
238 wxCommandEventHandler(MyFrame::OnSkipHook
));
239 Connect(SkipDown
, wxEVT_COMMAND_MENU_SELECTED
,
240 wxCommandEventHandler(MyFrame::OnSkipDown
));
242 Connect(IDInputCustom
, IDInputText
, wxEVT_COMMAND_MENU_SELECTED
,
243 wxCommandEventHandler(MyFrame::OnInputWindowKind
));
245 Connect(TestAccelA
, wxEVT_COMMAND_MENU_SELECTED
,
246 wxCommandEventHandler(MyFrame::OnTestAccelA
));
248 Connect(TestAccelCtrlA
, wxEVT_COMMAND_MENU_SELECTED
,
249 wxCommandEventHandler(MyFrame::OnTestAccelCtrlA
));
251 Connect(TestAccelEsc
, wxEVT_COMMAND_MENU_SELECTED
,
252 wxCommandEventHandler(MyFrame::OnTestAccelEsc
));
254 // notice that we don't connect OnCharHook() to the input window, unlike
255 // the usual key events this one is propagated upwards
256 Connect(wxEVT_CHAR_HOOK
, wxKeyEventHandler(MyFrame::OnCharHook
));
258 // status bar is useful for showing the menu items help strings
261 // and show itself (the frames, unlike simple controls, are not shown when
262 // created initially)
268 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
270 wxMessageBox("Demonstrates keyboard event processing in wxWidgets\n"
271 "(c) 2002 Vadim Zeitlin\n"
272 "(c) 2008 Marcin Wojdyr",
273 "About wxWidgets Keyboard Sample",
274 wxOK
| wxICON_INFORMATION
, this);
277 void MyFrame::DoCreateInputWindow(InputKind inputKind
)
279 wxWindow
* const oldWin
= m_inputWin
;
284 m_inputWin
= new wxWindow(this, wxID_ANY
,
285 wxDefaultPosition
, wxSize(-1, 50),
290 m_inputWin
= new wxTextCtrl(this, wxID_ANY
, "Press keys here");
294 m_inputWin
= new wxTextCtrl(this, wxID_ANY
, "Press keys here",
295 wxDefaultPosition
, wxSize(-1, 50),
300 m_inputWin
->SetBackgroundColour(*wxBLUE
);
301 m_inputWin
->SetForegroundColour(*wxWHITE
);
303 // connect event handlers for the blue input window
304 m_inputWin
->Connect(wxEVT_KEY_DOWN
, wxKeyEventHandler(MyFrame::OnKeyDown
),
306 m_inputWin
->Connect(wxEVT_KEY_UP
, wxKeyEventHandler(MyFrame::OnKeyUp
),
308 m_inputWin
->Connect(wxEVT_CHAR
, wxKeyEventHandler(MyFrame::OnChar
),
311 if ( inputKind
== Input_Custom
)
313 m_inputWin
->Connect(wxEVT_PAINT
,
314 wxPaintEventHandler(MyFrame::OnPaintInputWin
),
320 GetSizer()->Replace(oldWin
, m_inputWin
);
326 void MyFrame::OnInputWindowKind(wxCommandEvent
& event
)
329 static_cast<InputKind
>(event
.GetId() - IDInputCustom
)
333 void MyFrame::OnPaintInputWin(wxPaintEvent
& WXUNUSED(event
))
335 wxPaintDC
dc(m_inputWin
);
336 dc
.SetTextForeground(*wxWHITE
);
337 wxFont
font(*wxSWISS_FONT
);
338 font
.SetWeight(wxFONTWEIGHT_BOLD
);
339 font
.SetPointSize(font
.GetPointSize() + 2);
342 dc
.DrawLabel("Press keys here",
343 m_inputWin
->GetClientRect(), wxALIGN_CENTER
);
347 // helper function that returns textual description of wx virtual keycode
348 const char* GetVirtualKeyCodeName(int keycode
)
353 case WXK_##x: return #x;
442 WXK_(NUMPAD_PAGEDOWN
)
448 WXK_(NUMPAD_MULTIPLY
)
450 WXK_(NUMPAD_SEPARATOR
)
451 WXK_(NUMPAD_SUBTRACT
)
467 // helper function that returns textual description of key in the event
468 wxString
GetKeyName(const wxKeyEvent
&event
)
470 int keycode
= event
.GetKeyCode();
471 const char* virt
= GetVirtualKeyCodeName(keycode
);
474 if ( keycode
> 0 && keycode
< 32 )
475 return wxString::Format("Ctrl-%c", (unsigned char)('A' + keycode
- 1));
476 if ( keycode
>= 32 && keycode
< 128 )
477 return wxString::Format("'%c'", (unsigned char)keycode
);
480 int uc
= event
.GetUnicodeKey();
481 if ( uc
!= WXK_NONE
)
482 return wxString::Format("'%c'", uc
);
489 void MyFrame::LogEvent(const wxString
& name
, wxKeyEvent
& event
)
492 // event key_name KeyCode modifiers Unicode raw_code raw_flags pos
493 msg
.Printf("%7s %15s %5d %c%c%c%c"
499 #ifdef wxHAS_RAW_KEY_CODES
509 event
.ControlDown() ? 'C' : '-',
510 event
.AltDown() ? 'A' : '-',
511 event
.ShiftDown() ? 'S' : '-',
512 event
.MetaDown() ? 'M' : '-'
514 , event
.GetUnicodeKey()
515 , event
.GetUnicodeKey()
517 #ifdef wxHAS_RAW_KEY_CODES
518 , (unsigned long) event
.GetRawKeyCode()
519 , (unsigned long) event
.GetRawKeyFlags()
525 m_logText
->AppendText(msg
);