summaryrefslogtreecommitdiff
path: root/zen/scroll_window_under_cursor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zen/scroll_window_under_cursor.cpp')
-rw-r--r--zen/scroll_window_under_cursor.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/zen/scroll_window_under_cursor.cpp b/zen/scroll_window_under_cursor.cpp
new file mode 100644
index 00000000..6031cd88
--- /dev/null
+++ b/zen/scroll_window_under_cursor.cpp
@@ -0,0 +1,77 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+#include <cassert>
+#include "win.h" //includes "windows.h"
+#include "Windowsx.h" //WM_MOUSEWHEEL
+
+//redirect mouse wheel events directly to window under cursor rather than window having input focus
+//implementing new Windows Vista UI guidelines: http://msdn.microsoft.com/en-us/library/bb545459.aspx#wheel
+//this is confirmed to be required for at least Windows 2000 to Windows 8
+//on Ubuntu Linux, this is already the default behavior
+
+//Usage: just include this file into a Windows project
+
+namespace
+{
+#ifndef WM_MOUSEHWHEEL //MinGW is clueless...
+#define WM_MOUSEHWHEEL 0x020E
+#endif
+
+LRESULT CALLBACK mouseInputHook(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ //"if nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function
+ //without further processing and should return the value returned by CallNextHookEx"
+ if (nCode >= 0)
+ {
+ MSG& msgInfo = *reinterpret_cast<MSG*>(lParam);
+
+ if (msgInfo.message == WM_MOUSEWHEEL ||
+ msgInfo.message == WM_MOUSEHWHEEL)
+ {
+ POINT pt = {};
+ pt.x = GET_X_LPARAM(msgInfo.lParam); //yes, there's also msgInfo.pt, but let's not take chances
+ pt.y = GET_Y_LPARAM(msgInfo.lParam); //
+
+ //visible child window directly under cursor; attention: not necessarily from our process!
+ //http://blogs.msdn.com/b/oldnewthing/archive/2010/12/30/10110077.aspx
+ if (HWND hWin = ::WindowFromPoint(pt))
+ if (msgInfo.hwnd != hWin && ::GetCapture() == nullptr)
+ {
+ DWORD winProcessId = 0;
+ ::GetWindowThreadProcessId( //no-fail!
+ hWin, //_In_ HWND hWnd,
+ &winProcessId); //_Out_opt_ LPDWORD lpdwProcessId
+ if (winProcessId == ::GetCurrentProcessId()) //no-fail!
+ msgInfo.hwnd = hWin; //it would be a bug to set handle from another process here
+ }
+ }
+ }
+
+ return ::CallNextHookEx(nullptr, nCode, wParam, lParam);
+}
+
+struct Dummy
+{
+ Dummy()
+ {
+ hHook = ::SetWindowsHookEx(WH_GETMESSAGE, //__in int idHook,
+ mouseInputHook, //__in HOOKPROC lpfn,
+ nullptr, //__in HINSTANCE hMod,
+ ::GetCurrentThreadId()); //__in DWORD dwThreadId
+ assert(hHook);
+ }
+
+ ~Dummy()
+ {
+ if (hHook)
+ ::UnhookWindowsHookEx(hHook);
+ }
+
+private:
+ HHOOK hHook;
+} dummy;
+}
bgstack15