X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a96bab36bfde8077f7c807f18da054d9c0141d9c..4e2756feef7c684b276660c4044205f93e8f2c84:/samples/keyboard/keyboard.cpp diff --git a/samples/keyboard/keyboard.cpp b/samples/keyboard/keyboard.cpp index 86b4c613ae..579f253dcd 100644 --- a/samples/keyboard/keyboard.cpp +++ b/samples/keyboard/keyboard.cpp @@ -18,6 +18,27 @@ #include "wx/wx.h" #endif +#ifndef wxHAS_IMAGES_IN_RESOURCES + #include "../sample.xpm" +#endif + +// IDs for menu items +enum +{ + QuitID = wxID_EXIT, + ClearID = wxID_CLEAR, + SkipHook = 100, + SkipDown, + + // These IDs must be in the same order as MyFrame::InputKind enum elements. + IDInputCustom, + IDInputEntry, + IDInputText, + + TestAccelA, + TestAccelCtrlA, + TestAccelEsc +}; // Define a new frame type: this is going to be our main frame class MyFrame : public wxFrame @@ -29,18 +50,63 @@ private: // event handlers void OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(true); } void OnAbout(wxCommandEvent& event); + + void OnInputWindowKind(wxCommandEvent& event); + + void OnTestAccelA(wxCommandEvent& WXUNUSED(event)) + { m_logText->AppendText("Test accelerator \"A\" used.\n"); } + void OnTestAccelCtrlA(wxCommandEvent& WXUNUSED(event)) + { m_logText->AppendText("Test accelerator \"Ctrl-A\" used.\n"); } + void OnTestAccelEsc(wxCommandEvent& WXUNUSED(event)) + { m_logText->AppendText("Test accelerator \"Esc\" used.\n"); } + void OnClear(wxCommandEvent& WXUNUSED(event)) { m_logText->Clear(); } - void OnSkip(wxCommandEvent& event) { m_skip = event.IsChecked(); } - void OnKeyDown(wxKeyEvent& event) { LogEvent("KeyDown", event); } + void OnSkipDown(wxCommandEvent& event) { m_skipDown = event.IsChecked(); } + void OnSkipHook(wxCommandEvent& event) { m_skipHook = event.IsChecked(); } + + void OnKeyDown(wxKeyEvent& event) + { + LogEvent("KeyDown", event); + if ( m_skipDown ) + event.Skip(); + } void OnKeyUp(wxKeyEvent& event) { LogEvent("KeyUp", event); } - void OnChar(wxKeyEvent& event) { LogEvent("Char", event); } + void OnChar(wxKeyEvent& event) { LogEvent("Char", event); event.Skip(); } + void OnCharHook(wxKeyEvent& event) + { + // The logged messages can be confusing if the input window doesn't + // have focus so warn about this. + if ( !m_inputWin->HasFocus() ) + { + m_logText->SetDefaultStyle(*wxRED); + m_logText->AppendText("WARNING: focus is not on input window, " + "non-hook events won't be logged.\n"); + m_logText->SetDefaultStyle(wxTextAttr()); + } + + LogEvent("Hook", event); + if ( m_skipHook ) + event.Skip(); + } + void OnPaintInputWin(wxPaintEvent& event); void LogEvent(const wxString& name, wxKeyEvent& event); + // Set m_inputWin to either a new window of the given kind: + enum InputKind + { + Input_Custom, // Just a plain wxWindow + Input_Entry, // Single-line wxTextCtrl + Input_Text // Multi-line wxTextCtrl + }; + + void DoCreateInputWindow(InputKind inputKind); + wxTextCtrl *m_logText; wxWindow *m_inputWin; - bool m_skip; + bool m_skipHook, + m_skipDown; }; @@ -75,15 +141,10 @@ IMPLEMENT_APP(MyApp) MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title), m_inputWin(NULL), - m_skip(true) + m_skipHook(true), + m_skipDown(true) { - // IDs for menu items - enum - { - QuitID = wxID_EXIT, - ClearID = wxID_CLEAR, - SkipID = 100, - }; + SetIcon(wxICON(sample)); // create a menu bar wxMenu *menuFile = new wxMenu; @@ -91,15 +152,37 @@ MyFrame::MyFrame(const wxString& title) menuFile->Append(ClearID, "&Clear log\tCtrl-L"); menuFile->AppendSeparator(); - menuFile->AppendCheckItem(SkipID, "Call event.&Skip()\tCtrl-S"); - menuFile->Check(SkipID, true); + menuFile->Append(TestAccelA, "Test accelerator &1\tA"); + menuFile->Append(TestAccelCtrlA, "Test accelerator &2\tCtrl-A"); + menuFile->Append(TestAccelEsc, "Test accelerator &3\tEsc"); + menuFile->AppendSeparator(); + + menuFile->AppendCheckItem(SkipHook, "Skip CHAR_HOOK event", + "Not skipping this event disables both KEY_DOWN and CHAR events" + ); + menuFile->Check(SkipHook, true); + menuFile->AppendCheckItem(SkipDown, "Skip KEY_DOWN event", + "Not skipping this event disables CHAR event generation" + ); + menuFile->Check(SkipDown, true); + menuFile->AppendSeparator(); + + menuFile->AppendRadioItem(IDInputCustom, "Use &custom control\tCtrl-C", + "Use custom wxWindow for input window" + ); + menuFile->AppendRadioItem(IDInputEntry, "Use text &entry\tCtrl-E", + "Use single-line wxTextCtrl for input window" + ); + menuFile->AppendRadioItem(IDInputText, "Use &text control\tCtrl-T", + "Use multi-line wxTextCtrl for input window" + ); menuFile->AppendSeparator(); menuFile->Append(QuitID, "E&xit\tAlt-X", "Quit this program"); // the "About" item should be in the help menu wxMenu *menuHelp = new wxMenu; - menuHelp->Append(wxID_ABOUT, "&About...\tF1", "Show about dialog"); + menuHelp->Append(wxID_ABOUT, "&About\tF1", "Show about dialog"); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); @@ -109,24 +192,22 @@ MyFrame::MyFrame(const wxString& title) // ... and attach this menu bar to the frame SetMenuBar(menuBar); - m_inputWin = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 50), - wxRAISED_BORDER), - m_inputWin->SetBackgroundColour(*wxBLUE); + DoCreateInputWindow(Input_Custom); wxTextCtrl *headerText = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_READONLY); headerText->SetValue( " event key KeyCode mod UnicodeKey " - " RawKeyCode RawKeyFlags"); + " RawKeyCode RawKeyFlags Position"); - m_logText = new wxTextCtrl(this, wxID_ANY, "", + m_logText = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, - wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL); + wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH|wxHSCROLL); // set monospace font to have output in nice columns - wxFont font(10, wxFONTFAMILY_TELETYPE, + wxFont font(10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); headerText->SetFont(font); m_logText->SetFont(font); @@ -153,19 +234,29 @@ MyFrame::MyFrame(const wxString& title) Connect(ClearID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnClear)); - Connect(SkipID, wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(MyFrame::OnSkip)); + Connect(SkipHook, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnSkipHook)); + Connect(SkipDown, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnSkipDown)); - // connect event handlers for the blue input window - m_inputWin->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MyFrame::OnKeyDown), - NULL, this); - m_inputWin->Connect(wxEVT_KEY_UP, wxKeyEventHandler(MyFrame::OnKeyUp), - NULL, this); - m_inputWin->Connect(wxEVT_CHAR, wxKeyEventHandler(MyFrame::OnChar), - NULL, this); - m_inputWin->Connect(wxEVT_PAINT, - wxPaintEventHandler(MyFrame::OnPaintInputWin), - NULL, this); + Connect(IDInputCustom, IDInputText, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnInputWindowKind)); + + Connect(TestAccelA, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnTestAccelA)); + + Connect(TestAccelCtrlA, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnTestAccelCtrlA)); + + Connect(TestAccelEsc, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(MyFrame::OnTestAccelEsc)); + + // notice that we don't connect OnCharHook() to the input window, unlike + // the usual key events this one is propagated upwards + Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MyFrame::OnCharHook)); + + // status bar is useful for showing the menu items help strings + CreateStatusBar(); // and show itself (the frames, unlike simple controls, are not shown when // created initially) @@ -183,6 +274,62 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) wxOK | wxICON_INFORMATION, this); } +void MyFrame::DoCreateInputWindow(InputKind inputKind) +{ + wxWindow* const oldWin = m_inputWin; + + switch ( inputKind ) + { + case Input_Custom: + m_inputWin = new wxWindow(this, wxID_ANY, + wxDefaultPosition, wxSize(-1, 50), + wxRAISED_BORDER); + break; + + case Input_Entry: + m_inputWin = new wxTextCtrl(this, wxID_ANY, "Press keys here"); + break; + + case Input_Text: + m_inputWin = new wxTextCtrl(this, wxID_ANY, "Press keys here", + wxDefaultPosition, wxSize(-1, 50), + wxTE_MULTILINE); + break; + } + + m_inputWin->SetBackgroundColour(*wxBLUE); + m_inputWin->SetForegroundColour(*wxWHITE); + + // connect event handlers for the blue input window + m_inputWin->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MyFrame::OnKeyDown), + NULL, this); + m_inputWin->Connect(wxEVT_KEY_UP, wxKeyEventHandler(MyFrame::OnKeyUp), + NULL, this); + m_inputWin->Connect(wxEVT_CHAR, wxKeyEventHandler(MyFrame::OnChar), + NULL, this); + + if ( inputKind == Input_Custom ) + { + m_inputWin->Connect(wxEVT_PAINT, + wxPaintEventHandler(MyFrame::OnPaintInputWin), + NULL, this); + } + + if ( oldWin ) + { + GetSizer()->Replace(oldWin, m_inputWin); + Layout(); + delete oldWin; + } +} + +void MyFrame::OnInputWindowKind(wxCommandEvent& event) +{ + DoCreateInputWindow( + static_cast(event.GetId() - IDInputCustom) + ); +} + void MyFrame::OnPaintInputWin(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(m_inputWin); @@ -192,7 +339,7 @@ void MyFrame::OnPaintInputWin(wxPaintEvent& WXUNUSED(event)) font.SetPointSize(font.GetPointSize() + 2); dc.SetFont(font); - dc.DrawLabel("Press keys here", + dc.DrawLabel("Press keys here", m_inputWin->GetClientRect(), wxALIGN_CENTER); } @@ -203,7 +350,7 @@ const char* GetVirtualKeyCodeName(int keycode) switch ( keycode ) { #define WXK_(x) \ - case WXK_##x: return #x; + case WXK_##x: return #x; WXK_(BACK) WXK_(TAB) @@ -304,9 +451,16 @@ const char* GetVirtualKeyCodeName(int keycode) WXK_(NUMPAD_SUBTRACT) WXK_(NUMPAD_DECIMAL) WXK_(NUMPAD_DIVIDE) + + WXK_(WINDOWS_LEFT) + WXK_(WINDOWS_RIGHT) +#ifdef __WXOSX__ + WXK_(RAW_CONTROL) +#endif #undef WXK_ - default: - return NULL; + + default: + return NULL; } } @@ -317,22 +471,25 @@ wxString GetKeyName(const wxKeyEvent &event) const char* virt = GetVirtualKeyCodeName(keycode); if ( virt ) return virt; - if ( keycode > 0 && keycode < 27 ) + if ( keycode > 0 && keycode < 32 ) return wxString::Format("Ctrl-%c", (unsigned char)('A' + keycode - 1)); - if ( keycode >= 27 && keycode < 128 ) + if ( keycode >= 32 && keycode < 128 ) return wxString::Format("'%c'", (unsigned char)keycode); + #if wxUSE_UNICODE - return wxString::Format("'%c'", event.GetUnicodeKey()); -#else - return "unknown"; + int uc = event.GetUnicodeKey(); + if ( uc != WXK_NONE ) + return wxString::Format("'%c'", uc); #endif + + return "unknown"; } void MyFrame::LogEvent(const wxString& name, wxKeyEvent& event) { wxString msg; - // event key_name KeyCode modifiers Unicode raw_code raw_flags + // event key_name KeyCode modifiers Unicode raw_code raw_flags pos msg.Printf("%7s %15s %5d %c%c%c%c" #if wxUSE_UNICODE "%5d (U+%04x)" @@ -340,10 +497,11 @@ void MyFrame::LogEvent(const wxString& name, wxKeyEvent& event) " none " #endif #ifdef wxHAS_RAW_KEY_CODES - " %7lu 0x%lx" + " %7lu 0x%08lx" #else " not-set not-set" #endif + " (%5d,%5d)" "\n", name, GetKeyName(event), @@ -351,21 +509,20 @@ void MyFrame::LogEvent(const wxString& name, wxKeyEvent& event) event.ControlDown() ? 'C' : '-', event.AltDown() ? 'A' : '-', event.ShiftDown() ? 'S' : '-', - event.MetaDown() ? 'M' : '-', + event.MetaDown() ? 'M' : '-' #if wxUSE_UNICODE - event.GetUnicodeKey(), - event.GetUnicodeKey(), + , event.GetUnicodeKey() + , event.GetUnicodeKey() #endif #ifdef wxHAS_RAW_KEY_CODES - (unsigned long) event.GetRawKeyCode(), - (unsigned long) event.GetRawKeyFlags() + , (unsigned long) event.GetRawKeyCode() + , (unsigned long) event.GetRawKeyFlags() #endif + , event.GetX() + , event.GetY() ); m_logText->AppendText(msg); - - if ( m_skip ) - event.Skip(); }