Notepad++ box-selection hotkey no longer works

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Aspiring_AHKer
Posts: 4
Joined: 23 Oct 2017, 10:17

Notepad++ box-selection hotkey no longer works

23 Oct 2017, 10:26

Hello folks. I've been using AHK for a while and at some point, one of my favorite hotkeys stopped working. In Notepad++, I mapped the middle mouse button to Alt+LButton (box selection). I also mapped the shifted version. These used to work, but for some reason, they don't anymore. My other Notepad++ hotkeys are working. I'd appreciate any advice you can provide.

Code: Select all

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTEPAD++ HOTKEYS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#If WinActive("ahk_exe " "notepad++.exe")

	// Allows middle/thumb button to be used for box selection
	MButton::!LButton
	
	// If you've already clicked somewhere, you can Shift+middle/thumb to box select to a new point
	+MButton::+!LButton
	
	// Ctrl+Shift+A will select a line
	^+a::
		Send {Home down}{Home up}{Shift down}{End down}{End up}{Shift up}
	Return
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Notepad++ box-selection hotkey no longer works

23 Oct 2017, 17:16

Does Alt+LButton still work when done manually? I wonder if an update to Notepad++ disabled this functionality for some reason, or if you downgraded to a version without it? I had no idea about it myself, but just tested it and I believe it's working with manually pressing Alt+LButton. I'm on Notepad++ v6.7.9.2 which may not be the most recent (I usually reject update prompts).

You also mention that other hotkeys, which I assume the ^+a is an example of, still work. I just want to make sure you did test those since the box-selection problems came up. I would think maybe you launched Notepad++ as an administrator program if it needed permission to edit files in protected folders. In which case, your AHK scripts would also need the elevated/administrator permissions to interact with Notepad++.

It may be possible that an AHK update broke this syntax: #If WinActive("ahk_exe " "notepad++.exe") because it is a bit odd to put two consecutive strings in that way; I much more often see WinActive("ahk_exe notepad++.exe"). But again, if other hotkeys meant to work only in AHK are still working, then that is unlikely an issue.
Aspiring_AHKer
Posts: 4
Joined: 23 Oct 2017, 10:17

Re: Notepad++ box-selection hotkey no longer works

24 Oct 2017, 15:30

Hi Exaskryz! Alt+LButton does work.

I don't think the problem is with the AHK script itself. I thought it might be related to Logitech SetPoint and my Logitech M705. I have the thumb button mapped to middle mouse button. I fiddled with the settings and reinstalled Setpoint, but that didn't resolve it. With SetPoint off, the thumb button does nothing, and the middle mouse button still behaves inconsistently for this hotkey. My testing seems to have eliminated SetPoint and the mouse as the culprits.

Confusingly, [MButton::!LButton] sometimes works as expected in Notepad++, with a success rate of ~50%. If I repeated try highlighting with MButton in Notepad++, one second it'll box select as expected and the next it'll act as though I'm using LButton. It's seriously like flipping a coin!

Both (thumb and middle buttons) behave as expected when I'm in Explorer, where I mapped MButton to "move up a folder". There's no coin flip there.

It's not isolated to Notepad++ either. A similar problem occurs when I map [MButton::!LButton] in Android Studio. Alt+LButton box selects as expected, while MButton seems to always be interpreted as LButton - no coin flip like there is in Notepad++. As a test, mapping [MButton::g] and [MButton::+g] both work as expected in both editors.

------

This is driving me crazy! I've tried using HydraMouse to remap the button, but that didn't help.
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Notepad++ box-selection hotkey no longer works

24 Oct 2017, 17:00

Weird. Do you have any other hotkeys involved that use Alt?

I wonder, what happens if you explicitly write your remap out like this hotkey:

Code: Select all

*MButton::
Send {Blind}{LAlt down}{LButton down}
KeyWait, MButton
Send {Blind}{LButton up}{LAlt up}
return
Aspiring_AHKer
Posts: 4
Joined: 23 Oct 2017, 10:17

Re: Notepad++ box-selection hotkey no longer works

25 Oct 2017, 08:46

You are a god among men, Exaskryz!


Thanks, that worked perfectly. Now I've learned how to use {Blind} and KeyWait too, which will help me in the future. :D

Any idea why the previous hotkey was so unpredictable? It's not too important now that you've helped me get this working, but I am still curious.

Here's my full ~600 line script - hopefully somebody else can find something useful to them in here (Exaskryz: you've been immortalized in a comment for your assistance):

Code: Select all

#CommentFlag //  ; Change to C++ comment style.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
███    ██  ██████  ████████ ███████ ███████
████   ██ ██    ██    ██    ██      ██
██ ██  ██ ██    ██    ██    █████   ███████
██  ██ ██ ██    ██    ██    ██           ██
██   ████  ██████     ██    ███████ ███████
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================================================================
// This AutoHotkey script provides lots of functionality, which I will eventually summarize here.
// 
// You'll need to know these symbols to understand what's going on:
//    # = Windows
//    ! = Alt
//    ^ = Ctrl
//    + = Shift
//    
//    & = Combines keys in any order
//    < = Use left (Alt/Ctrl/Shift)
//    > = Use right (Alt/Ctrl/Shift)
//
//    ~ = When the hotkey fires, its key's native function will not be blocked (hidden from the system)
//    * = Wildcard: Fire the hotkey even if extra modifiers are being held down
//
//    $ = This is usually only necessary if the script uses the Send command to send the keys that comprise the hotkey
//        itself, which might otherwise cause it to trigger itself. The $ prefix forces the keyboard hook to be used to
//        implement this hotkey, which as a side-effect prevents the Send command from triggering it.
//
//
// More advanced stuf:
//
//    {Blind} = When {Blind} is the first item in the string, the program avoids releasing Alt/Control/Shift/Win if they
//              started out in the down position. For example, the hotkey +s::Send {Blind}abc would send ABC rather than
//              abc because the user is holding down the Shift key.
//
//    KeyWait = Waits for a key or mouse/joystick button to be released or pressed down.
//                 KeyWait, KeyName [, Options]
//
//
// Misc notes:
//    - The first comma can be omitted from most commands
//    - Sending double slashes is a hassle, so I've been sending them one at a time. Two alternatives:
//        - Send, %str__two_slashes%{Enter}{ASC 47}{ASC 47}
//
// DOCS:
//    https://www.autohotkey.com/docs/KeyList.htm
//    https://www.autohotkey.com/docs/Hotkeys.htm
//    https://www.autohotkey.com/docs/commands/Send.htm
//    https://www.autohotkey.com/docs/misc/Macros.htm
//
// Forums:
//    https://autohotkey.com/boards/
//======================================================================================================================





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
 ██████  ██████  ███    ██ ███████ ██  ██████
██      ██    ██ ████   ██ ██      ██ ██
██      ██    ██ ██ ██  ██ █████   ██ ██   ███
██      ██    ██ ██  ██ ██ ██      ██ ██    ██
 ██████  ██████  ██   ████ ██      ██  ██████
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================================================================
// Note that any function that wants to use these variables must have global as its first line.
//======================================================================================================================

dir__base := "C:/Dev/### WAREHOUSE ###/Scripting/"
dir__ahk  := dir__base . "AutoHotkey/"
dir__bat  := dir__base . "BATs/"
dir__python = "C:/Dev/### WAREHOUSE ###/Scripting/CodeAligner/ScriptCallers"

str__two_slashes = {ASC 47}{ASC 47}

// This is only meant to be put in the clipboard. It can't be sent directly.
str__comment_block = /***********************************************************************************************************************`r`n *`r`n **********************************************************************************************************************/`r`n

// Three non-breaking spaces. The bullets use NBSPs too.
str__indent =    
str__bullet_1 = ■ 
str__bullet_2 =    ► 
str__bullet_3 =       • 

// Use this to print a NBSP: {ASCII 0160}





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
 ██████  ██████  ██████  ███████     ██   ██  ██████  ████████ ██   ██ ███████ ██    ██ ███████
██      ██    ██ ██   ██ ██          ██   ██ ██    ██    ██    ██  ██  ██       ██  ██  ██
██      ██    ██ ██████  █████       ███████ ██    ██    ██    █████   █████     ████   ███████
██      ██    ██ ██   ██ ██          ██   ██ ██    ██    ██    ██  ██  ██         ██         ██
 ██████  ██████  ██   ██ ███████     ██   ██  ██████     ██    ██   ██ ███████    ██    ███████
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================================================================
// ALERT USER WHEN THIS SCRIPT IS LOADED
//     Note: go to Sound > Sounds and disable the Notification sound
//======================================================================================================================
#SingleInstance Force
#installKeybdHook
#Persistent
	Menu, Tray, Icon , Shell32.dll, 25, 1
	TrayTip, AutoHotKey, Started, , 1

	HideTrayTip()
Return



//======================================================================================================================
// HOW TO MANAGE THIS SCRIPT - Ctrl+Win+Alt+R reloads, Ctrl+Alt+Win+E edits
//======================================================================================================================
^#!r::Reload
^#!e::Edit



//======================================================================================================================
// Stupid testing hotkey - Shift+F11 shows a box with clipboard contents.
//======================================================================================================================
+F11::
{
	SplashTextOn, 800, 800, Clipboard, The clipboard contains:`n`n%clipboard%
	WinMove, Clipboard, , 0, 0  // Move the splash window to the top left corner.
	Msgbox, Press OK to dismiss the SplashText
	SplashTextOff
	Return
}



//======================================================================================================================
// CONNECT TO VPNs WITH Alt+F12 (US) AND Ctrl+F12 (Canada). Shift+F12 starts WAMP.
//======================================================================================================================
^F12::
{
	RunSilentBAT("ConnectToVPN_Canada.bat")
	TrayTip, VPN - Canadian Data Center, Connecting, , 1
	HideTrayTip()
	Return
}
!F12::
{
	RunSilentBAT("ConnectToVPN_US.bat")
	TrayTip, VPN - US Data Center, Connecting, , 1
	HideTrayTip()
	Return
} 
^!F12::
{
	TrayTip, Info, Connect to VPNs with: Alt+F12 (US) or Ctrl+F12 (Canada), , 1
}
+F12::
{
	Run, C:\Dev\wamp64\wampmanager.exe
	Return
}



//======================================================================================================================
// COPY, OPEN CHROME AND SEARCH - Ctrl+Shift+C
//======================================================================================================================
^+c::
{
	Send, ^c
	Sleep 50
	Run, http://www.google.com/search?q=%clipboard%
	Return
}





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
███████ ██████  ███████  ██████ ██  █████  ██          ██   ██  ██████  ████████ ██   ██ ███████ ██    ██ ███████
██      ██   ██ ██      ██      ██ ██   ██ ██          ██   ██ ██    ██    ██    ██  ██  ██       ██  ██  ██
███████ ██████  █████   ██      ██ ███████ ██          ███████ ██    ██    ██    █████   █████     ████   ███████
     ██ ██      ██      ██      ██ ██   ██ ██          ██   ██ ██    ██    ██    ██  ██  ██         ██         ██
███████ ██      ███████  ██████ ██ ██   ██ ███████     ██   ██  ██████     ██    ██   ██ ███████    ██    ███████
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================================================================
// MIDDLE MOUSE BUTTON GOES UP IN EXPLORER - Ctrl+RButton opens ConEmu
//======================================================================================================================
#IfWinActive, ahk_class CabinetWClass
	~MButton::
	{
		Send !{Up}
		Return
	}
	^RButton::
	{
		ClipSaved := ClipboardAll
		Send !d
		Sleep 10
		Send ^c
		Run "C:/Dev/ConEmu/ConEmu64.exe"
		
		// We want an exact match
		SetTitleMatchMode, 3
		
		// Wait a moment for the window to load, then move it (it was appearing offscreen)
		Sleep 250
		WinMove, cmd, , 0, 0
		
		IfWinExist, cmd
			WinActivate
		
		Return
	}
#IfWinActive



//======================================================================================================================
// WINDOWS KEY + H TOGGLES HIDDEN FILES -- Doesn't currently seem to work
//======================================================================================================================
#h:: 
	RegRead, HiddenFiles_Status, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, Hidden 
	If HiddenFiles_Status = 2
		RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, Hidden, 1 
	Else
		RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, Hidden, 2 
		WinGetClass, eh_Class,A
	If (eh_Class = "#32770" OR A_OSVersion = "WIN_VISTA")
		send, {F5}
	Else PostMessage, 0x111, 28931,,, A
Return



//======================================================================================================================
// NOTEPAD++ HOTKEYS
//======================================================================================================================
#If WinActive("ahk_exe " "notepad++.exe")

	// The * lets this hotkey work with extra modifier keys. By adding {Blind}, AHK will avoid releasing Shift if the
	// user is holding it. This lets this single hotkey handle click-and-drag box selection and (Shifted) box-select-to.
	// Thanks Exaskryz!
	*MButton::
		Send {Blind}{LAlt down}{LButton down}
		KeyWait, MButton
		Send {Blind}{LButton up}{LAlt up}
	return
	
	
	// Allows middle/thumb button to be used for box selection (Alt + LButton). This doesn't work as intended.
	//MButton::!LButton
	
	// After clicking somewhere, you can Shift+middle/thumb to box select to a new point. Doesn't work as intended.
	//+MButton::+!LButton
	
	
	// Ctrl+Shift+A will select a line
	^+a::
		Send {Home down}{Home up}{Shift down}{End down}{End up}{Shift up}
	Return
	
	
	//------------------------------------------------------------------------------------------------------------------
	// BULLET - LEVEL 1
	//------------------------------------------------------------------------------------------------------------------
	F1::
	{
		// Save clipboard contents for later
		original_clip_contents := ClipboardAll
		
		clipboard = %str__bullet_1%
		Send, ^v
		
		// Revert to original clipboard contents
		Clipboard := original_clip_contents
		
		Return
	}
	
	
	//------------------------------------------------------------------------------------------------------------------
	// BULLET - LEVEL 2
	//------------------------------------------------------------------------------------------------------------------
	F2::
	{
		// Save clipboard contents for later
		original_clip_contents := ClipboardAll
		
		clipboard = %str__bullet_2%
		Send, ^v
		
		// Revert to original clipboard contents
		Clipboard := original_clip_contents
		
		Return
	}
	
	
	//------------------------------------------------------------------------------------------------------------------
	// BULLET - LEVEL 3
	//------------------------------------------------------------------------------------------------------------------
	F3::
	{
		// Save clipboard contents for later
		original_clip_contents := ClipboardAll
		
		clipboard = %str__bullet_3%
		Send, ^v
		
		// Revert to original clipboard contents
		Clipboard := original_clip_contents
		
		Return
	}
	
#IfWinActive



//======================================================================================================================
// ANDROID STUDIO HOTKEYS
//======================================================================================================================
#If WinActive("ahk_exe " "studio64.exe")
	
	// Allows middle/thumb button to be used for box selection (Alt + LButton)
	MButton::+g
	
	
	// F12 will send Ctrl+Shift+F12, which finds last change location
	F12::
		Send, ^+{BS}
	Return
	
	
	// F7 will send Shift+F6, which does a [refactor > rename]
	F7::
		Send, +{F6}
	Return
	
#IfWinActive



//======================================================================================================================
// ATOM HOTKEYS
//======================================================================================================================
#If WinActive("ahk_exe " "atom.exe")

	// Ctrl+Shift+A will select line content (not including indenting whitespace)
	^+a::
		Send {Home down}{Home up}{Shift down}{End down}{End up}{Shift up}
	Return
	
#IfWinActive



//======================================================================================================================
// ECLIPSE HOTKEYS
//======================================================================================================================
#If WinActive("ahk_exe " "eclipse.exe")
	
	// Runs file in Eclipse as a Java application
	ScrollLock::
		Send {Alt down}{Shift down}x{Shift up}{Alt up}
		sleep 1000
		Send j
	Return
	
#IfWinActive





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
██ ███    ██ ███████ ███████ ██████  ████████     ████████ ███████ ██   ██ ████████
██ ████   ██ ██      ██      ██   ██    ██           ██    ██       ██ ██     ██
██ ██ ██  ██ ███████ █████   ██████     ██           ██    █████     ███      ██
██ ██  ██ ██      ██ ██      ██   ██    ██           ██    ██       ██ ██     ██
██ ██   ████ ███████ ███████ ██   ██    ██           ██    ███████ ██   ██    ██
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================================================================
// This types "// TODO: REMOVE", hits enter, then removes the "// " that Atom automatically inserts.
//======================================================================================================================
^Insert::
{
	Send, /
	Send, /
	Send, {Space}TODO: REMOVE
	Send, {Enter}{Backspace}{Backspace}{Backspace}
	Return
}



//======================================================================================================================
// This types "// TODO: REMOVE"
//======================================================================================================================
!Insert::
{
	Send, /
	Send, /
	Send, {Space}TODO: REMOVE
	Return
}



//======================================================================================================================
// This hits enter, then types "// TODO: REMOVE"
//======================================================================================================================
+Insert::
{
	Send, {Enter}//{Space}TODO: REMOVE
	Return
}



//======================================================================================================================
// TEST
//======================================================================================================================
+^Insert::
{
	clipboard = %str__comment_block%
	Send, ^v
	Return
}





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
 ██████  █████  ██      ██          ███████  ██████ ██████  ██ ██████  ████████ ███████
██      ██   ██ ██      ██          ██      ██      ██   ██ ██ ██   ██    ██    ██
██      ███████ ██      ██          ███████ ██      ██████  ██ ██████     ██    ███████
██      ██   ██ ██      ██               ██ ██      ██   ██ ██ ██         ██         ██
 ██████ ██   ██ ███████ ███████     ███████  ██████ ██   ██ ██ ██         ██    ███████
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//======================================================================================================================
// These functions call Python scripts to act on the current selection. Your original clipboard is recovered afterwards.
// 
// These all call short scripts that go on to call the actual scripts in CodeAligner. This is because I'm not sure how
// to call functions within a module from AHK.
// 
// For tasks which can have spaces inserted before or after, there will be separate versions of the dummy scripts, which
// will pass in the appropriate please_insert_before parameter (or leave it out and let it default to True).
// 
// align_via_clip__comments
// align_via_clip__ternary
// align_via_clip__equals__before
// align_via_clip__colon__after
//======================================================================================================================

^!q::
{
	Result := invoke_python_on_selection("align_via_clip__comments.pyw")
	Return
}

^!w::
{
	Result := invoke_python_on_selection("align_via_clip__ternary.pyw")
	Return
}

^!e::
{
	Result := invoke_python_on_selection("align_via_clip__equals.pyw")
	Return
}

^!r::
{
	Result := invoke_python_on_selection("align_via_clip__colon__after.pyw")
	Return
}





////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
███████ ██    ██ ███    ██  ██████ ████████ ██  ██████  ███    ██ ███████
██      ██    ██ ████   ██ ██         ██    ██ ██    ██ ████   ██ ██
█████   ██    ██ ██ ██  ██ ██         ██    ██ ██    ██ ██ ██  ██ ███████
██      ██    ██ ██  ██ ██ ██         ██    ██ ██    ██ ██  ██ ██      ██
██       ██████  ██   ████  ██████    ██    ██  ██████  ██   ████ ███████
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//======================================================================================================================
// This function wraps the next one. It makes things more concise and lets us pass in a filename instead of a path, as
// it uses the dir__python defined in the config section.
//======================================================================================================================
invoke_python_on_selection(script_name)
{
	// TODO: Should we add ".pyw"?
	return, copy__run_python__paste__recover_clip(dir__python + script_name)
}



//======================================================================================================================
// This function saves the clipboard, runs the provided script, pastes the result, then reverts to the original
// clipboard.
// 
// TODO: Reselect what we just pasted
//======================================================================================================================
copy__run_python__paste__recover_clip(script_path)
{
	// Save clipboard contents for later
	original_clip_contents := ClipboardAll
	
	// Put current selection in our clipboard
	Clipboard=
		Send, ^c
	
	// Delay
	sleep 200
	
	// Now we call the script that was passed in
	Run %script_path%
	
	// Delay
	sleep 200
	
	// This holds the new clipboard value
	modified_selected_text := Clipboard
	
	// Paste the modified version of the selected text
	Send, ^v
	
	// Delay
	sleep 200
	
	// Revert to original clipboard contents
	Clipboard := original_clip_contents
	
	// Return modified version of selected text
	return, modified_selected_text
}



//======================================================================================================================
// This function uses a simple Visual Basic script to run BAT files silently, with no annoying empty popup window.
//======================================================================================================================
RunSilentBAT(script_name)
{
	global
	
	script_path__silent_vbs := dir__ahk . "Run_BAT_Silently.vbs"
	script_path__bat        := dir__bat . script_name
	
	Run, C:/Windows/System32/wscript.exe "%script_path__silent_vbs%" "%script_path__bat%"
}



//======================================================================================================================
// This function hides the Tray Tip/toast notification rather quickly. Required since the default minimum is ~10s.
//======================================================================================================================
HideTrayTip()
{
	// Attempt to hide it the normal way
	TrayTip
	Sleep 1500
	
	// Windows 10 requires special handling - I don't really understand this
	if SubStr(A_OSVersion,1,3) = "10."
	{
		Menu Tray, NoIcon
			
		// It may be necessary to adjust this sleep.
		Sleep 500 
			
		Menu Tray, Icon
	}
}
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Notepad++ box-selection hotkey no longer works

25 Oct 2017, 11:21

Honestly I'm not sure what was causing the issue of unpredicatability. I quickly looked over your finalized code (Thanks for the immortalization :haha:) and don't see a particular reason the original remap would fail. You may also be interested in changing the {key Down} keys into {key DownTemp} keys which are truer to a remap and are explained in the remap documentation under Remarks.

One thing I am just realizing is that MButton::!LButton should have been enough to use the Shifted version, because remaps accept other modifiers. So pressing Shift+MButton with just that remap would've resulted in Shift+Alt+LButton. You could also do Ctrl+MButton to get Ctrl+Alt+LButton.

So I wonder if there may have been some kind of conflict between the two remaps, at least when doing the shifted verison? I don't think so, but, maybe it could have. Could be a weird quirk with remapping mouse buttons to mouse buttons.

Maybe experimenting with those changes can shed some light on the underlying issue. But otherwise, like you said, it's working with the code you've got now.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: ht55cd3 and 249 guests