Community
    • Login

    Can't rebind mouse buttons/scroll wheel

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    13 Posts 4 Posters 501 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • V
      Valour549
      last edited by

      Under modify shortcut, there is no option to rebind any of the mouse buttons or the scroll wheel.

      As a regular user of WinMerge, I would really really like to be able in Notepad++ to rebind Next Search Result / Previous Search Result to Alt + Wheeldown / Alt+Wheelup respectively.

      I tried editing shortcuts.xml to use the correct Key for wheelup and wheeldown, but it doesn’t work either.

      Is there any particular reason why we can’t rebind modifier + mouse buttons/scroll wheel as hotkeys?

      Alan KilbornA mathlete2M 2 Replies Last reply Reply Quote 0
      • Alan KilbornA
        Alan Kilborn @Valour549
        last edited by

        @Valour549 said:

        Is there any particular reason why we can’t rebind modifier + mouse buttons/scroll wheel as hotkeys?

        I don’t believe that there is a specific reason.
        Very common functionality that users are used to in other applications might be the reason (i.e., nobody ever thought that mouse stuff needed to be reassignable).
        You could make a feature request for this, after checking to see if the feature has already been requested (it would not surprise me if it has).

        1 Reply Last reply Reply Quote 1
        • mathlete2M
          mathlete2 @Valour549
          last edited by

          @Valour549 said in Can't rebind mouse buttons/scroll wheel:

          Is there any particular reason why we can’t rebind modifier + mouse buttons/scroll wheel as hotkeys?

          Maybe because the buttons/wheel on a mouse aren’t considers “keys” per se - they are forms of input from a completely different piece of hardware.

          Admittedly, programs like Autohotkey are able to manage input from both the keyboard and mouse, so in theory, it should be possible for NP++ to do the same. Further to @Alan-Kilborn 's point about filing a feature request: there doesn’t seem to be one for this particular use of the mouse yet.

          PeterJonesP 1 Reply Last reply Reply Quote 0
          • PeterJonesP
            PeterJones @mathlete2
            last edited by

            @Valour549 ,

            I just double-checked, and VK_LBUTTON, VK_RBUTTON, and VK_MBUTTON are sent as virtual keycodes (as are the X1 and X2 mouse buttons, so if you’ve got a mouse with extra buttons, they might be mappable as well), just the same as the other keyboard keys, so it should be doable. Scroll wheel events are processed differently (not with virtual keycodes, but with the WM_MOUSEWHEEL message), so I don’t think that Shortcut Mapper could process a scrollwheel up/down without (as far as I can tell) a huge redesign (since the Shortcut Mapper is currently limited to processing virtual keys).

            I recently expanded which keys were available to Notepad++, so I know where in the code to look, so I’ll run some experiments of trying to add the five mouse clicks (though not the scrollwheel).

            Since @mathlete2 was kind enough to check to see that no request currently exists, if you were to create an official feature request, then once I get my experiments working, I could attach a PR to that feature request. If you do make a request, make sure it links back to this discussion (and, if you can search the history of the forum to see if there have been other requests for allowing mouse buttons in the Shortcut Mapper; if so, link them); and once you’ve made the feature request, paste a link to that Issue back here in this discussion.

            Unfortunately, even if I am able to implement it, I cannot guarantee that the developer would accept my PR, so there is an element of risk, that the effort might be rejected.

            PeterJonesP 1 Reply Last reply Reply Quote 1
            • PeterJonesP
              PeterJones @PeterJones
              last edited by

              update: it didn’t end up being as easy as I’d hoped; on other real keys, it was just a matter of adding them to the available list for the shortcut mapper; when I tried the same with the mouse clicks (even unused ones, like the middle mouse button), nothing happened. So it’s going to be more involved than I hoped, so it will take more time, and I’m less hopeful that I have the skills to implement it. I won’t give up yet, but I thought I would manage expectations.

              Alan KilbornA 1 Reply Last reply Reply Quote 1
              • Alan KilbornA
                Alan Kilborn @PeterJones
                last edited by

                @PeterJones said:

                So it’s going to be more involved than I hoped, so it will take more time…

                Possibly the scripted version (supporting the mouse wheel) will beat you to publication. :-)

                1 Reply Last reply Reply Quote 1
                • Alan KilbornA
                  Alan Kilborn
                  last edited by

                  Here’s a scripted version of what the OP wants. It’s in two scripts, one is dependent on the other. First, the master script, MouseWheelHookDemo.py (the one that gets run):

                  # -*- coding: utf-8 -*-
                  
                  #########################################
                  #
                  #  MouseWheelHookDemo (MWHD)
                  #
                  #########################################
                  
                  # note:
                  #  This script was developed and tested under Python3 64-bit on unicode (non-ANSI) encoded data.
                  #  It may work as-is using Python2 and/or ANSI-encoded data and/or 32-bits, but that would be incidental.
                  
                  # references:
                  #  https://community.notepad-plus-plus.org/topic/26661
                  #  for newbie info on PythonScripts, see https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript
                  
                  # to execute, use this in (e.g.) user startup.py:
                  #  from MouseWheelHookDemo import MOUSE_WHEEL_HOOK_DEMO
                  # another execution option would be to copy and then paste that line into the PythonScript console >>> box
                  
                  # note: if running via startup.py, need to make sure that "Initialisation" for "Python Script Configuration" is set to "ATSTARTUP" and not "LAZY".
                  
                  from Npp import *
                  from ctypes import WinDLL
                  from MsgHooker import MH as MsgHook
                  
                  WM_MOUSEWHEEL = 0x020A
                  WM_SYSCOMMAND = 0x0112
                  SC_KEYMENU = 0xF100
                  VK_MENU = 0x12
                  
                  def HIWORD(value): return (value >> 16) & 0xFFFF
                  def LOWORD(value): return value & 0xFFFF
                  
                  user32 = WinDLL('user32')
                  
                  def alt_held():
                      return (user32.GetAsyncKeyState(VK_MENU) & 0x8000) != 0
                  
                  class MWHD(object):
                  
                      def __init__(self):
                  
                          # these must be assigned to "self" variables so that they aren't garbage collected!
                          self.mh1 = MsgHook([ editor1.hwnd, editor2.hwnd ], self.editor_hook_func, [ WM_MOUSEWHEEL ])
                          self.mh2 = MsgHook([ notepad.hwnd ], self.notepad_hook_func, [ WM_SYSCOMMAND ])
                  
                      def editor_hook_func(self, hwnd, msg, wParam, lParam):
                          wheel_delta = HIWORD(wParam)
                          if wheel_delta > 0x7FFF: wheel_delta -= 0x1_0000
                          keys_down = LOWORD(wParam)
                          alt_down = alt_held()
                          if alt_down and keys_down == 0:
                              notepad.menuCommand(MENUCOMMAND.SEARCH_GOTONEXTFOUND if wheel_delta < 0 else MENUCOMMAND.SEARCH_GOTOPREVFOUND)
                              return False
                          return True
                  
                      # https://stackoverflow.com/questions/352270/how-to-cancel-the-system-key-down-state-in-windows
                      def notepad_hook_func(self, hwnd, msg, wParam, lParam):
                          if (wParam & 0xFFF0) == SC_KEYMENU and lParam == 0: return False
                          return True
                  
                  MOUSE_WHEEL_HOOK_DEMO = MWHD()
                  

                  Next, the dependent script, MsgHooker.py:

                  # -*- coding: utf-8 -*-
                  
                  import platform
                  from ctypes import (WinDLL, WINFUNCTYPE)
                  from ctypes.wintypes import (HWND, INT, LPARAM, UINT, WPARAM)
                  
                  user32 = WinDLL('user32')
                  
                  GWL_WNDPROC = -4  # used to set a new address for the window procedure
                  
                  LRESULT = LPARAM
                  
                  WndProcType = WINFUNCTYPE(
                      LRESULT,  # return type
                      HWND, UINT, WPARAM, LPARAM  # function arguments
                      )
                  
                  running_32bit = platform.architecture()[0] == '32bit'
                  SetWindowLong = user32.SetWindowLongW if running_32bit else user32.SetWindowLongPtrW
                  SetWindowLong.restype = WndProcType
                  SetWindowLong.argtypes = [ HWND, INT, WndProcType ]
                  
                  class MH(object):
                  
                      def __init__(self,
                              hwnd_to_hook_list,
                              hook_function,  # supplied hook_function must have args:  hwnd, msg, wparam, lparam
                                              #  and must return True/False (False means the function handled the msg)
                              msgs_to_hook_list=None,  # None means ALL msgs
                              ):
                          self.users_hook_fn = hook_function
                          self.msg_list = msgs_to_hook_list if msgs_to_hook_list is not None else []
                          self.new_wnd_proc_hook_for_SetWindowLong = WndProcType(self._new_wnd_proc_hook)  # the result of this call must be a self.xxx variable!
                          self.orig_wnd_proc_by_hwnd_dict = {}
                          for h in hwnd_to_hook_list:
                              self.orig_wnd_proc_by_hwnd_dict[h] = SetWindowLong(h, GWL_WNDPROC, self.new_wnd_proc_hook_for_SetWindowLong)
                  
                      def _new_wnd_proc_hook(self, hwnd, msg, wParam, lParam):
                          retval = True  # assume that this message will go unhandled (by us)
                          need_to_call_orig_proc = True
                          if len(self.msg_list) == 0 or msg in self.msg_list:
                              retval = self.users_hook_fn(hwnd, msg, wParam, lParam)
                              if not retval: need_to_call_orig_proc = False
                          if need_to_call_orig_proc:
                              retval = self.orig_wnd_proc_by_hwnd_dict[hwnd](hwnd, msg, wParam, lParam)
                          return retval
                  
                  1 Reply Last reply Reply Quote 1
                  • Alan KilbornA Alan Kilborn referenced this topic on
                  • Alan KilbornA
                    Alan Kilborn
                    last edited by

                    Script compatibility note for PythonScript2:

                    Find 0x1_0000 in the code and replace with 0x10000.

                    1 Reply Last reply Reply Quote 1
                    • V
                      Valour549
                      last edited by

                      Thank you all for the replies.

                      I have created a suggestion on github here.

                      @Alan-Kilborn How do I use the scripts you created? Kind of a noob here so a step by step would be much appreciated 🙏

                      PeterJonesP 1 Reply Last reply Reply Quote 0
                      • PeterJonesP
                        PeterJones @Valour549
                        last edited by

                        @Valour549 said in Can't rebind mouse buttons/scroll wheel:

                        How do I use the scripts you created? Kind of a noob here

                        As it says near the top of @Alan-Kilborn’s first script,

                        for newbie info on PythonScripts, see https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript

                        1 Reply Last reply Reply Quote 0
                        • V
                          Valour549
                          last edited by

                          @Alan-Kilborn Thank you very much for the script, it’s working great.

                          @PeterJones Thank you for the FAQ guide. I found a typo I think. The highlight parts are meant to say step #4 right?

                          671fa878-d756-4d56-8e6b-67bf53015d46-image.png

                          PeterJonesP 1 Reply Last reply Reply Quote 1
                          • PeterJonesP
                            PeterJones @Valour549
                            last edited by

                            @Valour549 said in Can't rebind mouse buttons/scroll wheel:

                            I found a typo I think. The highlight parts are meant to say step #4 right?

                            Not a typo, but a “forgot to update”. Originally, the “install PythonScript” was “step #0”, which meant that the shortcuts were at step #3. At some point, that changed, and I forgot to update the cross-reference.

                            Fixed.

                            1 Reply Last reply Reply Quote 2
                            • Alan KilbornA
                              Alan Kilborn
                              last edited by

                              I must say that I like the functionality provided by the script myself, and I’ve started to use it. One thing I don’t particularly like, however, is not anything to do with the script, but rather how the NextResult (F4) and PreviousResult (Shift+F4) functionality works. After the last match is encountered, another F4 “wraps around” to the first match. It’s similar for Shift+F4. I find this annoying for reasons I’ve specified HERE. If other users feel the same way, and can publicly state so, maybe we can get an option to control this behavior.

                              1 Reply Last reply Reply Quote 0
                              • Alan KilbornA Alan Kilborn referenced this topic on
                              • First post
                                Last post
                              The Community of users of the Notepad++ text editor.
                              Powered by NodeBB | Contributors