| 1 | |
| 2 | import wx |
| 3 | import wx.lib.mixins.listctrl as listmix |
| 4 | |
| 5 | #---------------------------------------------------------------------- |
| 6 | |
| 7 | keyMap = { |
| 8 | wx.WXK_BACK : "WXK_BACK", |
| 9 | wx.WXK_TAB : "WXK_TAB", |
| 10 | wx.WXK_RETURN : "WXK_RETURN", |
| 11 | wx.WXK_ESCAPE : "WXK_ESCAPE", |
| 12 | wx.WXK_SPACE : "WXK_SPACE", |
| 13 | wx.WXK_DELETE : "WXK_DELETE", |
| 14 | wx.WXK_START : "WXK_START", |
| 15 | wx.WXK_LBUTTON : "WXK_LBUTTON", |
| 16 | wx.WXK_RBUTTON : "WXK_RBUTTON", |
| 17 | wx.WXK_CANCEL : "WXK_CANCEL", |
| 18 | wx.WXK_MBUTTON : "WXK_MBUTTON", |
| 19 | wx.WXK_CLEAR : "WXK_CLEAR", |
| 20 | wx.WXK_SHIFT : "WXK_SHIFT", |
| 21 | wx.WXK_ALT : "WXK_ALT", |
| 22 | wx.WXK_CONTROL : "WXK_CONTROL", |
| 23 | wx.WXK_MENU : "WXK_MENU", |
| 24 | wx.WXK_PAUSE : "WXK_PAUSE", |
| 25 | wx.WXK_CAPITAL : "WXK_CAPITAL", |
| 26 | #wx.WXK_PRIOR : "WXK_PRIOR", |
| 27 | #wx.WXK_NEXT : "WXK_NEXT", |
| 28 | wx.WXK_END : "WXK_END", |
| 29 | wx.WXK_HOME : "WXK_HOME", |
| 30 | wx.WXK_LEFT : "WXK_LEFT", |
| 31 | wx.WXK_UP : "WXK_UP", |
| 32 | wx.WXK_RIGHT : "WXK_RIGHT", |
| 33 | wx.WXK_DOWN : "WXK_DOWN", |
| 34 | wx.WXK_SELECT : "WXK_SELECT", |
| 35 | wx.WXK_PRINT : "WXK_PRINT", |
| 36 | wx.WXK_EXECUTE : "WXK_EXECUTE", |
| 37 | wx.WXK_SNAPSHOT : "WXK_SNAPSHOT", |
| 38 | wx.WXK_INSERT : "WXK_INSERT", |
| 39 | wx.WXK_HELP : "WXK_HELP", |
| 40 | wx.WXK_NUMPAD0 : "WXK_NUMPAD0", |
| 41 | wx.WXK_NUMPAD1 : "WXK_NUMPAD1", |
| 42 | wx.WXK_NUMPAD2 : "WXK_NUMPAD2", |
| 43 | wx.WXK_NUMPAD3 : "WXK_NUMPAD3", |
| 44 | wx.WXK_NUMPAD4 : "WXK_NUMPAD4", |
| 45 | wx.WXK_NUMPAD5 : "WXK_NUMPAD5", |
| 46 | wx.WXK_NUMPAD6 : "WXK_NUMPAD6", |
| 47 | wx.WXK_NUMPAD7 : "WXK_NUMPAD7", |
| 48 | wx.WXK_NUMPAD8 : "WXK_NUMPAD8", |
| 49 | wx.WXK_NUMPAD9 : "WXK_NUMPAD9", |
| 50 | wx.WXK_MULTIPLY : "WXK_MULTIPLY", |
| 51 | wx.WXK_ADD : "WXK_ADD", |
| 52 | wx.WXK_SEPARATOR : "WXK_SEPARATOR", |
| 53 | wx.WXK_SUBTRACT : "WXK_SUBTRACT", |
| 54 | wx.WXK_DECIMAL : "WXK_DECIMAL", |
| 55 | wx.WXK_DIVIDE : "WXK_DIVIDE", |
| 56 | wx.WXK_F1 : "WXK_F1", |
| 57 | wx.WXK_F2 : "WXK_F2", |
| 58 | wx.WXK_F3 : "WXK_F3", |
| 59 | wx.WXK_F4 : "WXK_F4", |
| 60 | wx.WXK_F5 : "WXK_F5", |
| 61 | wx.WXK_F6 : "WXK_F6", |
| 62 | wx.WXK_F7 : "WXK_F7", |
| 63 | wx.WXK_F8 : "WXK_F8", |
| 64 | wx.WXK_F9 : "WXK_F9", |
| 65 | wx.WXK_F10 : "WXK_F10", |
| 66 | wx.WXK_F11 : "WXK_F11", |
| 67 | wx.WXK_F12 : "WXK_F12", |
| 68 | wx.WXK_F13 : "WXK_F13", |
| 69 | wx.WXK_F14 : "WXK_F14", |
| 70 | wx.WXK_F15 : "WXK_F15", |
| 71 | wx.WXK_F16 : "WXK_F16", |
| 72 | wx.WXK_F17 : "WXK_F17", |
| 73 | wx.WXK_F18 : "WXK_F18", |
| 74 | wx.WXK_F19 : "WXK_F19", |
| 75 | wx.WXK_F20 : "WXK_F20", |
| 76 | wx.WXK_F21 : "WXK_F21", |
| 77 | wx.WXK_F22 : "WXK_F22", |
| 78 | wx.WXK_F23 : "WXK_F23", |
| 79 | wx.WXK_F24 : "WXK_F24", |
| 80 | wx.WXK_NUMLOCK : "WXK_NUMLOCK", |
| 81 | wx.WXK_SCROLL : "WXK_SCROLL", |
| 82 | wx.WXK_PAGEUP : "WXK_PAGEUP", |
| 83 | wx.WXK_PAGEDOWN : "WXK_PAGEDOWN", |
| 84 | wx.WXK_NUMPAD_SPACE : "WXK_NUMPAD_SPACE", |
| 85 | wx.WXK_NUMPAD_TAB : "WXK_NUMPAD_TAB", |
| 86 | wx.WXK_NUMPAD_ENTER : "WXK_NUMPAD_ENTER", |
| 87 | wx.WXK_NUMPAD_F1 : "WXK_NUMPAD_F1", |
| 88 | wx.WXK_NUMPAD_F2 : "WXK_NUMPAD_F2", |
| 89 | wx.WXK_NUMPAD_F3 : "WXK_NUMPAD_F3", |
| 90 | wx.WXK_NUMPAD_F4 : "WXK_NUMPAD_F4", |
| 91 | wx.WXK_NUMPAD_HOME : "WXK_NUMPAD_HOME", |
| 92 | wx.WXK_NUMPAD_LEFT : "WXK_NUMPAD_LEFT", |
| 93 | wx.WXK_NUMPAD_UP : "WXK_NUMPAD_UP", |
| 94 | wx.WXK_NUMPAD_RIGHT : "WXK_NUMPAD_RIGHT", |
| 95 | wx.WXK_NUMPAD_DOWN : "WXK_NUMPAD_DOWN", |
| 96 | #wx.WXK_NUMPAD_PRIOR : "WXK_NUMPAD_PRIOR", |
| 97 | wx.WXK_NUMPAD_PAGEUP : "WXK_NUMPAD_PAGEUP", |
| 98 | #wx.WXK_NUMPAD_NEXT : "WXK_NUMPAD_NEXT", |
| 99 | wx.WXK_NUMPAD_PAGEDOWN : "WXK_NUMPAD_PAGEDOWN", |
| 100 | wx.WXK_NUMPAD_END : "WXK_NUMPAD_END", |
| 101 | wx.WXK_NUMPAD_BEGIN : "WXK_NUMPAD_BEGIN", |
| 102 | wx.WXK_NUMPAD_INSERT : "WXK_NUMPAD_INSERT", |
| 103 | wx.WXK_NUMPAD_DELETE : "WXK_NUMPAD_DELETE", |
| 104 | wx.WXK_NUMPAD_EQUAL : "WXK_NUMPAD_EQUAL", |
| 105 | wx.WXK_NUMPAD_MULTIPLY : "WXK_NUMPAD_MULTIPLY", |
| 106 | wx.WXK_NUMPAD_ADD : "WXK_NUMPAD_ADD", |
| 107 | wx.WXK_NUMPAD_SEPARATOR : "WXK_NUMPAD_SEPARATOR", |
| 108 | wx.WXK_NUMPAD_SUBTRACT : "WXK_NUMPAD_SUBTRACT", |
| 109 | wx.WXK_NUMPAD_DECIMAL : "WXK_NUMPAD_DECIMAL", |
| 110 | wx.WXK_NUMPAD_DIVIDE : "WXK_NUMPAD_DIVIDE", |
| 111 | } |
| 112 | |
| 113 | |
| 114 | #---------------------------------------------------------------------- |
| 115 | |
| 116 | class KeySink(wx.Window): |
| 117 | def __init__(self, parent): |
| 118 | wx.Window.__init__(self, parent, -1, style=wx.WANTS_CHARS |
| 119 | #| wx.RAISED_BORDER |
| 120 | #| wx.SUNKEN_BORDER |
| 121 | , name="sink") |
| 122 | |
| 123 | self.SetBackgroundColour(wx.BLUE) |
| 124 | self.haveFocus = False |
| 125 | self.callSkip = True |
| 126 | self.logKeyDn = True |
| 127 | self.logKeyUp = True |
| 128 | self.logChar = True |
| 129 | |
| 130 | self.Bind(wx.EVT_PAINT, self.OnPaint) |
| 131 | self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) |
| 132 | self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) |
| 133 | self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse) |
| 134 | |
| 135 | self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) |
| 136 | self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) |
| 137 | self.Bind(wx.EVT_CHAR, self.OnChar) |
| 138 | |
| 139 | |
| 140 | def SetCallSkip(self, skip): |
| 141 | self.callSkip = skip |
| 142 | |
| 143 | def SetLogKeyUp(self, val): |
| 144 | self.logKeyUp = val |
| 145 | |
| 146 | def SetLogKeyDn(self, val): |
| 147 | self.logKeyDn = val |
| 148 | |
| 149 | def SetLogChar(self, val): |
| 150 | self.logChar = val |
| 151 | |
| 152 | |
| 153 | def OnPaint(self, evt): |
| 154 | dc = wx.PaintDC(self) |
| 155 | rect = self.GetClientRect() |
| 156 | dc.SetTextForeground(wx.WHITE) |
| 157 | dc.DrawLabel("Click here and then press some keys", |
| 158 | rect, wx.ALIGN_CENTER | wx.ALIGN_TOP) |
| 159 | if self.haveFocus: |
| 160 | dc.SetTextForeground(wx.GREEN) |
| 161 | dc.DrawLabel("Have Focus", rect, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM) |
| 162 | else: |
| 163 | dc.SetTextForeground(wx.RED) |
| 164 | dc.DrawLabel("Need Focus!", rect, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM) |
| 165 | |
| 166 | |
| 167 | def OnSetFocus(self, evt): |
| 168 | self.haveFocus = True |
| 169 | self.Refresh() |
| 170 | |
| 171 | def OnKillFocus(self, evt): |
| 172 | self.haveFocus = False |
| 173 | self.Refresh() |
| 174 | |
| 175 | def OnMouse(self, evt): |
| 176 | if evt.ButtonDown(): |
| 177 | self.SetFocus() |
| 178 | |
| 179 | |
| 180 | def OnKeyDown(self, evt): |
| 181 | if self.logKeyDn: |
| 182 | self.GetParent().keylog.LogKeyEvent("KeyDown", evt) |
| 183 | if self.callSkip: |
| 184 | evt.Skip() |
| 185 | |
| 186 | def OnKeyUp(self, evt): |
| 187 | if self.logKeyUp: |
| 188 | self.GetParent().keylog.LogKeyEvent("KeyUp", evt) |
| 189 | if self.callSkip: |
| 190 | evt.Skip() |
| 191 | |
| 192 | def OnChar(self, evt): |
| 193 | if self.logChar: |
| 194 | self.GetParent().keylog.LogKeyEvent("Char", evt) |
| 195 | |
| 196 | |
| 197 | #---------------------------------------------------------------------- |
| 198 | |
| 199 | class KeyLog(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): |
| 200 | colHeaders = [ "Event Type", |
| 201 | "Key Name", |
| 202 | "Key Code", |
| 203 | "Modifiers", |
| 204 | "Unicode", |
| 205 | "RawKeyCode", |
| 206 | "RawKeyFlags", |
| 207 | ] |
| 208 | |
| 209 | def __init__(self, parent): |
| 210 | wx.ListCtrl.__init__(self, parent, -1, |
| 211 | style = wx.LC_REPORT|wx.LC_VRULES|wx.LC_HRULES) |
| 212 | listmix.ListCtrlAutoWidthMixin.__init__(self) |
| 213 | |
| 214 | for idx, header in enumerate(self.colHeaders): |
| 215 | self.InsertColumn(idx, header) |
| 216 | idx += 1 |
| 217 | self.InsertColumn(idx, "") |
| 218 | |
| 219 | for x in range(idx): |
| 220 | self.SetColumnWidth(x, wx.LIST_AUTOSIZE_USEHEADER) |
| 221 | |
| 222 | self.SetColumnWidth(1, 125) |
| 223 | |
| 224 | |
| 225 | def LogKeyEvent(self, evType, evt): |
| 226 | keycode = evt.GetKeyCode() |
| 227 | keyname = keyMap.get(keycode, None) |
| 228 | if keyname is None: |
| 229 | if "unicode" in wx.PlatformInfo: |
| 230 | keycode = evt.GetUnicodeKey() |
| 231 | if keycode <= 127: |
| 232 | keycode = evt.GetKeyCode() |
| 233 | keyname = "\"" + unichr(evt.GetUnicodeKey()) + "\"" |
| 234 | if keycode < 27: |
| 235 | keyname = "Ctrl-%s" % chr(ord('A') + keycode-1) |
| 236 | |
| 237 | elif keycode < 256: |
| 238 | if keycode == 0: |
| 239 | keyname = "NUL" |
| 240 | elif keycode < 27: |
| 241 | keyname = "Ctrl-%s" % chr(ord('A') + keycode-1) |
| 242 | else: |
| 243 | keyname = "\"%s\"" % chr(keycode) |
| 244 | else: |
| 245 | keyname = "unknown (%s)" % keycode |
| 246 | |
| 247 | modifiers = "" |
| 248 | for mod, ch in [(evt.ControlDown(), 'C'), |
| 249 | (evt.AltDown(), 'A'), |
| 250 | (evt.ShiftDown(), 'S'), |
| 251 | (evt.MetaDown(), 'M')]: |
| 252 | if mod: |
| 253 | modifiers += ch |
| 254 | else: |
| 255 | modifiers += '-' |
| 256 | |
| 257 | id = self.InsertStringItem(self.GetItemCount(), evType) |
| 258 | self.SetStringItem(id, 1, keyname) |
| 259 | self.SetStringItem(id, 2, str(keycode)) |
| 260 | self.SetStringItem(id, 3, modifiers) |
| 261 | self.SetStringItem(id, 4, str(evt.GetUnicodeKey())) |
| 262 | self.SetStringItem(id, 5, str(evt.GetRawKeyCode())) |
| 263 | self.SetStringItem(id, 6, str(evt.GetRawKeyFlags())) |
| 264 | |
| 265 | #print ( id, evType, keyname, str(keycode), modifiers, str(evt.GetRawKeyCode()), str(evt.GetRawKeyFlags())) |
| 266 | |
| 267 | self.EnsureVisible(id) |
| 268 | |
| 269 | |
| 270 | def ClearLog(self): |
| 271 | self.DeleteAllItems() |
| 272 | |
| 273 | def CopyLog(self): |
| 274 | # build a newline and tab delimited string to put into the clipboard |
| 275 | if "unicode" in wx.PlatformInfo: |
| 276 | st = u"" |
| 277 | else: |
| 278 | st = "" |
| 279 | for h in self.colHeaders: |
| 280 | st += h + "\t" |
| 281 | st += "\n" |
| 282 | |
| 283 | for idx in range(self.GetItemCount()): |
| 284 | for col in range(self.GetColumnCount()): |
| 285 | item = self.GetItem(idx, col) |
| 286 | st += item.GetText() + "\t" |
| 287 | st += "\n" |
| 288 | |
| 289 | data = wx.TextDataObject() |
| 290 | data.SetText(st) |
| 291 | if wx.TheClipboard.Open(): |
| 292 | wx.TheClipboard.SetData(data) |
| 293 | wx.TheClipboard.Close() |
| 294 | else: |
| 295 | wx.MessageBox("Unable to open the clipboard", "Error") |
| 296 | |
| 297 | |
| 298 | |
| 299 | |
| 300 | #---------------------------------------------------------------------- |
| 301 | |
| 302 | |
| 303 | class TestPanel(wx.Panel): |
| 304 | def __init__(self, parent, log): |
| 305 | self.log = log |
| 306 | wx.Panel.__init__(self, parent, -1, style=0) |
| 307 | self.keysink = KeySink(self) |
| 308 | self.keysink.SetMinSize((100, 65)) |
| 309 | self.keylog = KeyLog(self) |
| 310 | |
| 311 | btn = wx.Button(self, -1, "Clear", style=wx.BU_EXACTFIT) |
| 312 | self.Bind(wx.EVT_BUTTON, self.OnClearBtn, btn) |
| 313 | btn.SetToolTipString( |
| 314 | "Clear the items from the log window") |
| 315 | |
| 316 | btn2 = wx.Button(self, -1, "Copy", style=wx.BU_EXACTFIT) |
| 317 | self.Bind(wx.EVT_BUTTON, self.OnCopyBtn, btn2) |
| 318 | btn2.SetToolTipString( |
| 319 | "Copy the contents of the log window to the clipboard") |
| 320 | |
| 321 | cb1 = wx.CheckBox(self, -1, "Call evt.Skip in Key* events") |
| 322 | self.Bind(wx.EVT_CHECKBOX, self.OnSkipCB, cb1) |
| 323 | cb1.SetValue(True) |
| 324 | |
| 325 | cb2 = wx.CheckBox(self, -1, "KEY_UP") |
| 326 | self.Bind(wx.EVT_CHECKBOX, self.OnKeyUpCB, cb2) |
| 327 | cb2.SetValue(True) |
| 328 | |
| 329 | cb3 = wx.CheckBox(self, -1, "KEY_DOWN") |
| 330 | self.Bind(wx.EVT_CHECKBOX, self.OnKeyDnCB, cb3) |
| 331 | cb3.SetValue(True) |
| 332 | |
| 333 | cb4 = wx.CheckBox(self, -1, "CHAR") |
| 334 | self.Bind(wx.EVT_CHECKBOX, self.OnCharCB, cb4) |
| 335 | cb4.SetValue(True) |
| 336 | |
| 337 | buttons = wx.BoxSizer(wx.HORIZONTAL) |
| 338 | buttons.Add(btn, 0, wx.ALL, 4) |
| 339 | buttons.Add(btn2, 0, wx.ALL, 4) |
| 340 | buttons.Add(cb1, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 6) |
| 341 | buttons.Add(cb2, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 6) |
| 342 | buttons.Add(cb3, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 6) |
| 343 | buttons.Add(cb4, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 6) |
| 344 | |
| 345 | sizer = wx.BoxSizer(wx.VERTICAL) |
| 346 | sizer.Add(self.keysink, 0, wx.GROW) |
| 347 | sizer.Add(buttons) |
| 348 | sizer.Add(self.keylog, 1, wx.GROW) |
| 349 | |
| 350 | self.SetSizer(sizer) |
| 351 | |
| 352 | |
| 353 | def OnClearBtn(self, evt): |
| 354 | self.keylog.ClearLog() |
| 355 | |
| 356 | def OnCopyBtn(self, evt): |
| 357 | self.keylog.CopyLog() |
| 358 | |
| 359 | def OnSkipCB(self, evt): |
| 360 | self.keysink.SetCallSkip(evt.GetInt()) |
| 361 | |
| 362 | def OnKeyUpCB(self, evt): |
| 363 | self.keysink.SetLogKeyUp(evt.GetInt()) |
| 364 | |
| 365 | def OnKeyDnCB(self, evt): |
| 366 | self.keysink.SetLogKeyDn(evt.GetInt()) |
| 367 | |
| 368 | def OnCharCB(self, evt): |
| 369 | self.keysink.SetLogChar(evt.GetInt()) |
| 370 | |
| 371 | |
| 372 | #---------------------------------------------------------------------- |
| 373 | |
| 374 | def runTest(frame, nb, log): |
| 375 | win = TestPanel(nb, log) |
| 376 | return win |
| 377 | |
| 378 | #---------------------------------------------------------------------- |
| 379 | |
| 380 | |
| 381 | |
| 382 | overview = """<html><body> |
| 383 | <h2><center>wxKeyEvents</center></h2> |
| 384 | |
| 385 | This demo simply catches all key events and prints info about them. |
| 386 | It is meant to be used as a compatibility test for cross platform work. |
| 387 | |
| 388 | </body></html> |
| 389 | """ |
| 390 | |
| 391 | |
| 392 | |
| 393 | if __name__ == '__main__': |
| 394 | import sys,os |
| 395 | import run |
| 396 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |
| 397 | |