List of all assigned keyboard shortcuts
-
Hi @guy038
I have been looking for a similar table for a long time. Can I see the results of your labors? jang.spb@gmail.com -
If I could iterate through it in a python code snippet would work
Just in case some else has the same requirement
import ctypes import ctypes.wintypes as wintypes user32 = ctypes.WinDLL('user32', use_last_error=True) NPP_HANDLE = user32.FindWindowW(u'Notepad++', None) MIIM_SUBMENU = 4 MIIM_STRING = 64 class MENUITEMINFO(ctypes.Structure): _fields_ = [ ("cbSize" , wintypes.UINT), ("fMask" , wintypes.UINT), ("fType" , wintypes.UINT), ("fState" , wintypes.UINT), ("wID" , wintypes.UINT), ("hSubMenu" , wintypes.HMENU), ("hbmpChecked" , wintypes.HBITMAP), ("hbmpUnchecked", wintypes.HBITMAP), ("dwItemData" , wintypes.LPVOID), # ULONG_PTR ("dwTypeData" , wintypes.LPWSTR), ("cch" , wintypes.UINT), ("hbmpItem" , wintypes.HBITMAP),] npp_menu_handle = user32.GetMenu(NPP_HANDLE) def get_configured_shortcuts(menu_handle): menu_items = user32.GetMenuItemCount(menu_handle) for item in range(menu_items): uitem = item fByPosition = True mii = MENUITEMINFO() mii.cbSize = ctypes.sizeof(mii) mii.fMask = MIIM_STRING | MIIM_SUBMENU lpmii = ctypes.byref(mii) user32.GetMenuItemInfoW(menu_handle, uitem, fByPosition, lpmii) if mii.hSubMenu: get_configured_shortcuts(mii.hSubMenu) mii.dwTypeData = ctypes.cast(ctypes.create_unicode_buffer(mii.cch+1), ctypes.c_wchar_p) mii.cch = mii.cch+1 mii.cbSize = ctypes.sizeof(mii) user32.GetMenuItemInfoW(menu_handle, uitem, fByPosition, lpmii) if '\t' in mii.dwTypeData: shortcuts.append(mii.dwTypeData.split('\t')) shortcuts = [] for i in range(user32.GetMenuItemCount(npp_menu_handle)): submenu_handle = user32.GetSubMenu(npp_menu_handle, i) get_configured_shortcuts(submenu_handle) _max_length = len(max([x[0] for x in shortcuts], key=len)) notepad.new() editor.setText('\r\n'.join(['{0:<{2}} : {1}'.format(x[0], x[1], _max_length) for x in shortcuts]))
-
Interesting approach to get some of the shortcuts. :)
-
Why some? What did I miss?
-
Well, just as one example, most (if not all) Scintilla commands that have shortcuts in Shortcut Mapper are not output by the script.
-
You are right, how could I miss those?
Damn it. -
I have seen this thread before, but didn’t have any new ideas about it. When I saw your recent efforts, I thought it was interesting as I hadn’t thought about that kind of approach. So now I’m thinking, if the Shortcut Mapper info is left in memory (after being invoked once?), could some ctypes magic find it and report it? I don’t know enough about the internals, IIRC doesn’t it use something called
BabyGrid
or something like that? -
if the Shortcut Mapper info is left in memory (after being invoked once?), could some ctypes magic find it and report it
Not sure about it, digging in npps memory seems to be a dangerous place :-D
-
Maybe it would be best if N++ itself had a feature to export this infos. :P
-
the shortcut mapper dialog seems to be the trusted source in this situation, isn’t it?
As it is a blocking dialog we start it in a different thread and then searching for the tabsyscontrol
and then with some magic ctypes we should be able to get the shortcuts currently configured.
Hmm, fun project - I guess I’ll give it a try :-) -
unfortunately TCM_SETCURSEL doesn’t trigger babygrid to be updated therefore I had to use keybd_event but seems to work.
import ctypes import ctypes.wintypes as wintypes from threading import Thread import time user32 = ctypes.WinDLL('user32', use_last_error=True) def start_sk_dialog(): notepad.menuCommand(MENUCOMMAND.SETTING_SHORTCUT_MAPPER) sk_mapper = Thread(target=start_sk_dialog) sk_mapper.start() time.sleep(1) WM_USER = 1024 WM_CLOSE = 16 TCM_FIRST = 4864 TCM_GETITEMCOUNT = (TCM_FIRST + 4) TCM_SETCURSEL = (TCM_FIRST + 12) BABYGRID_USER = (WM_USER + 7000) BGM_GETCELLDATA = BABYGRID_USER + 4 BGM_GETROWS = BABYGRID_USER + 23 class BGCELL(ctypes.Structure): _fields_ = [('row', wintypes.INT), ('col', wintypes.INT)] cell_buffer = ctypes.create_unicode_buffer(1000) bgcell = BGCELL() sk_mapper_hwnd = user32.FindWindowW(None, u'Shortcut mapper') sys_tab_hwnd = user32.FindWindowExW(sk_mapper_hwnd, None, u'SysTabControl32',None) item_count = user32.SendMessageW(sys_tab_hwnd, TCM_GETITEMCOUNT, 0, 0) babygrid = user32.FindWindowExW(sk_mapper_hwnd, None, u'BABYGRID',None) shortcuts = [] for tab in range(item_count): rows = user32.SendMessageW(babygrid, BGM_GETROWS, 0, 0) print 'rows', rows for i in range(1, rows+1): shortcut = [] for j in range(1,3): bgcell.row = i bgcell.col = j res = user32.SendMessageW(babygrid, BGM_GETCELLDATA, ctypes.byref(bgcell), cell_buffer) shortcut.append(cell_buffer.value) shortcuts.append(shortcut) user32.SetForegroundWindow(sk_mapper_hwnd) user32.SendMessageW(sys_tab_hwnd, TCM_SETCURSEL, tab, 0) user32.keybd_event(0x27,0,0,0) user32.keybd_event(0x27,0,2,0) user32.SendMessageW(sk_mapper_hwnd, WM_CLOSE, 0, 0) _max_length = len(max([x[0] for x in shortcuts if x[1]], key=len)) notepad.new() editor.setText('\r\n'.join(['{0:<{2}} : {1}'.format(x[0], x[1], _max_length) for x in shortcuts if x[1]]))
-
Hmmm, poking around this a little bit…
I get zero returned from the
FindWindowW
call, even though the window is opened by the script. Looking closer, I see in the call it is looking forShortcut mapper
but my window title isShortcut Mapper
. But changing the script to have a capitalM
makes no difference; zero still returned… -
strange, which npp version do you use?
-
I tried it with 7.6.6(64bit) and 7.7.1(32bit).
And title is on both Shortcut mapper -
@Ekopalypse said:
And title is on both Shortcut mapper
In answering this question, I went down a road with a fork in it. I took the fork.
Seriously, though, I’m using 7.7.1 32-bit.
At first I thought, well, okay, maybe I changed
Shortcut mapper
toShortcut Mapper
in myenglish_customizable.xml
file. So I grabbed a fresh portable 7.7.1 32-bit and ran it and I seeShortcut mapper
. Then I change the Localization setting toEnglish
and I seeShortcut Mapper
. TryingEnglish (customizable)
I also seeShortcut Mapper
.Note: In my real copy of N++ I also run with
english_customizable.xml
.So I suppose I now know where the
M
versusm
appears from. Re-running my fresh copy of N++ after choosingEnglish
from the menu results inShortcut mapper
again, so I’m not sure but really would like to understand what it takes to make a Localization choice “stick”… But that’s another issue. Maybe if one chooses anything besidesEnglish
, it sticks, but if you chooseEnglish
nothing happens on the next run, because the default language is supposed to be that, and in reality the base localization and the english.xml file, which probably should be the same…aren’t. Little, subtle differences… But all that, as I said, is a different issue…I dabbled a bit more with the script and I think I see why I’m getting zero for the hwnd. If I increase the sleep time to something like 5 seconds and run the script, it seems like I should see the Shortcut Mapper window pop up fairly quickly and then somewhat of a delay before the rest of the code runs. In reality the window popping up seems to be delayed by the 5 seconds as well. So I suspect that maybe the window really isn’t there yet for
FindWindowW
to find it…? -
that localization thing confuses me every time I use it.
What happens if you use this
from threading import Thread import time def start_sk_dialog(): notepad.menuCommand(MENUCOMMAND.SETTING_SHORTCUT_MAPPER) sk_mapper = Thread(target=start_sk_dialog) sk_mapper.start() time.sleep(5) print 'done'
For me it opens the dialog very quickly and after 5 seconds I see the done
in the console but dialog still open. -
@Ekopalypse said:
that localization thing confuses me every time I use it.
LOL.
I think I solved the mystery of the script. I have a little script-runner script that allows me to run the current .py file, so I don’t have to always go
Plugins
>Pythonscript
>Scripts
> (find my script) over and over with the mouse. This is handy for trying out temporary scripts that I haven’t bound to a keycombo (e.g. yours).If I DO run your script via the menu method and NOT via my script-runner, all goes as planned and I achieve your list of keycombinations! Well done! I’m not sure why my script-runner interferes, but I don’t care enough to go and figure that out. But…sorry for creating additional trouble for you due to all the troubleshooting, that was completely my fault.
-
I’m calling this thread incomplete until someone provides the full listing of a default set of keycombo assignments for Notepad++ 7.7.1, as output by the script shown above. As no one has done that yet, well… :
New : Ctrl+N Open... : Ctrl+O Reload from Disk : Ctrl+R Save : Ctrl+S Save As... : Ctrl+Alt+S Save All : Ctrl+Shift+S Close : Ctrl+W Close All : Ctrl+Shift+W Print... : Ctrl+P Exit : Alt+F4 Restore Recent Closed File : Ctrl+Shift+T UPPERCASE : Ctrl+Shift+U lowercase : Ctrl+U Proper Case : Alt+U Proper Case (blend) : Alt+Shift+U Sentence case : Ctrl+Alt+U Sentence case (blend) : Ctrl+Alt+Shift+U Split Lines : Ctrl+I Join Lines : Ctrl+J Move Up Current Line : Ctrl+Shift+Up Move Down Current Line : Ctrl+Shift+Down Insert Blank Line Above Current : Ctrl+Alt+Enter Insert Blank Line Below Current : Ctrl+Alt+Shift+Enter Toggle Single Line Comment : Ctrl+Q Single Line Comment : Ctrl+K Single Line Uncomment : Ctrl+Shift+K Block Comment : Ctrl+Shift+Q Function Completion : Ctrl+Spacebar Path Completion : Ctrl+Alt+Spacebar Word Completion : Ctrl+Enter Function Parameters Hint : Ctrl+Shift+Spacebar Column Editor... : Alt+C Find... : Ctrl+F Find in Files... : Ctrl+Shift+F Find Next : F3 Find Previous : Shift+F3 Select and Find Next : Ctrl+F3 Select and Find Previous : Ctrl+Shift+F3 Find (Volatile) Next : Ctrl+Alt+F3 Find (Volatile) Previous : Ctrl+Alt+Shift+F3 Replace... : Ctrl+H Incremental Search : Ctrl+Alt+I Search Results Window : F7 Previous Search Result : Shift+F4 Next Search Result : F4 Go to... : Ctrl+G Go to Matching Brace : Ctrl+B Select All Between Matching Braces : Ctrl+Alt+B 1st Style : Ctrl+Shift+1 2nd Style : Ctrl+Shift+2 3rd Style : Ctrl+Shift+3 4th Style : Ctrl+Shift+4 5th Style : Ctrl+Shift+5 Find Style : Ctrl+Shift+0 1st Style : Ctrl+1 2nd Style : Ctrl+2 3rd Style : Ctrl+3 4th Style : Ctrl+4 5th Style : Ctrl+5 Find Style : Ctrl+0 Toggle Bookmark : Ctrl+F2 Next Bookmark : F2 Previous Bookmark : Shift+F2 Toggle Full Screen Mode : F11 Post-It : F12 1st Tab : Ctrl+Numpad 1 2nd Tab : Ctrl+Numpad 2 3rd Tab : Ctrl+Numpad 3 4th Tab : Ctrl+Numpad 4 5th Tab : Ctrl+Numpad 5 6th Tab : Ctrl+Numpad 6 7th Tab : Ctrl+Numpad 7 8th Tab : Ctrl+Numpad 8 9th Tab : Ctrl+Numpad 9 Next Tab : Ctrl+Page down Previous Tab : Ctrl+Page up Move Tab Forward : Ctrl+Shift+Page down Move Tab Backward : Ctrl+Shift+Page up Switch to previous document : Ctrl+Shift+Tab Switch to next document : Ctrl+Tab Hide Lines : Alt+H Focus on Another View : F8 Fold All : Alt+0 Unfold All : Alt+Shift+0 Collapse Current Level : Ctrl+Alt+F Uncollapse Current Level : Ctrl+Alt+Shift+F 1 : Alt+1 2 : Alt+2 3 : Alt+3 4 : Alt+4 5 : Alt+5 6 : Alt+6 7 : Alt+7 8 : Alt+8 1 : Alt+Shift+1 2 : Alt+Shift+2 3 : Alt+Shift+3 4 : Alt+Shift+4 5 : Alt+Shift+5 6 : Alt+Shift+6 7 : Alt+Shift+7 8 : Alt+Shift+8 Text Direction RTL : Ctrl+Alt+R Text Direction LTR : Ctrl+Alt+L Toggle macro record : Ctrl+Shift+R Playback : Ctrl+Shift+P Run... : F5 About Notepad++ : F1 Trim Trailing Space and Save : Alt+Shift+S Trim Trailing Space and Save : Alt+F1 SCI_CUT : Ctrl+X or Shift+DEL SCI_COPY : Ctrl+C or Ctrl+INS SCI_PASTE : Ctrl+V or Shift+INS SCI_SELECTALL : Ctrl+A SCI_CLEAR : DEL SCI_UNDO : Ctrl+Z or Alt+Backspace SCI_REDO : Ctrl+Y or Ctrl+Shift+Z SCI_NEWLINE : Enter or Shift+Enter SCI_TAB : Tab SCI_BACKTAB : Shift+Tab SCI_ZOOMIN : Ctrl+Num + SCI_ZOOMOUT : Ctrl+Num - SCI_SETZOOM : Ctrl+Num / SCI_SELECTIONDUPLICATE : Ctrl+D SCI_EDITTOGGLEOVERTYPE : INS SCI_LINEDOWN : Down SCI_LINEDOWNEXTEND : Shift+Down SCI_LINEDOWNRECTEXTEND : Alt+Shift+Down SCI_LINESCROLLDOWN : Ctrl+Down SCI_LINEUP : Up SCI_LINEUPEXTEND : Shift+Up SCI_LINEUPRECTEXTEND : Alt+Shift+Up SCI_LINESCROLLUP : Ctrl+Up SCI_PARADOWN : Ctrl+] SCI_PARADOWNEXTEND : Ctrl+Shift+] SCI_PARAUP : Ctrl+[~~~
-
Hmmm, well there seems to be some gremlins in the machinery in the above script/listing, as
Trim Trailing Space and Save
is listed twice (the second appearance it is tied toGet PHP help
’s default keycombo), and the defaultRun commands
ofGet PHP help
,Wikipedia Search
, andOpen file in another instance
don’t appear at all… :( -
looks like a timing issue, seems that user32.keybd_event returns to fast.
Put a time.sleep(.1) after the second user32.keybd_event and it should be ok.