#include "wx/wx.h"
#endif
-#ifndef __WXMSW__
+#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
{
// 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;
};
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title),
m_inputWin(NULL),
- m_skip(true)
+ m_skipHook(true),
+ m_skipDown(true)
{
SetIcon(wxICON(sample));
- // IDs for menu items
- enum
- {
- QuitID = wxID_EXIT,
- ClearID = wxID_CLEAR,
- SkipID = 100,
- };
-
// create a menu bar
wxMenu *menuFile = new wxMenu;
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();
// ... 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, "",
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,
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)
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<InputKind>(event.GetId() - IDInputCustom)
+ );
+}
+
void MyFrame::OnPaintInputWin(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(m_inputWin);
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;
}
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)"
" 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),
, (unsigned long) event.GetRawKeyCode()
, (unsigned long) event.GetRawKeyFlags()
#endif
+ , event.GetX()
+ , event.GetY()
);
m_logText->AppendText(msg);
-
- if ( m_skip )
- event.Skip();
}