keyboard.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: keyboard.cpp
  3. // Purpose: Keyboard wxWidgets sample
  4. // Author: Vadim Zeitlin
  5. // Modified by: Marcin Wojdyr
  6. // Created: 07.04.02
  7. // Copyright: (c) 2002 Vadim Zeitlin
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. #include "wx/wxprec.h"
  11. #ifdef __BORLANDC__
  12. #pragma hdrstop
  13. #endif
  14. #ifndef WX_PRECOMP
  15. #include "wx/wx.h"
  16. #endif
  17. #ifndef wxHAS_IMAGES_IN_RESOURCES
  18. #include "../sample.xpm"
  19. #endif
  20. // IDs for menu items
  21. enum
  22. {
  23. QuitID = wxID_EXIT,
  24. ClearID = wxID_CLEAR,
  25. SkipHook = 100,
  26. SkipDown,
  27. // These IDs must be in the same order as MyFrame::InputKind enum elements.
  28. IDInputCustom,
  29. IDInputEntry,
  30. IDInputText,
  31. TestAccelA,
  32. TestAccelCtrlA,
  33. TestAccelEsc
  34. };
  35. // Define a new frame type: this is going to be our main frame
  36. class MyFrame : public wxFrame
  37. {
  38. public:
  39. MyFrame(const wxString& title);
  40. private:
  41. // event handlers
  42. void OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(true); }
  43. void OnAbout(wxCommandEvent& event);
  44. void OnInputWindowKind(wxCommandEvent& event);
  45. void OnTestAccelA(wxCommandEvent& WXUNUSED(event))
  46. { m_logText->AppendText("Test accelerator \"A\" used.\n"); }
  47. void OnTestAccelCtrlA(wxCommandEvent& WXUNUSED(event))
  48. { m_logText->AppendText("Test accelerator \"Ctrl-A\" used.\n"); }
  49. void OnTestAccelEsc(wxCommandEvent& WXUNUSED(event))
  50. { m_logText->AppendText("Test accelerator \"Esc\" used.\n"); }
  51. void OnClear(wxCommandEvent& WXUNUSED(event)) { m_logText->Clear(); }
  52. void OnSkipDown(wxCommandEvent& event) { m_skipDown = event.IsChecked(); }
  53. void OnSkipHook(wxCommandEvent& event) { m_skipHook = event.IsChecked(); }
  54. void OnKeyDown(wxKeyEvent& event)
  55. {
  56. LogEvent("KeyDown", event);
  57. if ( m_skipDown )
  58. event.Skip();
  59. }
  60. void OnKeyUp(wxKeyEvent& event) { LogEvent("KeyUp", event); }
  61. void OnChar(wxKeyEvent& event) { LogEvent("Char", event); event.Skip(); }
  62. void OnCharHook(wxKeyEvent& event)
  63. {
  64. // The logged messages can be confusing if the input window doesn't
  65. // have focus so warn about this.
  66. if ( !m_inputWin->HasFocus() )
  67. {
  68. m_logText->SetDefaultStyle(*wxRED);
  69. m_logText->AppendText("WARNING: focus is not on input window, "
  70. "non-hook events won't be logged.\n");
  71. m_logText->SetDefaultStyle(wxTextAttr());
  72. }
  73. LogEvent("Hook", event);
  74. if ( m_skipHook )
  75. event.Skip();
  76. }
  77. void OnPaintInputWin(wxPaintEvent& event);
  78. void LogEvent(const wxString& name, wxKeyEvent& event);
  79. // Set m_inputWin to either a new window of the given kind:
  80. enum InputKind
  81. {
  82. Input_Custom, // Just a plain wxWindow
  83. Input_Entry, // Single-line wxTextCtrl
  84. Input_Text // Multi-line wxTextCtrl
  85. };
  86. void DoCreateInputWindow(InputKind inputKind);
  87. wxTextCtrl *m_logText;
  88. wxWindow *m_inputWin;
  89. bool m_skipHook,
  90. m_skipDown;
  91. };
  92. // Define a new application type, each program should derive a class from wxApp
  93. class MyApp : public wxApp
  94. {
  95. public:
  96. // 'Main program' equivalent: the program execution "starts" here
  97. virtual bool OnInit()
  98. {
  99. // create the main application window
  100. new MyFrame("Keyboard wxWidgets App");
  101. // If we returned false here, the application would exit immediately.
  102. return true;
  103. }
  104. };
  105. // Create a new application object: this macro will allow wxWidgets to create
  106. // the application object during program execution (it's better than using a
  107. // static object for many reasons) and also declares the accessor function
  108. // wxGetApp() which will return the reference of the right type (i.e. MyApp and
  109. // not wxApp)
  110. IMPLEMENT_APP(MyApp)
  111. // ============================================================================
  112. // implementation
  113. // ============================================================================
  114. // frame constructor
  115. MyFrame::MyFrame(const wxString& title)
  116. : wxFrame(NULL, wxID_ANY, title),
  117. m_inputWin(NULL),
  118. m_skipHook(true),
  119. m_skipDown(true)
  120. {
  121. SetIcon(wxICON(sample));
  122. // create a menu bar
  123. wxMenu *menuFile = new wxMenu;
  124. menuFile->Append(ClearID, "&Clear log\tCtrl-L");
  125. menuFile->AppendSeparator();
  126. menuFile->Append(TestAccelA, "Test accelerator &1\tA");
  127. menuFile->Append(TestAccelCtrlA, "Test accelerator &2\tCtrl-A");
  128. menuFile->Append(TestAccelEsc, "Test accelerator &3\tEsc");
  129. menuFile->AppendSeparator();
  130. menuFile->AppendCheckItem(SkipHook, "Skip CHAR_HOOK event",
  131. "Not skipping this event disables both KEY_DOWN and CHAR events"
  132. );
  133. menuFile->Check(SkipHook, true);
  134. menuFile->AppendCheckItem(SkipDown, "Skip KEY_DOWN event",
  135. "Not skipping this event disables CHAR event generation"
  136. );
  137. menuFile->Check(SkipDown, true);
  138. menuFile->AppendSeparator();
  139. menuFile->AppendRadioItem(IDInputCustom, "Use &custom control\tCtrl-C",
  140. "Use custom wxWindow for input window"
  141. );
  142. menuFile->AppendRadioItem(IDInputEntry, "Use text &entry\tCtrl-E",
  143. "Use single-line wxTextCtrl for input window"
  144. );
  145. menuFile->AppendRadioItem(IDInputText, "Use &text control\tCtrl-T",
  146. "Use multi-line wxTextCtrl for input window"
  147. );
  148. menuFile->AppendSeparator();
  149. menuFile->Append(QuitID, "E&xit\tAlt-X", "Quit this program");
  150. // the "About" item should be in the help menu
  151. wxMenu *menuHelp = new wxMenu;
  152. menuHelp->Append(wxID_ABOUT, "&About\tF1", "Show about dialog");
  153. // now append the freshly created menu to the menu bar...
  154. wxMenuBar *menuBar = new wxMenuBar();
  155. menuBar->Append(menuFile, "&File");
  156. menuBar->Append(menuHelp, "&Help");
  157. // ... and attach this menu bar to the frame
  158. SetMenuBar(menuBar);
  159. DoCreateInputWindow(Input_Custom);
  160. wxTextCtrl *headerText = new wxTextCtrl(this, wxID_ANY, "",
  161. wxDefaultPosition, wxDefaultSize,
  162. wxTE_READONLY);
  163. headerText->SetValue(
  164. " event key KeyCode mod UnicodeKey "
  165. " RawKeyCode RawKeyFlags Position");
  166. m_logText = new wxTextCtrl(this, wxID_ANY, "",
  167. wxDefaultPosition, wxDefaultSize,
  168. wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH|wxHSCROLL);
  169. // set monospace font to have output in nice columns
  170. wxFont font(10, wxFONTFAMILY_TELETYPE,
  171. wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
  172. headerText->SetFont(font);
  173. m_logText->SetFont(font);
  174. // layout
  175. wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
  176. sizer->Add(m_inputWin, wxSizerFlags().Expand());
  177. sizer->Add(headerText, wxSizerFlags().Expand());
  178. sizer->Add(m_logText, wxSizerFlags(1).Expand());
  179. SetSizerAndFit(sizer);
  180. // set size and position on screen
  181. SetSize(700, 340);
  182. CentreOnScreen();
  183. // connect menu event handlers
  184. Connect(QuitID, wxEVT_MENU,
  185. wxCommandEventHandler(MyFrame::OnQuit));
  186. Connect(wxID_ABOUT, wxEVT_MENU,
  187. wxCommandEventHandler(MyFrame::OnAbout));
  188. Connect(ClearID, wxEVT_MENU,
  189. wxCommandEventHandler(MyFrame::OnClear));
  190. Connect(SkipHook, wxEVT_MENU,
  191. wxCommandEventHandler(MyFrame::OnSkipHook));
  192. Connect(SkipDown, wxEVT_MENU,
  193. wxCommandEventHandler(MyFrame::OnSkipDown));
  194. Connect(IDInputCustom, IDInputText, wxEVT_MENU,
  195. wxCommandEventHandler(MyFrame::OnInputWindowKind));
  196. Connect(TestAccelA, wxEVT_MENU,
  197. wxCommandEventHandler(MyFrame::OnTestAccelA));
  198. Connect(TestAccelCtrlA, wxEVT_MENU,
  199. wxCommandEventHandler(MyFrame::OnTestAccelCtrlA));
  200. Connect(TestAccelEsc, wxEVT_MENU,
  201. wxCommandEventHandler(MyFrame::OnTestAccelEsc));
  202. // notice that we don't connect OnCharHook() to the input window, unlike
  203. // the usual key events this one is propagated upwards
  204. Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MyFrame::OnCharHook));
  205. // status bar is useful for showing the menu items help strings
  206. CreateStatusBar();
  207. // and show itself (the frames, unlike simple controls, are not shown when
  208. // created initially)
  209. Show(true);
  210. }
  211. // event handlers
  212. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  213. {
  214. wxMessageBox("Demonstrates keyboard event processing in wxWidgets\n"
  215. "(c) 2002 Vadim Zeitlin\n"
  216. "(c) 2008 Marcin Wojdyr",
  217. "About wxWidgets Keyboard Sample",
  218. wxOK | wxICON_INFORMATION, this);
  219. }
  220. void MyFrame::DoCreateInputWindow(InputKind inputKind)
  221. {
  222. wxWindow* const oldWin = m_inputWin;
  223. switch ( inputKind )
  224. {
  225. case Input_Custom:
  226. m_inputWin = new wxWindow(this, wxID_ANY,
  227. wxDefaultPosition, wxSize(-1, 50),
  228. wxRAISED_BORDER);
  229. break;
  230. case Input_Entry:
  231. m_inputWin = new wxTextCtrl(this, wxID_ANY, "Press keys here");
  232. break;
  233. case Input_Text:
  234. m_inputWin = new wxTextCtrl(this, wxID_ANY, "Press keys here",
  235. wxDefaultPosition, wxSize(-1, 50),
  236. wxTE_MULTILINE);
  237. break;
  238. }
  239. m_inputWin->SetBackgroundColour(*wxBLUE);
  240. m_inputWin->SetForegroundColour(*wxWHITE);
  241. // connect event handlers for the blue input window
  242. m_inputWin->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MyFrame::OnKeyDown),
  243. NULL, this);
  244. m_inputWin->Connect(wxEVT_KEY_UP, wxKeyEventHandler(MyFrame::OnKeyUp),
  245. NULL, this);
  246. m_inputWin->Connect(wxEVT_CHAR, wxKeyEventHandler(MyFrame::OnChar),
  247. NULL, this);
  248. if ( inputKind == Input_Custom )
  249. {
  250. m_inputWin->Connect(wxEVT_PAINT,
  251. wxPaintEventHandler(MyFrame::OnPaintInputWin),
  252. NULL, this);
  253. }
  254. if ( oldWin )
  255. {
  256. GetSizer()->Replace(oldWin, m_inputWin);
  257. Layout();
  258. delete oldWin;
  259. }
  260. }
  261. void MyFrame::OnInputWindowKind(wxCommandEvent& event)
  262. {
  263. DoCreateInputWindow(
  264. static_cast<InputKind>(event.GetId() - IDInputCustom)
  265. );
  266. }
  267. void MyFrame::OnPaintInputWin(wxPaintEvent& WXUNUSED(event))
  268. {
  269. wxPaintDC dc(m_inputWin);
  270. dc.SetTextForeground(*wxWHITE);
  271. wxFont font(*wxSWISS_FONT);
  272. font.SetWeight(wxFONTWEIGHT_BOLD);
  273. font.SetPointSize(font.GetPointSize() + 2);
  274. dc.SetFont(font);
  275. dc.DrawLabel("Press keys here",
  276. m_inputWin->GetClientRect(), wxALIGN_CENTER);
  277. }
  278. // helper function that returns textual description of wx virtual keycode
  279. const char* GetVirtualKeyCodeName(int keycode)
  280. {
  281. switch ( keycode )
  282. {
  283. #define WXK_(x) \
  284. case WXK_##x: return #x;
  285. WXK_(BACK)
  286. WXK_(TAB)
  287. WXK_(RETURN)
  288. WXK_(ESCAPE)
  289. WXK_(SPACE)
  290. WXK_(DELETE)
  291. WXK_(START)
  292. WXK_(LBUTTON)
  293. WXK_(RBUTTON)
  294. WXK_(CANCEL)
  295. WXK_(MBUTTON)
  296. WXK_(CLEAR)
  297. WXK_(SHIFT)
  298. WXK_(ALT)
  299. WXK_(CONTROL)
  300. WXK_(MENU)
  301. WXK_(PAUSE)
  302. WXK_(CAPITAL)
  303. WXK_(END)
  304. WXK_(HOME)
  305. WXK_(LEFT)
  306. WXK_(UP)
  307. WXK_(RIGHT)
  308. WXK_(DOWN)
  309. WXK_(SELECT)
  310. WXK_(PRINT)
  311. WXK_(EXECUTE)
  312. WXK_(SNAPSHOT)
  313. WXK_(INSERT)
  314. WXK_(HELP)
  315. WXK_(NUMPAD0)
  316. WXK_(NUMPAD1)
  317. WXK_(NUMPAD2)
  318. WXK_(NUMPAD3)
  319. WXK_(NUMPAD4)
  320. WXK_(NUMPAD5)
  321. WXK_(NUMPAD6)
  322. WXK_(NUMPAD7)
  323. WXK_(NUMPAD8)
  324. WXK_(NUMPAD9)
  325. WXK_(MULTIPLY)
  326. WXK_(ADD)
  327. WXK_(SEPARATOR)
  328. WXK_(SUBTRACT)
  329. WXK_(DECIMAL)
  330. WXK_(DIVIDE)
  331. WXK_(F1)
  332. WXK_(F2)
  333. WXK_(F3)
  334. WXK_(F4)
  335. WXK_(F5)
  336. WXK_(F6)
  337. WXK_(F7)
  338. WXK_(F8)
  339. WXK_(F9)
  340. WXK_(F10)
  341. WXK_(F11)
  342. WXK_(F12)
  343. WXK_(F13)
  344. WXK_(F14)
  345. WXK_(F15)
  346. WXK_(F16)
  347. WXK_(F17)
  348. WXK_(F18)
  349. WXK_(F19)
  350. WXK_(F20)
  351. WXK_(F21)
  352. WXK_(F22)
  353. WXK_(F23)
  354. WXK_(F24)
  355. WXK_(NUMLOCK)
  356. WXK_(SCROLL)
  357. WXK_(PAGEUP)
  358. WXK_(PAGEDOWN)
  359. WXK_(NUMPAD_SPACE)
  360. WXK_(NUMPAD_TAB)
  361. WXK_(NUMPAD_ENTER)
  362. WXK_(NUMPAD_F1)
  363. WXK_(NUMPAD_F2)
  364. WXK_(NUMPAD_F3)
  365. WXK_(NUMPAD_F4)
  366. WXK_(NUMPAD_HOME)
  367. WXK_(NUMPAD_LEFT)
  368. WXK_(NUMPAD_UP)
  369. WXK_(NUMPAD_RIGHT)
  370. WXK_(NUMPAD_DOWN)
  371. WXK_(NUMPAD_PAGEUP)
  372. WXK_(NUMPAD_PAGEDOWN)
  373. WXK_(NUMPAD_END)
  374. WXK_(NUMPAD_BEGIN)
  375. WXK_(NUMPAD_INSERT)
  376. WXK_(NUMPAD_DELETE)
  377. WXK_(NUMPAD_EQUAL)
  378. WXK_(NUMPAD_MULTIPLY)
  379. WXK_(NUMPAD_ADD)
  380. WXK_(NUMPAD_SEPARATOR)
  381. WXK_(NUMPAD_SUBTRACT)
  382. WXK_(NUMPAD_DECIMAL)
  383. WXK_(NUMPAD_DIVIDE)
  384. WXK_(WINDOWS_LEFT)
  385. WXK_(WINDOWS_RIGHT)
  386. #ifdef __WXOSX__
  387. WXK_(RAW_CONTROL)
  388. #endif
  389. #undef WXK_
  390. default:
  391. return NULL;
  392. }
  393. }
  394. // helper function that returns textual description of key in the event
  395. wxString GetKeyName(const wxKeyEvent &event)
  396. {
  397. int keycode = event.GetKeyCode();
  398. const char* virt = GetVirtualKeyCodeName(keycode);
  399. if ( virt )
  400. return virt;
  401. if ( keycode > 0 && keycode < 32 )
  402. return wxString::Format("Ctrl-%c", (unsigned char)('A' + keycode - 1));
  403. if ( keycode >= 32 && keycode < 128 )
  404. return wxString::Format("'%c'", (unsigned char)keycode);
  405. #if wxUSE_UNICODE
  406. int uc = event.GetUnicodeKey();
  407. if ( uc != WXK_NONE )
  408. return wxString::Format("'%c'", uc);
  409. #endif
  410. return "unknown";
  411. }
  412. void MyFrame::LogEvent(const wxString& name, wxKeyEvent& event)
  413. {
  414. wxString msg;
  415. // event key_name KeyCode modifiers Unicode raw_code raw_flags pos
  416. msg.Printf("%7s %15s %5d %c%c%c%c"
  417. #if wxUSE_UNICODE
  418. "%5d (U+%04x)"
  419. #else
  420. " none "
  421. #endif
  422. #ifdef wxHAS_RAW_KEY_CODES
  423. " %7lu 0x%08lx"
  424. #else
  425. " not-set not-set"
  426. #endif
  427. " (%5d,%5d)"
  428. "\n",
  429. name,
  430. GetKeyName(event),
  431. event.GetKeyCode(),
  432. event.ControlDown() ? 'C' : '-',
  433. event.AltDown() ? 'A' : '-',
  434. event.ShiftDown() ? 'S' : '-',
  435. event.MetaDown() ? 'M' : '-'
  436. #if wxUSE_UNICODE
  437. , event.GetUnicodeKey()
  438. , event.GetUnicodeKey()
  439. #endif
  440. #ifdef wxHAS_RAW_KEY_CODES
  441. , (unsigned long) event.GetRawKeyCode()
  442. , (unsigned long) event.GetRawKeyFlags()
  443. #endif
  444. , event.GetX()
  445. , event.GetY()
  446. );
  447. m_logText->AppendText(msg);
  448. }