Skip to content

Commit

Permalink
One-Hand mice merge without horizontal wheel
Browse files Browse the repository at this point in the history
  • Loading branch information
lededev committed Dec 18, 2024
1 parent 39521d2 commit a33a095
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 147 deletions.
9 changes: 5 additions & 4 deletions Src/MainFrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2808,17 +2808,18 @@ BOOL CMainFrame::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
return FALSE;
strTipText = strFullText.substr(newline1st + 1).c_str();
}
constexpr size_t tipBufLen = 512;
if (pNMHDR->code == TTN_NEEDTEXTA)
{
m_upszLongTextA.reset(new CHAR[256]);
m_upszLongTextA.reset(new CHAR[tipBufLen]);
pTTTA->lpszText = m_upszLongTextA.get();
_wcstombsz(pTTTA->lpszText, strTipText, 256);
_wcstombsz(pTTTA->lpszText, strTipText, tipBufLen);
}
else
{
m_upszLongTextW.reset(new WCHAR[256]);
m_upszLongTextW.reset(new WCHAR[tipBufLen]);
pTTTW->lpszText = m_upszLongTextW.get();
lstrcpyn(pTTTW->lpszText, strTipText, 256);
lstrcpyn(pTTTW->lpszText, strTipText, tipBufLen);
}
*pResult = 0;

Expand Down
4 changes: 2 additions & 2 deletions Src/Merge.rc
Original file line number Diff line number Diff line change
Expand Up @@ -4574,8 +4574,8 @@ STRINGTABLE
BEGIN
ID_MICE_PREVDIFF "\nPrevious Difference (Alt+Up)\n(Right Button+Wheel Up)\n(Alt+Wheel Up)"
ID_MICE_NEXTDIFF "\nNext Difference (Alt+Down)\n(Right Button+Wheel Down)\n(Alt+Wheel Down)"
ID_MICE_L2R "\nCopy to Right (Alt+Right)\n(Right Button+Wheel Right)\n(Alt+Wheel Right)\n(Alt+Shift+Wheel Down)"
ID_MICE_R2L "\nCopy to Left (Alt+Left)\n(Right Button+Wheel Left)\n(Alt+Wheel Left)\n(Alt+Shift+Wheel Up)"
ID_MICE_L2R "\nCopy to Right (Alt+Right)\n(Right Button+Wheel Right)\n(Alt+Wheel Right)\n(Right Button+Shift+Wheel Down)\n(Alt+Shift+Wheel Down)\n(Hold Right Button+Middle Button Click+Wheel Down)"
ID_MICE_R2L "\nCopy to Left (Alt+Left)\n(Right Button+Wheel Left)\n(Alt+Wheel Left)\n(Right Button+Shift+Wheel Up)\n(Alt+Shift+Wheel Up)\n(Hold Right Button+Middle Button Click+Wheel Up)"
ID_MICE_L2RNEXT "\nCopy to Right and Advance (Ctrl+Alt+Right)\n(Ctrl+Alt+Wheel Right)\n(Ctrl+Alt+Shift+Wheel Down)"
ID_MICE_R2LNEXT "\nCopy to Left and Advance (Ctrl+Alt+Left)\n(Ctrl+Alt+Wheel Left)\n(Ctrl+Alt+Shift+Wheel Up)"
END
Expand Down
300 changes: 178 additions & 122 deletions Src/MouseHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,165 +6,222 @@
# define WM_MOUSEHWHEEL 0x20e
#endif

// Define state matrix
const std::function<bool(LPARAM)> CMouseHook::stateMatrix[3][6] = {
// State::Idle
{
[](LPARAM) { Transition(State::RightButtonDown); return false; }, // WM_RBUTTONDOWN
[](LPARAM) { return false; }, // WM_RBUTTONUP
[](LPARAM) { return false; }, // WM_LBUTTONDOWN
[](LPARAM) { return false; }, // WM_MBUTTONUP
[](LPARAM lParam) { return MouseWheelAction(lParam); }, // WM_MOUSEWHEEL
[](LPARAM lParam) { return MouseHWheelAction(lParam); } // WM_MOUSEHWHEEL
},
// State::RightButtonDown
{
[](LPARAM) { return false; }, // WM_RBUTTONDOWN
[](LPARAM) { Transition(State::Idle); return false; }, // WM_RBUTTONUP
[](LPARAM) { return false; }, // WM_LBUTTONDOWN
[](LPARAM) { Transition(State::HorizontalScrollSimulated); return false; }, // WM_MBUTTONUP
[](LPARAM lParam) { return RightButtonDown_MouseWheel(lParam); }, // WM_MOUSEWHEEL
[](LPARAM lParam) { return RightButtonDown_MouseHWheel(lParam); } // WM_MOUSEHWHEEL
},
// State::HorizontalScrollSimulated
{
[](LPARAM) { return false; }, // WM_RBUTTONDOWN
[](LPARAM) { Transition(State::Idle); return false; }, // WM_RBUTTONUP
[](LPARAM) { return false; }, // WM_LBUTTONDOWN
[](LPARAM) { Transition(State::RightButtonDown); return false; }, // WM_MBUTTONUP
[](LPARAM lParam) { // WM_MOUSEWHEEL
auto b = RightButtonDown_MouseWheel(lParam);
Transition(State::RightButtonDown);
return b;
},
[](LPARAM lParam) { // WM_MOUSEHWHEEL
auto b = RightButtonDown_MouseHWheel(lParam);
Transition(State::RightButtonDown);
return b;
}
}
};

void CMouseHook::Transition(State nextState) {
m_currentState = nextState;
}

LRESULT CALLBACK CMouseHook::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
return CallNextHookEx(m_hMouseHook, nCode, wParam, lParam);

if (wParam == WM_LBUTTONDOWN)
{
EndRightWheelScrolling();
}
else if (wParam == WM_RBUTTONDOWN)
const static std::unordered_map<UINT, int> actionIdx =
{
m_bRButtonDown = true;
}
else if (wParam == WM_RBUTTONUP)
{WM_RBUTTONDOWN, 0}
,{WM_RBUTTONUP, 1}
,{WM_LBUTTONDOWN, 2}
,{WM_MBUTTONUP, 3}
,{WM_MOUSEWHEEL, 4}
,{WM_MOUSEHWHEEL, 5}
};
auto it = actionIdx.find(static_cast<UINT>(wParam));
if (it != actionIdx.end())
{
m_bRButtonDown = false;
EndRightWheelScrolling();
auto bRet = stateMatrix[static_cast<int>(m_currentState)][it->second](lParam);
if (bRet)
return 1;
}
else if (wParam == WM_MOUSEWHEEL)
{
MOUSEHOOKSTRUCTEX* pMouseStruct = (MOUSEHOOKSTRUCTEX*)lParam;
short zDelta = HIWORD(pMouseStruct->mouseData);

if (GetAsyncKeyState(VK_MENU) & 0x8000)
return CallNextHookEx(m_hMouseHook, nCode, wParam, lParam);
}

bool CMouseHook::MouseWheelAction(LPARAM lParam)
{
MOUSEHOOKSTRUCTEX* pMouseStruct = (MOUSEHOOKSTRUCTEX*)lParam;
short zDelta = HIWORD(pMouseStruct->mouseData);

if (GetAsyncKeyState(VK_MENU) & 0x8000)
{
HWND hwndTarget = GetForegroundWindow();
// When hold Alt key, use nFlags to check MK_CONTROL MK_SHIFT holding got problem, Use GetAsyncKeyState() instead.
const auto bShiftDown = GetAsyncKeyState(VK_SHIFT) & 0x8000;
const auto bControlDown = GetAsyncKeyState(VK_CONTROL) & 0x8000;
// zDelta > 0 scrool up, < 0 scrool down
if (zDelta > 0)
{
HWND hwndTarget = GetForegroundWindow();
// When hold Alt key, use nFlags to check MK_CONTROL MK_SHIFT holding got problem, Use GetAsyncKeyState() instead.
const auto bShiftDown = GetAsyncKeyState(VK_SHIFT) & 0x8000;
const auto bControlDown = GetAsyncKeyState(VK_CONTROL) & 0x8000;
// zDelta > 0 scrool up, < 0 scrool down
if (zDelta > 0)
// Check Shift key hold for mice without HWheel function
if (bShiftDown && bControlDown)
{
// Check Shift key hold for mice without HWheel function
if (bShiftDown && bControlDown)
{
// Alt+Ctrl+Shift+ScrollUp as Alt+Ctrl+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2LNEXT, 0);
return 1;
}
else if (bShiftDown)
{
// Alt+Shift+ScrollUp as Alt+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2L, 0);
return 1;
}
else if (!m_bRButtonDown)
{
// Alt+ScrollUp as Alt+Up
PostMessage(hwndTarget, WM_COMMAND, ID_PREVDIFF, 0);
return 1;
}
// Alt+Ctrl+Shift+ScrollUp as Alt+Ctrl+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2LNEXT, 0);
return true;
}
else if (zDelta < 0)
else if (bShiftDown)
{
// Check Shift key hold for mice without HWheel function
if (bShiftDown && bControlDown)
{
// Alt+Ctrl+Shift+ScrollDown as Alt+Ctrl+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2RNEXT, 0);
return 1;
}
else if (bShiftDown)
{
// Alt+Shift+ScrollDown as Alt+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2R, 0);
return 1;
}
else if (!m_bRButtonDown)
{
// Alt+ScrollDown as Alt+Down
PostMessage(hwndTarget, WM_COMMAND, ID_NEXTDIFF, 0);
return 1;
}
// Alt+Shift+ScrollUp as Alt+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2L, 0);
return true;
}
else if (m_currentState == State::Idle)
{
// Alt+ScrollUp as Alt+Up
PostMessage(hwndTarget, WM_COMMAND, ID_PREVDIFF, 0);
return true;
}
}

// Hold mice right button for One-handed operation
if (m_bRButtonDown)
else if (zDelta < 0)
{
HWND hwndTarget = GetForegroundWindow();
if (zDelta > 0)
// Check Shift key hold for mice without HWheel function
if (bShiftDown && bControlDown)
{
// RButton+ScrollUp as Alt+Up
StartRightWheelScrolling();
PostMessage(hwndTarget, WM_COMMAND, ID_PREVDIFF, 0);
return 1;
// Alt+Ctrl+Shift+ScrollDown as Alt+Ctrl+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2RNEXT, 0);
return true;
}
else if (zDelta < 0)
else if (bShiftDown)
{
// RButton+ScrollDown as Alt+Down
StartRightWheelScrolling();
// Alt+Shift+ScrollDown as Alt+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2R, 0);
return true;
}
else if (m_currentState == State::Idle)
{
// Alt+ScrollDown as Alt+Down
PostMessage(hwndTarget, WM_COMMAND, ID_NEXTDIFF, 0);
return 1;
return true;
}
}
}
else if (wParam == WM_MOUSEHWHEEL)
{
MOUSEHOOKSTRUCTEX* pMouseStruct = (MOUSEHOOKSTRUCTEX*)lParam;
short zDelta = HIWORD(pMouseStruct->mouseData);
return false;
}

if (GetAsyncKeyState(VK_MENU) & 0x8000)
bool CMouseHook::MouseHWheelAction(LPARAM lParam)
{
MOUSEHOOKSTRUCTEX* pMouseStruct = (MOUSEHOOKSTRUCTEX*)lParam;
short zDelta = HIWORD(pMouseStruct->mouseData);

if (GetAsyncKeyState(VK_MENU) & 0x8000)
{
HWND hwndTarget = GetForegroundWindow();
const auto bControlDown = GetAsyncKeyState(VK_CONTROL) & 0x8000;
// zDelta > 0 scrool right, < 0 scrool left
if (zDelta > 0)
{
HWND hwndTarget = GetForegroundWindow();
const auto bControlDown = GetAsyncKeyState(VK_CONTROL) & 0x8000;
// zDelta > 0 scrool right, < 0 scrool left
if (zDelta > 0)
if (bControlDown)
{
if (bControlDown)
{
// Alt+Ctrl+HScrollRight as Alt+Ctrl+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2RNEXT, 0);
return 1;
}
else if (!m_bRButtonDown)
{
// Alt+HScrollRight as Alt+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2R, 0);
return 1;
}
// Alt+Ctrl+HScrollRight as Alt+Ctrl+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2RNEXT, 0);
return true;
}
else if (zDelta < 0)
else if (m_currentState == State::Idle)
{
if (bControlDown)
{
// Alt+Ctrl+HScrollLeft as Alt+Ctrl+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2LNEXT, 0);
return 1;
}
else if (!m_bRButtonDown)
{
// Alt+HScrollLeft as Alt+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2L, 0);
return 1;
}
// Alt+HScrollRight as Alt+Right
PostMessage(hwndTarget, WM_COMMAND, ID_L2R, 0);
return true;
}
}

// Hold mice right button for One-handed operation
if (m_bRButtonDown)
else if (zDelta < 0)
{
HWND hwndTarget = GetForegroundWindow();
if (zDelta > 0)
if (bControlDown)
{
// RButton+ScrollRight as Alt+Right
StartRightWheelScrolling();
PostMessage(hwndTarget, WM_COMMAND, ID_L2R, 0);
return 1;
// Alt+Ctrl+HScrollLeft as Alt+Ctrl+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2LNEXT, 0);
return true;
}
else if (zDelta < 0)
else if (m_currentState == State::Idle)
{
// RButton+ScrollLeft as Alt+Left
StartRightWheelScrolling();
// Alt+HScrollLeft as Alt+Left
PostMessage(hwndTarget, WM_COMMAND, ID_R2L, 0);
return 1;
return true;
}
}
}
return CallNextHookEx(m_hMouseHook, nCode, wParam, lParam);
return false;
}

bool CMouseHook::RightButtonDown_MouseWheel(LPARAM lParam)
{
MOUSEHOOKSTRUCTEX* pMouseStruct = (MOUSEHOOKSTRUCTEX*)lParam;
short zDelta = HIWORD(pMouseStruct->mouseData);
HWND hwndTarget = GetForegroundWindow();
if (zDelta > 0)
{
// RButton(hold)+ScrollUp as Alt+Up, RButton(hold) MButtonClk WheelScrollUp as Alt+Left
StartRightWheelScrolling();
PostMessage(hwndTarget, WM_COMMAND, (State::HorizontalScrollSimulated == m_currentState) ?
ID_R2L : ID_PREVDIFF, 0);
return true;
}
else if (zDelta < 0)
{
// RButton(hold)+ScrollDown as Alt+Down, RButton(hold) MButtonClk WheelScrollUp as Alt+Right
StartRightWheelScrolling();
PostMessage(hwndTarget, WM_COMMAND, (State::HorizontalScrollSimulated == m_currentState) ?
ID_L2R : ID_NEXTDIFF, 0);
return true;
}
return false;
}

bool CMouseHook::RightButtonDown_MouseHWheel(LPARAM lParam)
{
MOUSEHOOKSTRUCTEX* pMouseStruct = (MOUSEHOOKSTRUCTEX*)lParam;
short zDelta = HIWORD(pMouseStruct->mouseData);
HWND hwndTarget = GetForegroundWindow();
if (zDelta > 0)
{
// RButton+ScrollRight as Alt+Right
StartRightWheelScrolling();
PostMessage(hwndTarget, WM_COMMAND, ID_L2R, 0);
return true;
}
else if (zDelta < 0)
{
// RButton+ScrollLeft as Alt+Left
StartRightWheelScrolling();
PostMessage(hwndTarget, WM_COMMAND, ID_R2L, 0);
return true;
}
return false;
}

void CMouseHook::SetMouseHook()
Expand All @@ -180,4 +237,3 @@ void CMouseHook::UnhookMouseHook()
m_hMouseHook = nullptr;
}
}

Loading

0 comments on commit a33a095

Please sign in to comment.