From 5048c832bb3c2f41ecd29ac079d74e39e304aec8 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Thu, 10 Jul 2003 09:16:00 +0000
Subject: [PATCH] Applied patch [ 758687 ] RegisterHotkey implemented

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@21842 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/window.tex | 55 +++++++++++++++++++++++++++++++++++++++
 docs/todo.txt            |  2 ++
 include/wx/defs.h        | 11 ++++++++
 include/wx/event.h       |  8 +++++-
 include/wx/msw/setup0.h  |  3 +++
 include/wx/msw/window.h  |  9 +++++++
 include/wx/window.h      |  5 ++++
 src/common/event.cpp     |  3 +++
 src/common/wincmn.cpp    | 13 ++++++++++
 src/msw/window.cpp       | 56 ++++++++++++++++++++++++++++++++++++++++
 10 files changed, 164 insertions(+), 1 deletion(-)

diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex
index bf8ce8e985..fa07aa81b9 100644
--- a/docs/latex/wx/window.tex
+++ b/docs/latex/wx/window.tex
@@ -1879,6 +1879,39 @@ repainted.
 
 This is the same as \helpref{Refresh}{wxwindowrefresh} but has a nicer syntax.
 
+\membersection{wxWindow::RegisterHotKey}\label{wxwindowregisterhotkey}
+
+\func{bool}{RegisterHotKey}{\param{int}{ hotkeyId}, \param{int}{ modifiers}, \param{int}{ virtualKeyCode}}
+
+Registers a system wide hotkey. Every time the user presses the hotkey registered here, this window
+will receive a hotkey event. It will receive the event even if the application is in the background
+and does not have the input focus because the user is working with some other application.
+
+\wxheading{Parameters}
+
+\docparam{hotkeyId}{Numeric identifier of the hotkey. For applications this must be between 0 and 0xBFFF. If
+this function is called from a shared DLL, it must be a system wide unique identifier between 0xC000 and 0xFFFF.
+This is a MSW specific detail.}
+
+\docparam{modifiers}{A bitwise combination of {\tt wxMOD\_SHIFT}, {\tt wxMOD\_CONTROL}, {\tt wxMOD\_ALT}
+or {\tt wxMOD\_WIN} specifying the modifier keys that have to be pressed along with the key.}
+
+\docparam{virtualKeyCode}{The virtual key code of the hotkey.}
+
+\wxheading{Return value}
+
+{\tt true} if the hotkey was registered successfully. {\tt false} if some other application already registered a
+hotkey with this modifier/virtualKeyCode combination.
+
+\wxheading{Remarks}
+
+Use EVT\_HOTKEY(hotkeyId, fnc) in the event table to capture the event.
+This function is currently only implemented under MSW.
+
+\wxheading{See also}
+
+\helpref{wxWindow::UnregisterHotKey}{wxwindowunregisterhotkey}
+
 \membersection{wxWindow::ReleaseMouse}\label{wxwindowreleasemouse}
 
 \func{virtual void}{ReleaseMouse}{\void}
@@ -2802,6 +2835,28 @@ Returns {\tt false} if a transfer failed.
 \helpref{wxWindow::TransferDataFromWindow}{wxwindowtransferdatafromwindow},\rtfsp
 \helpref{wxValidator}{wxvalidator}, \helpref{wxWindow::Validate}{wxwindowvalidate}
 
+\membersection{wxWindow::UnregisterHotKey}\label{wxwindowunregisterhotkey}
+
+\func{bool}{UnregisterHotKey}{\param{int}{ hotkeyId}}
+
+Unregisters a system wide hotkey.
+
+\wxheading{Parameters}
+
+\docparam{hotkeyId}{Numeric identifier of the hotkey. Must be the same id that was passed to RegisterHotKey.}
+
+\wxheading{Return value}
+
+{\tt true} if the hotkey was unregistered successfully, {\tt false} if the id was invalid.
+
+\wxheading{Remarks}
+
+This function is currently only implemented under MSW.
+
+\wxheading{See also}
+
+\helpref{wxWindow::RegisterHotKey}{wxwindowregisterhotkey}
+
 \membersection{wxWindow::Update}\label{wxwindowupdate}
 
 \func{virtual void}{Update}{\void}
diff --git a/docs/todo.txt b/docs/todo.txt
index cfc177cbcc..125f33989c 100644
--- a/docs/todo.txt
+++ b/docs/todo.txt
@@ -16,3 +16,5 @@ Please see also:
 - In doc/view file selector, document type is selected by
   extension, not the type selected in the (Windows) file selector.
 
+- Add wxUSE_HOTKEY and any other missing options to configure.
+
diff --git a/include/wx/defs.h b/include/wx/defs.h
index 85331769e6..68405ceca5 100644
--- a/include/wx/defs.h
+++ b/include/wx/defs.h
@@ -1737,6 +1737,17 @@ enum wxKeyCode
     WXK_WINDOWS_MENU
 };
 
+#if wxUSE_HOTKEY
+enum wxHotkeyModifier
+{
+    wxMOD_NONE = 0,
+    wxMOD_ALT = 1,
+    wxMOD_CONTROL = 2,
+    wxMOD_SHIFT = 4,
+    wxMOD_WIN = 8
+};
+#endif
+
 // Mapping modes (same values as used by Windows, don't change)
 enum
 {
diff --git a/include/wx/event.h b/include/wx/event.h
index a61b0a9d42..c881a924f2 100644
--- a/include/wx/event.h
+++ b/include/wx/event.h
@@ -186,7 +186,9 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EVENT_TYPE(wxEVT_NAVIGATION_KEY, 214)
     DECLARE_EVENT_TYPE(wxEVT_KEY_DOWN, 215)
     DECLARE_EVENT_TYPE(wxEVT_KEY_UP, 216)
-
+#if wxUSE_HOTKEY
+    DECLARE_EVENT_TYPE(wxEVT_HOTKEY, 217)
+#endif
         // Set cursor event
     DECLARE_EVENT_TYPE(wxEVT_SET_CURSOR, 230)
 
@@ -819,6 +821,7 @@ private:
  wxEVT_CHAR_HOOK
  wxEVT_KEY_DOWN
  wxEVT_KEY_UP
+ wxEVT_HOTKEY
  */
 
 class WXDLLIMPEXP_CORE wxKeyEvent : public wxEvent
@@ -2332,6 +2335,9 @@ typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureC
 #define EVT_CHAR(func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_CHAR, wxID_ANY, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL ),
 #define EVT_KEY_DOWN(func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_KEY_DOWN, wxID_ANY, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL ),
 #define EVT_KEY_UP(func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_KEY_UP, wxID_ANY, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL ),
+#if wxUSE_HOTKEY
+#define EVT_HOTKEY(id, func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_HOTKEY, id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, (wxObject *) NULL ),
+#endif
 #define EVT_CHAR_HOOK(func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_CHAR_HOOK, wxID_ANY, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction) & func, NULL ),
 #define EVT_MENU_OPEN(func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_MENU_OPEN, wxID_ANY, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxMenuEventFunction) & func, (wxObject *) NULL ),
 #define EVT_MENU_CLOSE(func)  DECLARE_EVENT_TABLE_ENTRY( wxEVT_MENU_CLOSE, wxID_ANY, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxMenuEventFunction) & func, (wxObject *) NULL ),
diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h
index eb7f96dadf..454b7120cd 100644
--- a/include/wx/msw/setup0.h
+++ b/include/wx/msw/setup0.h
@@ -569,6 +569,9 @@
 // wxAcceleratorTable/Entry classes and support for them in wxMenu(Bar)
 #define wxUSE_ACCEL 1
 
+// Hotkey support (currently Windows only)
+#define wxUSE_HOTKEY 1
+
 // Use wxCaret: a class implementing a "cursor" in a text control (called caret
 // under Windows).
 //
diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h
index c44f9d908a..0e0f8317df 100644
--- a/include/wx/msw/window.h
+++ b/include/wx/msw/window.h
@@ -177,6 +177,12 @@ public:
     wxWindow* GetWindowChild(wxWindowID id);
 #endif // __WXUNIVERSAL__
 
+#if wxUSE_ACCEL
+    // install and deinstall a system wide hotkey
+    virtual bool RegisterHotKey(int hotkeyId, int modifiers, int virtualKeyCode);
+    virtual bool UnregisterHotKey(int hotkeyId);
+#endif
+
     // implementation from now on
     // --------------------------
 
@@ -362,6 +368,9 @@ public:
     bool HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII = FALSE);
     bool HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam);
     bool HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam);
+#if wxUSE_ACCEL
+    bool HandleHotKey(WXWPARAM wParam, WXLPARAM lParam);
+#endif
 #ifdef __WIN32__
     int HandleMenuChar(int chAccel, WXLPARAM lParam);
 #endif
diff --git a/include/wx/window.h b/include/wx/window.h
index 7839127ea9..959f775c70 100644
--- a/include/wx/window.h
+++ b/include/wx/window.h
@@ -516,6 +516,11 @@ public:
         { m_acceleratorTable = accel; }
     wxAcceleratorTable *GetAcceleratorTable()
         { return &m_acceleratorTable; }
+
+    // install and deinstall a system wide hotkey
+    virtual bool RegisterHotKey(int hotkeyId, int modifiers, int virtualKeyCode);
+    virtual bool UnregisterHotKey(int hotkeyId);
+
 #endif // wxUSE_ACCEL
 
     // dialog units translations
diff --git a/src/common/event.cpp b/src/common/event.cpp
index 8474ad0eec..ee22ca1062 100644
--- a/src/common/event.cpp
+++ b/src/common/event.cpp
@@ -197,6 +197,9 @@ DEFINE_EVENT_TYPE(wxEVT_CHAR_HOOK)
 DEFINE_EVENT_TYPE(wxEVT_NAVIGATION_KEY)
 DEFINE_EVENT_TYPE(wxEVT_KEY_DOWN)
 DEFINE_EVENT_TYPE(wxEVT_KEY_UP)
+#if wxUSE_HOTKEY
+DEFINE_EVENT_TYPE(wxEVT_HOTKEY)
+#endif
 
 // Set cursor event
 DEFINE_EVENT_TYPE(wxEVT_SET_CURSOR)
diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp
index d7492c0a39..06582f8f98 100644
--- a/src/common/wincmn.cpp
+++ b/src/common/wincmn.cpp
@@ -2106,6 +2106,19 @@ void wxWindowBase::ReleaseMouse()
                GetCapture());
 }
 
+#if wxUSE_HOTKEY
+bool wxWindowBase::RegisterHotKey(int hotkeyId, int modifiers, int virtualKeyCode)
+{
+    // not implemented
+    return false;
+}
+
+bool wxWindowBase::UnregisterHotKey(int hotkeyId)
+{
+    // not implemented
+    return false;
+}
+#endif
 
 void wxWindowBase::SendDestroyEvent()
 {
diff --git a/src/msw/window.cpp b/src/msw/window.cpp
index 8bb2ed22f1..e910670307 100644
--- a/src/msw/window.cpp
+++ b/src/msw/window.cpp
@@ -2549,6 +2549,12 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
             }
             break;
 
+#if wxUSE_HOTKEY
+        case WM_HOTKEY:
+            processed = HandleHotKey((WORD)wParam, lParam);
+            break;
+#endif
+
         case WM_HSCROLL:
         case WM_VSCROLL:
             {
@@ -5093,6 +5099,9 @@ const char *wxGetMessageName(int message)
         case 0x030F: return "WM_QUERYNEWPALETTE";
         case 0x0310: return "WM_PALETTEISCHANGING";
         case 0x0311: return "WM_PALETTECHANGED";
+#if wxUSE_HOTKEY
+        case 0x0312: return "WM_HOTKEY";
+#endif
 
         // common controls messages - although they're not strictly speaking
         // standard, it's nice to decode them nevertheless
@@ -5411,3 +5420,50 @@ wxPoint wxGetMousePosition()
     return wxPoint(pt.x, pt.y);
 }
 
+#if wxUSE_HOTKEY
+bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int virtualKeyCode)
+{
+    UINT win_modifiers=0;
+    if (modifiers & wxMOD_ALT)
+        win_modifiers|=MOD_ALT;
+    if (modifiers & wxMOD_SHIFT)
+        win_modifiers|=MOD_SHIFT;
+    if (modifiers & wxMOD_CONTROL)
+        win_modifiers|=MOD_CONTROL;
+    if (modifiers & wxMOD_WIN)
+        win_modifiers|=MOD_WIN;
+
+    return ::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, virtualKeyCode)!=FALSE;
+}
+
+bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
+{
+    return ::UnregisterHotKey(GetHwnd(), hotkeyId)!=FALSE;
+}
+
+bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam)
+{
+    int hotkeyId=wParam;
+     int virtualKey=HIWORD(lParam);
+    int win_modifiers=LOWORD(lParam);
+    /*
+    wxHotkeyModifier modifiers=wxMOD_NONE;
+    if (win_modifiers & MOD_ALT)
+        modifiers|=wxMOD_ALT;
+    if (win_modifiers & MOD_SHIFT)
+        modifiers|=wxMOD_SHIFT;
+    if (win_modifiers & MOD_CONTROL)
+        modifiers|=wxMOD_CONTROL;
+    if (win_modifiers & MOD_WIN)
+        modifiers|=wxMOD_WIN;
+*/
+    wxKeyEvent event(CreateKeyEvent(wxEVT_HOTKEY, virtualKey, wParam, lParam));
+    event.SetId(hotkeyId);
+    event.m_shiftDown = (win_modifiers & MOD_SHIFT) != 0;
+    event.m_controlDown = (win_modifiers & MOD_CONTROL) != 0;
+    event.m_altDown = (win_modifiers & MOD_ALT) != 0;
+    event.m_metaDown = (win_modifiers & MOD_WIN) != 0;
+    return GetEventHandler()->ProcessEvent(event);    
+}
+#endif
+
-- 
2.50.0

