From 4ce81a75efb34de9f01fe3c7b9ffecb03293b1c3 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Thu, 14 Jan 1999 11:23:37 +0000
Subject: [PATCH] Added OnKeyDown, OnKeyUp.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1404 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/clipbrd.tex  | 22 ++++-----
 docs/latex/wx/keyevent.tex | 12 ++++-
 docs/latex/wx/window.tex   | 66 ++++++++++++++++++++++++++-
 docs/motif/todo.txt        |  4 +-
 include/wx/event.h         | 10 ++--
 include/wx/motif/window.h  |  3 ++
 include/wx/msw/clipbrd.h   | 18 +++++++-
 include/wx/msw/window.h    |  4 ++
 include/wx/stubs/window.h  |  2 +
 src/common/image.cpp       |  2 -
 src/motif/window.cpp       | 14 ++++++
 src/msw/clipbrd.cpp        | 30 ++++++++++++
 src/msw/window.cpp         | 93 ++++++++++++++++++++++++++++++++++++++
 src/stubs/window.cpp       | 15 ++++++
 14 files changed, 274 insertions(+), 21 deletions(-)

diff --git a/docs/latex/wx/clipbrd.tex b/docs/latex/wx/clipbrd.tex
index c8cefc54b9..a97e1ed478 100644
--- a/docs/latex/wx/clipbrd.tex
+++ b/docs/latex/wx/clipbrd.tex
@@ -3,8 +3,9 @@
 A class for manipulating the clipboard. Note that this is not compatible with the
 clipboard class from wxWindows 1.xx, which has the same name but a different implementation.
 
-To use the clipboard, construct a wxClipboard object on the stack and 
-call \helpref{wxClipboard::Open}{wxclipboardopen}. If this operation returns TRUE, you
+To use the clipboard, you call member functions of the global {\bf wxTheClipboard} object.
+
+Call \helpref{wxClipboard::Open}{wxclipboardopen} to get ownership of the clipboard. If this operation returns TRUE, you
 now own the clipboard. Call \helpref{wxClipboard::SetData}{wxclipboardsetdata} to put data
 on the clipboard (one or more times), or \helpref{wxClipboard::GetData}{wxclipboardgetdata} to
 retrieve data from the clipboard. Call \helpref{wxClipboard::Close}{wxclipboardclose} to close
@@ -13,22 +14,21 @@ the clipboard and relinquish ownership. You should keep the clipboard open only
 For example:
 
 \begin{verbatim}
-  wxClipboard clipboard;
-
   // Write some text to the clipboard
-  if (clipboard.Open())
+  if (wxTheClipboard->Open())
   {
-    wxTextDataObject object("Some text");
-    clipboard.SetData(& object);
-    clipboard.Close();
+    // This object is held by the clipboard, so do not delete it in the app.
+    wxTextDataObject* object = new wxTextDataObject("Some text");
+    wxTheClipboard->SetData(& object);
+    wxTheClipboard->Close();
   }
 
   // Read some text
-  if (clipboard.Open() && clipboard.IsSupportedFormat(wxDF_TEXT))
+  if (wxTheClipboard->Open() && wxTheClipboard->IsSupportedFormat(wxDF_TEXT))
   {
     wxTextDataObject object;
-    clipboard.GetData(& object);
-    clipboard.Close();
+    wxTheClipboard->GetData(& object);
+    wxTheClipboard->Close();
 
     wxMessageBox(object.GetText());
   }
diff --git a/docs/latex/wx/keyevent.tex b/docs/latex/wx/keyevent.tex
index 53a2d5b7db..96919d7cff 100644
--- a/docs/latex/wx/keyevent.tex
+++ b/docs/latex/wx/keyevent.tex
@@ -1,6 +1,6 @@
 \section{\class{wxKeyEvent}}\label{wxkeyevent}
 
-This event class contains information about keypress (character) events. See \helpref{wxWindow::OnChar}{wxwindowonchar}.
+This event class contains information about keypress (character) events.
 
 \wxheading{Derived from}
 
@@ -13,10 +13,20 @@ functions that take a wxKeyEvent argument.
 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_CHAR(func)}}{Process a wxEVT\_CHAR event (an ASCII key has been pressed).}
+\twocolitem{{\bf EVT\_KEY\_DOWN(func)}}{Process a wxEVT\_KEY\_DOWN event (any key has been pressed).}
+\twocolitem{{\bf EVT\_KEY\_UP(func)}}{Process a wxEVT\_KEY\_UP event (any key has been released).}
 \twocolitem{{\bf EVT\_CHAR(func)}}{Process a wxEVT\_CHAR event.}
 \twocolitem{{\bf EVT\_CHAR\_HOOK(func)}}{Process a wxEVT\_CHAR\_HOOK event.}
 \end{twocollist}%
 
+\wxheading{See also}
+
+\helpref{wxWindow::OnChar}{wxwindowonchar}, 
+\helpref{wxWindow::OnCharHook}{wxwindowoncharhook}, 
+\helpref{wxWindow::OnKeyDown}{wxwindowonkeydown}, 
+\helpref{wxWindow::OnKeyUp}{wxwindowonkeyup}
+
 \latexignore{\rtfignore{\wxheading{Members}}}
 
 \membersection{wxKeyEvent::m\_altDown}
diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex
index 88f0808095..011a13f2fa 100644
--- a/docs/latex/wx/window.tex
+++ b/docs/latex/wx/window.tex
@@ -807,7 +807,7 @@ otherwise it returns FALSE (it is being deactivated).
 
 \func{void}{OnChar}{\param{wxKeyEvent\&}{ event}}
 
-Called when the user has pressed a key.
+Called when the user has pressed a key, which has been translated into an ASCII value.
 
 \wxheading{Parameters}
 
@@ -823,10 +823,15 @@ default function to achieve default keypress functionality.
 Note that the ASCII values do not have explicit key codes: they are passed as ASCII
 values.
 
+Note that not all keypresses can be intercepted this way. If you wish to intercept special
+keys, such as shift, control, and function keys, then you will need to use \helpref{wxWindow::OnKeyDown}{wxwindowonkeydown} or 
+\helpref{wxWindow::OnKeyUp}{wxwindowonkeyup}.
+
 Most, but not all, windows allow keypresses to be intercepted.
 
 \wxheading{See also}
 
+\helpref{wxWindow::OnKeyDown}{wxwindowonkeydown}, \helpref{wxWindow::OnKeyUp}{wxwindowonkeyup},\rtfsp
 \helpref{wxKeyEvent}{wxkeyevent}, \helpref{wxWindow::OnCharHook}{wxwindowoncharhook},\rtfsp
 \helpref{Event handling overview}{eventhandlingoverview}
 
@@ -999,6 +1004,65 @@ To intercept this event, use the EVT\_ERASE\_BACKGROUND macro in an event table
 
 \helpref{wxEraseEvent}{wxeraseevent}, \helpref{Event handling overview}{eventhandlingoverview}
 
+\membersection{wxWindow::OnKeyDown}\label{wxwindowonkeydown}
+
+\func{void}{OnKeyDown}{\param{wxKeyEvent\&}{ event}}
+
+Called when the user has pressed a key, before it is translated into an ASCII value using other
+modifier keys that might be pressed at the same time.
+
+\wxheading{Parameters}
+
+\docparam{event}{Object containing keypress information. See \helpref{wxKeyEvent}{wxkeyevent} for
+details about this class.}
+
+\wxheading{Remarks}
+
+This member function is called in response to a key down event. To intercept this event,
+use the EVT\_KEY\_DOWN macro in an event table definition. Your {\bf OnKeyDown} handler may call this
+default function to achieve default keypress functionality.
+
+Note that not all keypresses can be intercepted this way. If you wish to intercept special
+keys, such as shift, control, and function keys, then you will need to use \helpref{wxWindow::OnKeyDown}{wxwindowonkeydown} or 
+\helpref{wxWindow::OnKeyUp}{wxwindowonkeyup}.
+
+Most, but not all, windows allow keypresses to be intercepted.
+
+\wxheading{See also}
+
+\helpref{wxWindow::OnChar}{wxwindowonchar}, \helpref{wxWindow::OnKeyUp}{wxwindowonkeyup},\rtfsp
+\helpref{wxKeyEvent}{wxkeyevent}, \helpref{wxWindow::OnCharHook}{wxwindowoncharhook},\rtfsp
+\helpref{Event handling overview}{eventhandlingoverview}
+
+\membersection{wxWindow::OnKeyUp}\label{wxwindowonkeyup}
+
+\func{void}{OnKeyUp}{\param{wxKeyEvent\&}{ event}}
+
+Called when the user has released a key.
+
+\wxheading{Parameters}
+
+\docparam{event}{Object containing keypress information. See \helpref{wxKeyEvent}{wxkeyevent} for
+details about this class.}
+
+\wxheading{Remarks}
+
+This member function is called in response to a key up event. To intercept this event,
+use the EVT\_KEY\_UP macro in an event table definition. Your {\bf OnKeyUp} handler may call this
+default function to achieve default keypress functionality.
+
+Note that not all keypresses can be intercepted this way. If you wish to intercept special
+keys, such as shift, control, and function keys, then you will need to use \helpref{wxWindow::OnKeyDown}{wxwindowonkeydown} or 
+\helpref{wxWindow::OnKeyUp}{wxwindowonkeyup}.
+
+Most, but not all, windows allow key up events to be intercepted.
+
+\wxheading{See also}
+
+\helpref{wxWindow::OnChar}{wxwindowonchar}, \helpref{wxWindow::OnKeyDown}{wxwindowonkeydown},\rtfsp
+\helpref{wxKeyEvent}{wxkeyevent}, \helpref{wxWindow::OnCharHook}{wxwindowoncharhook},\rtfsp
+\helpref{Event handling overview}{eventhandlingoverview}
+
 \membersection{wxWindow::OnKillFocus}\label{wxwindowonkillfocus}
 
 \func{void}{OnKillFocus}{\param{wxFocusEvent\& }{event}}
diff --git a/docs/motif/todo.txt b/docs/motif/todo.txt
index dfe385f197..34f4ed94e7 100644
--- a/docs/motif/todo.txt
+++ b/docs/motif/todo.txt
@@ -41,10 +41,10 @@ High Priority
 
 - Get wxGLCanvas from 1.68 working.
 
-- Implement missing wxImage functions for Motif.
-
 - wxClipboard
 
+- EVT_KEY_DOWN, EVT_KEY_UP events.
+
 Low Priority
 ------------
 
diff --git a/include/wx/event.h b/include/wx/event.h
index befa415c1d..8defe804d3 100644
--- a/include/wx/event.h
+++ b/include/wx/event.h
@@ -85,7 +85,10 @@ const wxEventType wxEVT_NC_RIGHT_DCLICK =                   wxEVT_FIRST + 211;
 
 /* Character input event type  */
 const wxEventType wxEVT_CHAR =                              wxEVT_FIRST + 212;
-const wxEventType wxEVT_NAVIGATION_KEY =                    wxEVT_FIRST + 213;
+const wxEventType wxEVT_CHAR_HOOK =                         wxEVT_FIRST + 213;
+const wxEventType wxEVT_NAVIGATION_KEY =                    wxEVT_FIRST + 214;
+const wxEventType wxEVT_KEY_DOWN =                          wxEVT_FIRST + 215;
+const wxEventType wxEVT_KEY_UP =                            wxEVT_FIRST + 216;
 
  /*
   * Scrollbar event identifiers
@@ -105,8 +108,6 @@ const wxEventType wxEVT_END_SESSION =                       wxEVT_FIRST + 403;
 const wxEventType wxEVT_QUERY_END_SESSION =                 wxEVT_FIRST + 404;
 const wxEventType wxEVT_ACTIVATE_APP =                      wxEVT_FIRST + 405;
 const wxEventType wxEVT_POWER =                             wxEVT_FIRST + 406;
-const wxEventType wxEVT_CHAR_HOOK =                         wxEVT_FIRST + 407;
-const wxEventType wxEVT_KEY_UP =                            wxEVT_FIRST + 408;
 const wxEventType wxEVT_ACTIVATE =                          wxEVT_FIRST + 409;
 const wxEventType wxEVT_CREATE =                            wxEVT_FIRST + 410;
 const wxEventType wxEVT_DESTROY =                           wxEVT_FIRST + 411;
@@ -537,6 +538,7 @@ public:
 /*
  wxEVT_CHAR
  wxEVT_CHAR_HOOK
+ wxEVT_KEY_DOWN
  wxEVT_KEY_UP
  */
 
@@ -1172,6 +1174,8 @@ const wxEventTableEntry theClass::sm_eventTableEntries[] = { \
 #define EVT_PAINT(func)  { wxEVT_PAINT, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxPaintEventFunction) & func, (wxObject *) NULL },
 #define EVT_ERASE_BACKGROUND(func)  { wxEVT_ERASE_BACKGROUND, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxEraseEventFunction) & func, (wxObject *) NULL },
 #define EVT_CHAR(func)  { wxEVT_CHAR, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL },
+#define EVT_KEY_DOWN(func)  { wxEVT_KEY_DOWN, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL },
+#define EVT_KEY_UP(func)  { wxEVT_KEY_UP, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL },
 #define EVT_CHAR_HOOK(func)  { wxEVT_CHAR_HOOK, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, NULL },
 #define EVT_MENU_HIGHLIGHT(id, func)  { wxEVT_MENU_HIGHLIGHT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxMenuEventFunction) & func, (wxObject *) NULL },
 #define EVT_MENU_HIGHLIGHT_ALL(func)  { wxEVT_MENU_HIGHLIGHT, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxMenuEventFunction) & func, (wxObject *) NULL },
diff --git a/include/wx/motif/window.h b/include/wx/motif/window.h
index daa7e42b93..53dfc0511f 100644
--- a/include/wx/motif/window.h
+++ b/include/wx/motif/window.h
@@ -416,6 +416,9 @@ public:
 
   void OnEraseBackground(wxEraseEvent& event);
   void OnChar(wxKeyEvent& event);
+  void OnKeyDown(wxKeyEvent& event);
+  void OnKeyUp(wxKeyEvent& event);
+  void OnChar(wxKeyEvent& event);
   void OnPaint(wxPaintEvent& event);
   void OnIdle(wxIdleEvent& event);
 
diff --git a/include/wx/msw/clipbrd.h b/include/wx/msw/clipbrd.h
index eec3bbdd7c..9849af42eb 100644
--- a/include/wx/msw/clipbrd.h
+++ b/include/wx/msw/clipbrd.h
@@ -22,6 +22,7 @@
 #if wxUSE_CLIPBOARD
 
 #include "wx/list.h"
+#include "wx/module.h"
 
 // These functions superceded by wxClipboard, but retained in order to implement
 // wxClipboard, and for compatibility.
@@ -72,10 +73,25 @@ public:
  // implementation 
  
   bool              m_open;
+  wxList            m_data;
 };
 
 /* The clipboard */
-// WXDLLEXPORT_DATA(extern wxClipboard*) wxTheClipboard;
+WXDLLEXPORT_DATA(extern wxClipboard*) wxTheClipboard;
+
+//-----------------------------------------------------------------------------
+// wxClipboardModule
+//-----------------------------------------------------------------------------
+
+class wxClipboardModule: public wxModule
+{
+  DECLARE_DYNAMIC_CLASS(wxClipboardModule)
+  
+public:
+    wxClipboardModule() {}
+    bool OnInit();
+    void OnExit();
+};
 
 #endif // wxUSE_CLIPBOARD
 #endif
diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h
index 21d27e908b..ce6e781f84 100644
--- a/include/wx/msw/window.h
+++ b/include/wx/msw/window.h
@@ -454,6 +454,8 @@ public:
 
   void OnEraseBackground(wxEraseEvent& event);
   void OnChar(wxKeyEvent& event);
+  void OnKeyDown(wxKeyEvent& event);
+  void OnKeyUp(wxKeyEvent& event);
   void OnPaint(wxPaintEvent& event);
   void OnIdle(wxIdleEvent& event);
 
@@ -612,6 +614,8 @@ public:
   virtual void MSWOnMouseLeave(int x, int y, WXUINT flags);
 
   virtual void MSWOnChar(WXWORD wParam, WXLPARAM lParam, bool isASCII = FALSE);
+  virtual void MSWOnKeyDown(WXWORD wParam, WXLPARAM lParam, bool isASCII = FALSE);
+  virtual void MSWOnKeyUp(WXWORD wParam, WXLPARAM lParam, bool isASCII = FALSE);
 
   virtual bool MSWOnActivate(int flag, bool minimized, WXHWND activate);
   virtual long MSWOnMDIActivate(long flag, WXHWND activate, WXHWND deactivate);
diff --git a/include/wx/stubs/window.h b/include/wx/stubs/window.h
index 75809c01b1..bf0b03db9e 100644
--- a/include/wx/stubs/window.h
+++ b/include/wx/stubs/window.h
@@ -390,6 +390,8 @@ public:
 
   void OnEraseBackground(wxEraseEvent& event);
   void OnChar(wxKeyEvent& event);
+  void OnKeyDown(wxKeyEvent& event);
+  void OnKeyUp(wxKeyEvent& event);
   void OnPaint(wxPaintEvent& event);
   void OnIdle(wxIdleEvent& event);
 
diff --git a/src/common/image.cpp b/src/common/image.cpp
index a7d34cce08..01921b677a 100644
--- a/src/common/image.cpp
+++ b/src/common/image.cpp
@@ -1700,8 +1700,6 @@ wxImage::wxImage( const wxBitmap &bitmap )
 
 #endif
 
-// TODO
-
 #ifdef __WXMOTIF__
 
 #include <Xm/Xm.h>
diff --git a/src/motif/window.cpp b/src/motif/window.cpp
index 1d78e7a52a..09f18c717a 100644
--- a/src/motif/window.cpp
+++ b/src/motif/window.cpp
@@ -70,6 +70,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
 
 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
   EVT_CHAR(wxWindow::OnChar)
+  EVT_KEY_DOWN(wxWindow::OnKeyDown)
+  EVT_KEY_UP(wxWindow::OnKeyUp)
   EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
   EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
   EVT_INIT_DIALOG(wxWindow::OnInitDialog)
@@ -1472,6 +1474,7 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
 
 void wxWindow::OnChar(wxKeyEvent& event)
 {
+/* ??
     if ( event.KeyCode() == WXK_TAB ) {
         // propagate the TABs to the parent - it's up to it to decide what
         // to do with it
@@ -1480,6 +1483,17 @@ void wxWindow::OnChar(wxKeyEvent& event)
                 return;
         }
     }
+*/
+}
+
+void wxWindow::OnKeyDown(wxKeyEvent& event)
+{
+    Default();
+}
+
+void wxWindow::OnKeyUp(wxKeyEvent& event)
+{
+    Default();
 }
 
 void wxWindow::OnPaint(wxPaintEvent& event)
diff --git a/src/msw/clipbrd.cpp b/src/msw/clipbrd.cpp
index 4ea1d85875..5a38cb9f60 100644
--- a/src/msw/clipbrd.cpp
+++ b/src/msw/clipbrd.cpp
@@ -333,6 +333,8 @@ bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName, int max
 
 IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
 
+wxClipboard* wxTheClipboard = (wxClipboard*) NULL;
+
 wxClipboard::wxClipboard()
 {
     m_open = FALSE;
@@ -345,6 +347,14 @@ wxClipboard::~wxClipboard()
 
 void wxClipboard::Clear()
 {
+    wxNode* node = m_data.First();
+    while (node)
+    {
+        wxDataObject* data = (wxDataObject*) node->Data();
+        delete data;
+        node = node->Next();
+    }
+    m_data.Clear();
 }
 
 bool wxClipboard::Open()
@@ -479,4 +489,24 @@ bool wxClipboard::GetData( wxDataObject *data )
 #endif
 }
 
+//-----------------------------------------------------------------------------
+// wxClipboardModule
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
+
+bool wxClipboardModule::OnInit()
+{
+    wxTheClipboard = new wxClipboard();
+  
+    return TRUE;
+}
+
+void wxClipboardModule::OnExit()
+{
+    if (wxTheClipboard) delete wxTheClipboard;
+    wxTheClipboard = (wxClipboard*) NULL;
+}
+
 #endif // wxUSE_CLIPBOARD
+
diff --git a/src/msw/window.cpp b/src/msw/window.cpp
index f8b44aa487..9d1f5e24e1 100644
--- a/src/msw/window.cpp
+++ b/src/msw/window.cpp
@@ -100,6 +100,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
 
 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
     EVT_CHAR(wxWindow::OnChar)
+    EVT_KEY_DOWN(wxWindow::OnKeyDown)
+    EVT_KEY_UP(wxWindow::OnKeyUp)
     EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
     EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
     EVT_INIT_DIALOG(wxWindow::OnInitDialog)
@@ -1161,6 +1163,9 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
         }
 
     case WM_KEYDOWN:
+    {
+        MSWOnKeyDown((WORD) wParam, lParam);
+#if 0
         // we consider these message "not interesting"
         if ( wParam == VK_SHIFT || wParam == VK_CONTROL )
             return Default();
@@ -1178,8 +1183,15 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
             MSWOnChar((WORD)wParam, lParam);
         else
             return Default();
+#endif
         break;
+    }
 
+    case WM_KEYUP:
+    {
+        MSWOnKeyUp((WORD) wParam, lParam);
+        break;
+    }
     case WM_CHAR: // Always an ASCII character
         {
             MSWOnChar((WORD)wParam, lParam, TRUE);
@@ -2392,6 +2404,74 @@ void wxWindow::MSWOnChar(WXWORD wParam, WXLPARAM lParam, bool isASCII)
     }
 }
 
+void wxWindow::MSWOnKeyDown(WXWORD wParam, WXLPARAM lParam, bool isASCII)
+{
+    int id;
+
+    if ((id = wxCharCodeMSWToWX(wParam)) == 0) {
+        id = wParam;
+    }
+
+    if (id != -1)
+    {
+        wxKeyEvent event(wxEVT_KEY_DOWN);
+        event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE);
+        event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE);
+        if ((HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN)
+            event.m_altDown = TRUE;
+
+        event.m_eventObject = this;
+        event.m_keyCode = id;
+        event.SetTimestamp(wxApp::sm_lastMessageTime);
+
+        POINT pt ;
+        GetCursorPos(&pt) ;
+        RECT rect ;
+        GetWindowRect((HWND) GetHWND(),&rect) ;
+        pt.x -= rect.left ;
+        pt.y -= rect.top ;
+
+        event.m_x = pt.x; event.m_y = pt.y;
+
+        if (!GetEventHandler()->ProcessEvent(event))
+            Default();
+    }
+}
+
+void wxWindow::MSWOnKeyUp(WXWORD wParam, WXLPARAM lParam, bool isASCII)
+{
+    int id;
+
+    if ((id = wxCharCodeMSWToWX(wParam)) == 0) {
+        id = wParam;
+    }
+
+    if (id != -1)
+    {
+        wxKeyEvent event(wxEVT_KEY_UP);
+        event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE);
+        event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE);
+        if ((HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN)
+            event.m_altDown = TRUE;
+
+        event.m_eventObject = this;
+        event.m_keyCode = id;
+        event.SetTimestamp(wxApp::sm_lastMessageTime);
+
+        POINT pt ;
+        GetCursorPos(&pt) ;
+        RECT rect ;
+        GetWindowRect((HWND) GetHWND(),&rect) ;
+        pt.x -= rect.left ;
+        pt.y -= rect.top ;
+
+        event.m_x = pt.x; event.m_y = pt.y;
+
+        if (!GetEventHandler()->ProcessEvent(event))
+            Default();
+    }
+}
+
 void wxWindow::MSWOnJoyDown(int joystick, int x, int y, WXUINT flags)
 {
     int buttons = 0;
@@ -3464,6 +3544,8 @@ WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, bool *want3D)
 
 void wxWindow::OnChar(wxKeyEvent& event)
 {
+/* I'm commenting this out because otherwise, we lose tabs in e.g. a text window (see MDI sample)
+ * (JACS, 14/01/99)
     if ( event.KeyCode() == WXK_TAB ) {
         // propagate the TABs to the parent - it's up to it to decide what
         // to do with it
@@ -3472,6 +3554,7 @@ void wxWindow::OnChar(wxKeyEvent& event)
                 return;
         }
     }
+*/
 
     bool isVirtual;
     int id = wxCharCodeWXToMSW((int)event.KeyCode(), &isVirtual);
@@ -3483,6 +3566,16 @@ void wxWindow::OnChar(wxKeyEvent& event)
         (void) MSWDefWindowProc(m_lastMsg, (WPARAM) id, m_lastLParam);
 }
 
+void wxWindow::OnKeyDown(wxKeyEvent& event)
+{
+    Default();
+}
+
+void wxWindow::OnKeyUp(wxKeyEvent& event)
+{
+    Default();
+}
+
 void wxWindow::OnPaint(wxPaintEvent& event)
 {
     Default();
diff --git a/src/stubs/window.cpp b/src/stubs/window.cpp
index 10ec3976dd..ef3388cc30 100644
--- a/src/stubs/window.cpp
+++ b/src/stubs/window.cpp
@@ -44,6 +44,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
 
 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
   EVT_CHAR(wxWindow::OnChar)
+  EVT_KEY_DOWN(wxWindow::OnKeyDown)
+  EVT_KEY_UP(wxWindow::OnKeyUp)
   EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
   EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
   EVT_INIT_DIALOG(wxWindow::OnInitDialog)
@@ -551,6 +553,7 @@ void wxWindow::SetFont(const wxFont& font)
 
 void wxWindow::OnChar(wxKeyEvent& event)
 {
+/* ??
     if ( event.KeyCode() == WXK_TAB ) {
         // propagate the TABs to the parent - it's up to it to decide what
         // to do with it
@@ -559,6 +562,18 @@ void wxWindow::OnChar(wxKeyEvent& event)
                 return;
         }
     }
+*/
+    Default();
+}
+
+void wxWindow::OnKeyDown(wxKeyEvent& event)
+{
+    Default();
+}
+
+void wxWindow::OnKeyUp(wxKeyEvent& event)
+{
+    Default();
 }
 
 void wxWindow::OnPaint(wxPaintEvent& event)
-- 
2.50.0

