Community
    • Login

    Can't rebind mouse buttons/scroll wheel

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    13 Posts 4 Posters 515 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.
    • 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