Special characters with unmapped "shortcut" combos
-
can we prevent non-assigned shortcut-like key combos (e.g., SHIFT+CTRL+A) from inserting invisible special characters if they are not mapped to a shortcut?
Yes, it is possible.
Some versions of such a PythonScript have been posted before, but those versions use a callback for when the document is modified, to check for and remove such control characters. This is okay, but I believe the character goes into the undo buffer, so if you undo a change(s), you could get the character back at some point.
The following script is a bit lower level and avoids that possible problem. I call the script
ControlCharsPreventBeingEnteredInText.py
and here is its listing:# -*- coding: utf-8 -*- from __future__ import print_function #------------------------------------------------------------------------------- # references: # https://community.notepad-plus-plus.org/topic/25179/special-characters-with-unmapped-shortcut-combos <-- contains the script below # https://community.notepad-plus-plus.org/topic/18921/ctrl-e-and-ctrl-shift-alt-not-working # possibly the script here: https://community.notepad-plus-plus.org/topic/20471 (see Dec 14, 2020, 4:38 PM posting) # https://community.notepad-plus-plus.org/topic/23734 # https://github.com/notepad-plus-plus/notepad-plus-plus/issues/13279 #------------------------------------------------------------------------------- from Npp import * import ctypes from ctypes import wintypes import platform #------------------------------------------------------------------------------- user32 = ctypes.WinDLL('user32') try: editor1.hwnd editor2.hwnd except AttributeError: notepad.hwnd = user32.FindWindowW(u'Notepad++', None) editor1.hwnd = user32.FindWindowExW(notepad.hwnd, None, u'Scintilla', None) editor2.hwnd = user32.FindWindowExW(notepad.hwnd, editor1.hwnd, u'Scintilla', None) LRESULT = wintypes.LPARAM WndProcType = ctypes.WINFUNCTYPE( LRESULT, # return type wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM # arguments ) running_32bit = platform.architecture()[0] == '32bit' SetWindowLong = user32.SetWindowLongW if running_32bit else user32.SetWindowLongPtrW SetWindowLong.restype = WndProcType SetWindowLong.argtypes = [wintypes.HWND, wintypes.INT, WndProcType] GWL_WNDPROC = -4 WM_CHAR = 0x102 #------------------------------------------------------------------------------- class CCPBEIT(object): def __init__(self): self.new_editor1_wnd_proc_hook_for_SetWindowLong = WndProcType(self.new_editor1_wnd_proc_hook) self.orig_editor1_wnd_proc = SetWindowLong(editor1.hwnd, GWL_WNDPROC, self.new_editor1_wnd_proc_hook_for_SetWindowLong) self.new_editor2_wnd_proc_hook_for_SetWindowLong = WndProcType(self.new_editor2_wnd_proc_hook) self.orig_editor2_wnd_proc = SetWindowLong(editor2.hwnd, GWL_WNDPROC, self.new_editor2_wnd_proc_hook_for_SetWindowLong) def common_editor_wnd_proc_hook(self, hwnd, msg, wParam, lParam): retval = True if msg == WM_CHAR: if 0 <= wParam <= 31 or wParam >= 0x7F: retval = False # set to False if we don't want further processing of this message return retval def new_editor1_wnd_proc_hook(self, hwnd, msg, wParam, lParam): retval = self.common_editor_wnd_proc_hook(hwnd, msg, wParam, lParam) if retval: retval = self.orig_editor1_wnd_proc(hwnd, msg, wParam, lParam) return retval def new_editor2_wnd_proc_hook(self, hwnd, msg, wParam, lParam): retval = self.common_editor_wnd_proc_hook(hwnd, msg, wParam, lParam) if retval: retval = self.orig_editor2_wnd_proc(hwnd, msg, wParam, lParam) return retval #------------------------------------------------------------------------------- CCPBEIT()
The script should work under PythonScript2 or PythonScript3, and on 32-bit or 64-bit.
To set up the script to run upon Notepad++ startup, modify (user)
startup.py
to contain the following line:import ControlCharsPreventBeingEnteredInText
and set PythonScript’s Configuration for Initialisation to be
ATSTARTUP
. -
Should have done Google searching instead of on the forum - my forum search-fu is not quite up to par apparently:
https://community.notepad-plus-plus.org/topic/11233/disable-ascii-control-characters-shortcuts
I already have lots of
CTRL+SHIFT+
keys mapped, the ones I don’t have mapped are:- 6
- B
- H
- I
So in my PythonScript startup, I just added:
SCI_NULL = 2172 keys = ['6', 'B', 'H', 'I'] editor.assignCmdKey(7 + (KEYMOD.SHIFT<<16), SCI_NULL) # Shift+ESC (weird that it's 7 and not 27) for key in keys: editor.assignCmdKey(ord(key) + ((KEYMOD.CTRL|KEYMOD.SHIFT)<<16), SCI_NULL)
Cheers.
-
-
-
@Alan-Kilborn it is work! Thank u very much!!!
i dont understand why Don Ho do not off by default this Special characters with unmapped “shortcut”…
-
@kuzduk-kuzduk said in Special characters with unmapped "shortcut" combos:
i dont understand why Don Ho do not off by default this Special characters with unmapped “shortcut”…
When a new feature is added, existing behavior is maintained for the default for the new feature setting.
So… in this case, before the ability to control it was added, control characters would be typable. With the setting in its default state, typable control characters are maintained.
It is only if you set the setting to the non-default state that there is a behavior change. -
@kuzduk-kuzduk said in Special characters with unmapped "shortcut" combos:
i dont understand why Don Ho do not off by default this Special characters with unmapped “shortcut”…
For clarification: this used to be a problem, like in November 2023 when this Topic was active. But Don Ho released v8.6.5 at the end of March, and that new version contains a fix for this issue, thanks to the work that @Alan-Kilborn put into implementing the fix. So this was fixed before @kuzduk-kuzduk made this post, though you might not have noticed that in the change list for the recent release.
So now, in v8.6.5, there is a new setting
Prevent control character (C0 code) typing into document
:
If you leave it in the default, it will have the old behavior (can type the control codes for unmapped shortcuts); if you checkmark the option, then it will have the desired behavior which was previously obtained through the PythonScript code shared above. You no longer need to run one of those PythonScript scripts if you use the newest version of Notepad++ with the option enabled. -
@PeterJones Thanks, but this doesn’t work for me because I’m using npp 8.5.8
I can’t use 8.6 and higher because they don’t work correctly with the PauseBreak global hotkey: https://community.notepad-plus-plus.org/topic/25582/global- hotkey-pausebreak-not-correct-in-npp-8-6-via-puntoswitcher/3?_=1712842017033
-
@Alan-Kilborn @Alan-Kilborn so sad, but it not work in russian layout: russian keys А…Я not typed symbols in npp 8.5.8. May be this script can be modidfied for given this drawback?
-
@kuzduk-kuzduk said in Special characters with unmapped "shortcut" combos:
Thanks, but this doesn’t work for me because I’m using npp 8.5.8
You have to pick your poison on this: Either use a version that supports the Prevent control character… checkbox, or don’t (and thus you don’t get the functionality).
-
@kuzduk-kuzduk said in Special characters with unmapped "shortcut" combos:
so sad, but it not work in russian layout: russian keys А…Я not typed symbols in npp 8.5.8.
I don’t know what this means, exactly, since I don’t have familiarity with Russian keyboard and their characters that might be different from a US keyboard.
May be this script can be modified for given this drawback?
Perhaps, but that modification would have to be made by you.
-
You earlier said,
i dont understand why Don Ho do not off by default this Special characters with unmapped “shortcut”…
And now you say
Thanks, but this doesn’t work for me because I’m using npp 8.5.8
I am sorry.
Some applications use a model where they are able to release patch fixes to old releases of software; Notepad++ does not work that way. If there are bug fixes, they go in the next revision. So, to be able to get a fix, you have to be willing to update to a new version.
(Yes, I said “willing” , not “able”, because despite your assertion, your choice to not upgrade Notepad++ instead of choosing to remap the weird PauseBreak global shortcut to something other than PauseBreak is just that… your choice. And it’s your choice to prioritize keeping PauseBreak over keeping )
so sad, but [Alan’s script does] not work in russian layout
As an alternative, figure out all the
Ctrl
sequences that type ASCII control characters based on your setup. Then create a NULL macro for each of those. A “NULL macro” is a “do nothing” macro. The scintilla action 2172 is a do-nothing/no-op/null-op action. So, you could insert a macro like the following intoshortcuts.xml
, then save and restart:<Macro name="NULL-CTRL-R" Ctrl="yes" Alt="no" Shift="no" Key="82" FolderName="Control Remaps"> <Action type="0" message="2172" wParam="0" lParam="0" sParam="" /> </Macro>
This mapped macro it would stop
Ctrl+R
from inserting theDC2
ASCII 18 control character, and instead run a no-op command, making it “do nothing”.Creating multiple such macros, one for each unmapped sequence, would get rid of the accidental ASCII control characters in your documents. (And I showed putting it in
FolderName="Control Remaps"
, so they would all show up in a sub-menu of Macros instead of cluttering your main Macros menu)-----
update: earlier in this discussion, @Michael-Vincent linked to this old discussion. It turns out, my suggestion is essentially what Claudia suggested 8 years ago (good to know that her excellent answers have apparently become part of my subconscious mind), though she chose message 0 instead of 2172. And in this February’s replies to that ancient thread, @mkupper showed a mapping with lots of macros that show how to do the “one macro for each unmapped sequence” that I just suggested today. (Though I would again recommend changing to 2172, and I’d add the FolderName attribute to de-clutter the Macro menu.) And @Alan-Kilborn already made the
2172
correction in that other discussion. So basically, it turns out I said nothing new anywhere in the second half of this post of mine. ;-)