jeeswg's Notepad tutorial

Helpful script writing tricks and HowTo's
User avatar
jeeswg
Posts: 5443
Joined: 19 Dec 2016, 01:58
Location: UK

jeeswg's Notepad tutorial

14 May 2017, 20:47

INTRODUCTION

This tutorial is intended to use Notepad to introduce some IT concepts and to explain some AutoHotkey techniques.

It is also meant as an addition to an AutoHotkey beginner's tutorial.

In theory, the focus of this tutorial is not Notepad itself, but using Notepad to explain more general ideas. So if you think that there is something missing from this tutorial, then please provide a solid or roundabout connection to Notepad as a justification for why it should be included in this tutorial.

==================================================

ABBREVIATIONS

AHK (AutoHotkey)
OS (operating system)
PC (personal computer)

TERMINOLOGY

32-bit/64-bit
class
ClassNN
hWnd
PID
window title
Wow64

==================================================

WINDOWS - CLASS

Notepad's main window has class 'Notepad'.

E.g. programs and their classes.

Code: Select all

;e.g. of Windows accessories and window classes:
Calculator: CalcFrame
Character Map: #32770 [note: a lot of windows have class '#32770']
Command Prompt: ConsoleWindowClass
HTML Help: HH Parent
Notepad: Notepad
Paint: MSPaintApp
WordPad: WordPadClass

;e.g. of programs and window classes:
Adobe Reader: AcrobatSDIWindow
AutoHotkey: AutoHotkey
Google Chrome: Chrome_WidgetWin_1
Internet Explorer: IEFrame
LibreOffice Calc: SALFRAME
LibreOffice Writer: SALFRAME
Media Player Classic: MediaPlayerClassicW
Microsoft Excel: XLMAIN
Microsoft Word: OpusApp
Mozilla Firefox: MozillaWindowClass
NirSoft SearchMyFiles: SearchMyFiles
Notepad2: Notepad2
TeXstudio: Qt5QWindowIcon
WinDjView: Afx:0000000140000000:b:0000000000010003:0000000000000006:???????????????? [note: the class varies, the question marks are characters 0-9 or A-F]
WinMerge: WinMergeWindowClassW
wxMaxima: wxWindowClassNR
E.g. get a window's class.

Code: Select all

q:: ;get the active window's class
WinGetClass, vWinClass, A
MsgBox, % vWinClass
return
==================================================

WINDOWS - PATH

On 32-bit PCs, Notepad has path:
C:\Windows\System32\notepad.exe

On 64-bit PCs, Notepad has path:
C:\Windows\System32\notepad.exe [64-bit version]
C:\Windows\SysWOW64\notepad.exe [32-bit version][WoW64 (Windows 32-bit on Windows 64-bit)]

E.g. get a window's process name/path.

Code: Select all

q:: ;get the active window's process name/path
WinGet, vPName, ProcessName, A
WinGet, vPPath, ProcessPath, A
MsgBox, % vPName "`r`n" vPPath
return
Regarding 64-bit PCs, it may look like that is the wrong way round, but it is correct.

If you are running a 32-bit version of AutoHotkey, on a 64-bit PC and try to run 'C:\Windows\System32\notepad.exe', it will instead open 'C:\Windows\SysWOW64\notepad.exe', unless you turn off Wow64 file system redirection.

E.g. get the 'bitness' of the OS and of AutoHotkey, and if applicable demonstrate the effects of Wow64 file system redirection.

Code: Select all

;note: this is intended to be run by 32-bit AutoHotkey on a 64-bit PC
q:: ;open Notepad 32-bit and 64-bit

;these 2 lines use the ternary operator:
;'condition ? result if true : result if false'
vBitnessOS := A_Is64bitOS ? 64 : 32
vBitnessAHK := (A_PtrSize = 8) ? 64 : 32

MsgBox, % "OS is x" vBitnessOS "`r`n" "AHK is x" vBitnessAHK

;if OS is not x64 OR AHK is not x32, then return
if !(vBitnessOS = 64) || !(vBitnessAHK = 32)
	return

Run, C:\Windows\System32\notepad.exe,,, vPID
WinWait, % "ahk_class Notepad ahk_pid " vPID
WinGet, vPPath1, ProcessPath, % "ahk_class Notepad ahk_pid " vPID
Sleep 1000
WinClose, % "ahk_class Notepad ahk_pid " vPID

if A_Is64bitOS
	DllCall("kernel32\Wow64DisableWow64FsRedirection", UIntP,0)
Sleep 1000

Run, C:\Windows\System32\notepad.exe,,, vPID
WinWait, % "ahk_class Notepad ahk_pid " vPID
WinGet, vPPath2, ProcessPath, % "ahk_class Notepad ahk_pid " vPID
Sleep 1000
WinClose, % "ahk_class Notepad ahk_pid " vPID

MsgBox, % vPPath1 "`r`n" vPPath2
return
==================================================

WINDOWS - PID AND HWND

When you open Notepad e.g. by clicking on its Start menu icon or double-clicking a txt file, a new instance of Notepad is opened.

Each new instance of Notepad (or any process) has a unique process ID (PID). A process ID is usually a 4-digit number that is divisible by 4.

Each new instance of Notepad has a main window, that window has a window handle (hWnd). All windows have a unique window handle. If a window no longer exists, its window handle can be reused.

If for example you open the Find dialog or the Replace dialog. Those are also windows with their own window handle (hWnd).

In any particular instance of Notepad, all the windows will have the same process ID (PID).

==================================================

CONTROLS

Notepad's window normally has the following GUI elements:
- A title bar (with icon, window title, and minimise/maximise/close buttons).
- A menu bar (e.g. text: 'File, Edit, Format, View, Help').
- An Edit control (with vertical and horizontal scrollbars).
- A status bar (e.g. text: 'Ln 1, Col 1').

The title bar and menu bar are not regarded as controls.

The Edit control and status bar are regarded as controls.

Controls are actually windows. Controls have window handles and classes just like Notepad's main window (which has class 'Notepad').

Notepad's main window normally has 2 controls:
- An Edit control, which has class 'Edit'.
- A status bar, which has class 'msctls_statusbar32'.

Notepad's Find dialog normally has 10 controls:
- A Static control, with text 'Find what'.
- An Edit control, which starts off blank.
- 7 visible Button controls, with text: 'Match case, Direction, Up, Down, Find Next, Cancel, Help'.
- 1 hidden Button control, with text 'Match whole word only'

Why would there be a hidden control?

This is because Notepad uses a template Find dialog, that many other programs also use.

Notepad does not offer 'whole word' searching, so therefore this control is unnecessary, and is thus hidden.

==================================================

WINDOWS - CLASSNN

If you use AutoHotkey's window spy on a Notepad's main window it will list the following controls:
- Edit1, msctls_statusbar321

If you use AutoHotkey's window spy on a Notepad Find dialog it will give the following controls:
- Static1, Edit1, Button1, Button2, Button3, Button4, Button5, Button6, Button7, Button8

AutoHotkey refers to controls by their 'ClassNN'. Each control is referred to by its class and a number.

E.g. list a window's controls and their text.

Code: Select all

q:: ;get control information for the active window (ClassNN and text)
WinGet, vCtlList, ControlList, A
vOutput := ""
Loop, Parse, vCtlList, `n
{
	vCtlClassNN := A_LoopField
	ControlGetText, vText, % vCtlClassNN, A
	vOutput .= vCtlClassNN "`t" vText "`r`n"
}

Clipboard := vOutput
MsgBox, % "done"
return
==================================================

REGISTRY

Notepad stores information regarding its settings in the registry in the following registry key:

HKEY_CURRENT_USER\Software\Microsoft\Notepad

You can open RegEdit (Registry Editor) and navigate to the key to view (and edit) the information.

The meaning of the registry entries is as follows:
- fWrap/StatusBar - word wrap/status bar, on/off.
- iMargin*/szHeader/szTrailer - Page Setup dialog settings.
- iPointSize - font size.
- iWindowPosDX/iWindowPosDY - main window width/height.
- iWindowPosX/iWindowPosY - main window top-left corner coordinates.
- lf* - font details (part of a LOGFONT structure).
- fMLE_is_broken - UNKNOWN.
- fSavePageSettings - UNKNOWN (may not appear in all versions of Notepad).
- fSaveWindowPositions - UNKNOWN.

E.g. get some of Notepad's font details.

Code: Select all

:: ;Notepad - get font information
RegRead, vFontPointSize, HKEY_CURRENT_USER, Software\Microsoft\Notepad, iPointSize
RegRead, vFontName, HKEY_CURRENT_USER, Software\Microsoft\Notepad, lfFaceName
RegRead, vFontIsItalic, HKEY_CURRENT_USER, Software\Microsoft\Notepad, lfItalic
RegRead, vFontWeight, HKEY_CURRENT_USER, Software\Microsoft\Notepad, lfWeight

vFontSize := Round(vFontPointSize/10)
vFontIsBold := (vFontWeight = 700)

vOutput := "name: " vFontName "`r`n"
vOutput .= "size: " vFontSize "`r`n"
vOutput .= "is bold: " vFontIsBold "`r`n"
vOutput .= "is italic: " vFontIsItalic "`r`n"

Clipboard := vOutput
MsgBox, % vOutput
return
E.g. set some of Notepad's font details.

Code: Select all

q:: ;Notepad - set font information
;warning: edit the registry at your own risk
vFontName := "Arial"
vFontSize := 72
vFontIsBold := 1
vFontIsItalic := 1

vFontPointSize := vFontSize*10
vFontWeight := vFontIsBold ? 700 : 400

RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Notepad, iPointSize, % vFontPointSize
RegWrite, REG_SZ, HKEY_CURRENT_USER, Software\Microsoft\Notepad, lfFaceName, % vFontName
RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Notepad, lfItalic, % vFontIsItalic
RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Notepad, lfWeight, % vFontWeight
return
==================================================

REGISTRY - TXT FILE OPEN / AHK FILE EDIT SCRIPT / AUTOHOTKEY TRAY MENU EDIT SCRIPT

Code: Select all

;note: Admin mode is needed to change certain registry settings
;although this is not necessary in older Windows OSes e.g. Windows XP
;[change 'open' for txt files]
;[change 'edit' for ahk files]
;affects tray menu and right-click ahk files
;HKEY_CLASSES_ROOT\txtfile\shell\open\command
;HKEY_CLASSES_ROOT\AutoHotkeyScript\Shell\Edit\Command
;from
;(Default)	REG_SZ	notepad.exe %1
;to
;(Default)	REG_SZ	"C:\Program Files\Windows NT\Accessories\wordpad.exe" "%1"

if !A_IsAdmin
	Run, % "*RunAs " (A_IsCompiled ? "" : A_AhkPath " ") Chr(34) A_ScriptFullPath Chr(34)

;vTarget = notepad.exe `%1
vTarget = "C:\Program Files\Windows NT\Accessories\wordpad.exe" "`%1"
;txt file open with:
;RegWrite, REG_SZ, HKEY_CLASSES_ROOT\txtfile\shell\open\command,, % vTarget
;AutoHotkey edit script:
RegWrite, REG_SZ, HKEY_CLASSES_ROOT\AutoHotkeyScript\Shell\Edit\Command,, % vTarget
return
==================================================

REGISTRY - ADD 'OPEN WITH NOTEPAD' TO ALL FILES

Code: Select all

;note: Admin mode is needed to change certain registry settings
;although this is not necessary in older Windows OSes e.g. Windows XP
;[add 'open with notepad' to all files][if a shortcut, the target is opened]
;HKEY_CLASSES_ROOT\*\Shell\Open with Notepad\command
;from
;(Default)	REG_SZ	notepad.exe %1
;to
;(Default)	REG_SZ	"C:\Program Files\Windows NT\Accessories\wordpad.exe" "%1"

if !A_IsAdmin
	Run, % "*RunAs " (A_IsCompiled ? "" : A_AhkPath " ") Chr(34) A_ScriptFullPath Chr(34)

;vTarget = notepad.exe `%1
vTarget = "C:\Program Files\Windows NT\Accessories\wordpad.exe" "`%1"
;open with Notepad for all files:
RegWrite, REG_SZ, HKEY_CLASSES_ROOT\*\Shell\Open with Notepad\command,, % vTarget
return
==================================================

WINDOWS - WINDOW STYLE

[style/extended style]

A window/control has styles which affect how they look/behave. Some can only be changed when the window is created, some can be changed at any time.

[word wrap][centre text]

Code: Select all

q:: ;get style/extended style for window/control
WinGet, vWinStyle, Style, A
WinGet, vWinExStyle, ExStyle, A
ControlGet, vCtlStyle, Style,, Edit1, A
ControlGet, vCtlExStyle, ExStyle,, Edit1, A
MsgBox, % Format("0x{:08X}", vWinStyle) " " Format("0x{:08X}", vWinExStyle)
MsgBox, % Format("0x{:08X}", vCtlStyle) " " Format("0x{:08X}", vCtlExStyle)
return

;==================================================

w:: ;check if word wrap on, by checking if WS_HSCROLL style is on/off
ControlGet, vCtlStyle, Style,, Edit1, A
;WS_HSCROLL := 0x100000
vState := (vCtlStyle & 0x100000) ? "off" : "on"
MsgBox, % "word wrap is " vState
return

;==================================================

e:: ;toggle centre text on/off
;ES_CENTER := 0x1
Control, Style, ^0x1, Edit1, A
return
See lower down for hide/show title bar.

==================================================

WINDOWS - COORDINATES

[window coordinates, absolute]
[control coordinates, absolute/relative to window/relative to window's client area]

Code: Select all

q:: ;window - get coordinates
WinGetPos, vWinX, vWinY, vWinW, vWinH, A
MsgBox, % Format("x{} y{} w{} h{}", vWinX, vWinY, vWinW, vWinH)
return

w:: ;window - set coordinates
WinGetPos, vWinX, vWinY, vWinW, vWinH, A
WinMove, A,, % vWinX + 10, % vWinY, % vWinW, % vWinH
return

Code: Select all

w:: ;control - set coordinates
;in AHK v1: ControlMove is relative to the window's top-left corner
ControlGetPos, vCtlX, vCtlY, vCtlW, vCtlH, Edit1, A
ControlMove, Edit1, % vCtlX, % vCtlY, % vCtlW - 5, % vCtlH, A
return
==================================================

TITLE BAR / TITLE BAR BUTTONS / ALT-SPACE MENU

[hide/show title bar]

Code: Select all

q:: ;toggle hide/show title bar
;WS_CAPTION := 0xC00000
;which is a combination of:
;WS_BORDER := 0x800000
;WS_DLGFRAME := 0x400000
WinSet, Style, ^0xC00000, A
return
[minimise, maximise/restore, close]

Code: Select all

q:: ;window - get minimised/maximised state
WinGet, vWinMinMax, MinMax, ahk_class Notepad
MsgBox, % vWinMinMax ;0=normal, 1=max, -1=min
return

w:: ;window - set minimised/maximised state
WinGet, hWnd, ID, A
WinMaximize, % "ahk_id " hWnd
Sleep 1000
WinMinimize, % "ahk_id " hWnd
Sleep 1000
WinRestore, % "ahk_id " hWnd
Sleep 1000
return

e:: window - close
WinClose, A
return
Odd behavior for WinRestore and WinMaximize - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=34205

[enable/disable title bar buttons][hide show min/max buttons]

Note: if you disable both the min and max buttons, they disappear.

Code: Select all

q:: ;toggle enable/disable min button
;WS_MAXIMIZEBOX := 0x10000
WinSet, Style, ^0x10000, A
return

w:: ;toggle enable/disable max button
;WS_MINIMIZEBOX := 0x20000
WinSet, Style, ^0x20000, A
return

e:: ;toggle enable/disable close button
;SC_CLOSE := 0xF060, MF_BYCOMMAND := 0x0
;MF_ENABLED := 0x0, MF_GRAYED := 0x1, MF_DISABLED := 0x2
WinGet, hWnd, ID, A
hMenu := DllCall("GetSystemMenu", Ptr,hWnd, Int,0, Ptr)
vState := DllCall("GetMenuState", Ptr,hMenu, UInt,0xF060, UInt,0, UInt)
if (vState = 4294967295) ;0xFFFFFFFF
	DllCall("GetSystemMenu", Ptr,hWnd, Int,1, Ptr), vState := 0x0
vIsEnabled := !(vState & 0x2)
DllCall("EnableMenuItem", Ptr,hMenu, UInt,0xF060, UInt,vIsEnabled?0x3:0x0)
DllCall("DrawMenuBar", Ptr,hWnd)
if !vIsEnabled
	DllCall("GetSystemMenu", Ptr,hWnd, Int,1, Ptr)
return

r:: ;set the max button to maximise/restore
WinSet, Style, ^0x1000000, A ;WS_MAXIMIZE := 0x1000000
return
event hooks and blocking min/max/restore/close - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 24#p160424
Enable/disable external menuitem - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 61#p161161

[show alt-space menu/show context menus]

Code: Select all

q:: ;show alt-space menu
;note: space is Chr(0x20) (hex) aka Chr(32) (dec)
PostMessage, 0x112, 0xF100, 0x20,, A ;WM_SYSCOMMAND := 0x112 ;SC_KEYMENU := 0xF100
return

w:: ;show File menu
;note: F is Chr(0x46) (hex) aka Chr(70) (dec)
PostMessage, 0x112, 0xF100, 0x46,, A ;WM_SYSCOMMAND := 0x112 ;SC_KEYMENU := 0xF100
return

e:: ;show Edit menu
;note: E is Chr(0x45) (hex) aka Chr(69) (dec)
PostMessage, 0x112, 0xF100, 0x45,, A ;WM_SYSCOMMAND := 0x112 ;SC_KEYMENU := 0xF100
return
[title bar: system properties, font]

How to open the context menu of the window's title bar - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 70#p165570
Odd behavior for WinRestore and WinMaximize - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 72#p158372

[title bar - system properties, font]

to set the title bar appearance manually in Windows 7: Control Panel, Appearance and Personalization, Change the theme, Window Color

;function to set system fonts:
GUI COMMANDS: COMPLETE RETHINK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 78#p131078
get a process's GDI handles (e.g. get/set title bar font and apply WM_SETFONT to a control) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 85#p145585

==================================================

MENU BAR

[get menu item text/check state/enabled state/command ID]

To invoke menu items use WM_COMMAND.
To invoke sysmenu (system menu) (alt-space menu) items use WM_SYSCOMMAND.

Code: Select all

q:: ;invoke menu items - save as
WinGet, hWnd, ID, ahk_class Notepad
PostMessage, 0x111, 4,,, % "ahk_id " hWnd ;WM_COMMAND := 0x111
return

w:: ;invoke sysmenu items - maximise
WinGet, hWnd, ID, ahk_class Notepad
PostMessage, 0x112, 61488,,, % "ahk_id " hWnd ;WM_SYSCOMMAND := 0x112
return
Enable/disable external menuitem - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 85#p161185

[menu command IDs][for PostMessage/SendMessage]

Get Info from Context Menu (x64/x32 compatible) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=31971

[show/hide menu bar]

Code: Select all

;you must keep a record of the menu handle
;in order to restore it later
q:: ;hide/show menu bar
WinGet, hWnd, ID, A
if hMenu := DllCall("user32\GetMenu", Ptr,hWnd, Ptr)
{
	hMenu%A_Index% := hMenu
	DllCall("user32\SetMenu", Ptr,hWnd, Ptr,0)
}
else
	DllCall("user32\SetMenu", Ptr,hWnd, Ptr,hMenu%A_Index%)
return
[resources in Notepad.exe]

Use Resource Hacker and check for a Menu resource:
On older OSes: C:\Windows\System32\notepad.exe
On newer OSes: C:\Windows\System32\en-US\notepad.exe.mui

[get/set a menu item's checked/unchecked state (ticked/unticked)]

list of AutoHotkey WM_COMMAND IDs (e.g. Reload/Edit/Suspend/ListVars on another script) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?t=27824

Code: Select all

q:: ;Notepad - toggle word wrap on/off
WinGet, hWnd, ID, A
PostMessage, 0x111, 32,,, % "ahk_id " hWnd ;WM_COMMAND := 0x111
return

w:: ;Notepad - get word wrap on/off state
WinGet, hWnd, ID, A
hMenuBar := DllCall("user32\GetMenu", Ptr,hWnd, Ptr)
hMenuFormat := DllCall("user32\GetSubMenu", Ptr,hMenuBar, Int,2, Ptr)
SendMessage, 0x116, % hMenuFormat,,, % "ahk_id " hWnd ;WM_INITMENU := 0x116
vState := DllCall("user32\GetMenuState", Ptr,hMenuFormat, UInt,32, UInt,0, UInt)
vIsTicked := (vState >> 3) & 1
MsgBox, % vState " " vIsTicked
return
==================================================

CONTROLS - STATUS BAR

[get status bar text (multiple parts)]

Code: Select all

;note: StatusBarGetText can only be used on a control with ClassNN 'msctls_statusbar321'.
q:: ;status bar get text
StatusBarGetText, vText1, 1, A ;usually (always?) blank
StatusBarGetText, vText2, 2, A ;e.g. 'Ln 1, Col 1' (plus leading/trailing spaces)
MsgBox, % "[" vText1 "]"
MsgBox, % "[" vText2 "]"
return

;requires Acc library
;Acc library (MSAA) and AccViewer download links - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=26201

w:: ;status bar get text via Acc
ControlGet, hCtl, Hwnd,, msctls_statusbar321, A
oAcc := Acc_Get("Object", "4", 0, "ahk_id " hCtl)
MsgBox, % oAcc.accName(1)
MsgBox, % oAcc.accName(2)
oAcc := ""
return
==================================================

CONTROLS - EDIT CONTROL

see above: [word wrap - menu item check state, control style]
see below: [ctrl+left/ctrl+right]

==================================================

CONTROLS - EDIT CONTROL'S SCROLLBARS

E.g. get information regarding the scrollbars within Notepad's Edit control.

Code: Select all

;requires Acc library
;Acc library (MSAA) and AccViewer download links - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=26201

;q:: ;Notepad - get scrollbar percentage and coordinates
ControlGet, hCtl, Hwnd,, Edit1, ahk_class Notepad
oAcc1 := Acc_Get("Object", "5", 0, "ahk_id " hCtl)
oAcc2 := Acc_Get("Object", "6", 0, "ahk_id " hCtl)
vPercent1 := oAcc1.accValue
vPercent2 := oAcc2.accValue
oRect1 := Acc_Location(oAcc1)
oRect2 := Acc_Location(oAcc2)
vCoord1 := oRect1.x " " oRect1.y " " oRect1.w " " oRect1.h
vCoord2 := oRect2.x " " oRect2.y " " oRect2.w " " oRect2.h
oAcc := ""

vOutput := "vertical scrollbar:`r`n"
vOutput .= "scroll percentage: " vPercent1 "`%`r`n"
vOutput .= "XYWH coordinates: " vCoord1 "`r`n"
vOutput .= "`r`n"
vOutput .= "horizontal scrollbar:`r`n"
vOutput .= "scroll percentage: " vPercent2 "`%`r`n"
vOutput .= "XYWH coordinates: " vCoord2 "`r`n"
Clipboard := vOutput
MsgBox, % vOutput
return
==================================================

PROCESS - COMMAND LINE

[get path]

Code: Select all

;note: this would give the file first opened in that instance of Notepad,
;which is not necessarily the file that is currently open
q:: ;get command line path
WinGet, vPID, PID, A
oWMI := ComObjGet("winmgmts:")
oQueryEnum := oWMI.ExecQuery("Select * from Win32_Process where ProcessId=" vPID)._NewEnum()
if oQueryEnum[oProcess]
	vCmdLn := oProcess.CommandLine
oWMI := oQueryEnum := oProcess := ""
MsgBox, % vCmdLn
return
==================================================

WINDOW - OPEN/SAVE AS DIALOG

[Common File Dialog/Common Item Dialog]

Code: Select all

;invoke the 'Desktop' button
;on old-style Common File Dialog
;and new-style Common Item Dialog
#IfWinActive Open ahk_class #32770 ahk_exe notepad.exe
q::
#IfWinActive Save As ahk_class #32770 ahk_exe notepad.exe
q::
WinGet, hWnd, ID, A
JEE_DlgInvokeBtn(hWnd, "Desktop")
return
#IfWinActive

;==================================================

JEE_DlgInvokeBtn(hWnd, vName)
{
	hCtl := ""
	if !hCtl ;check for treeview e.g. Notepad (Windows 7 version)
	{
		if hCtl := ControlGetHwnd("SysTreeView321", "ahk_id " hWnd)
			oAcc := Acc_Get("Object", "outline", 0, "ahk_id " hCtl)
	}
	if !hCtl ;check for toolbar e.g. Notepad (Windows XP version)
	{
		if hCtl := ControlGetHwnd("ToolbarWindow322", "ahk_id " hWnd)
			oAcc := Acc_Get("Object", "tool_bar", 0, "ahk_id " hCtl)
	}
	Loop, % oAcc.accChildCount
		if (oAcc.accName(A_Index) = vName)
		{
			oAcc.accDoDefaultAction(A_Index)
			break
		}
	oAcc := ""
}
==================================================

SHELL - RECENT FILES

;[JEE_SysGetRecentItems function]
;list Recent Items (My Recent Documents) (Start Menu) - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=31386

Code: Select all

q:: ;list recent files
vOutput := JEE_SysGetRecentItems("`r`n", 30, "F", vCount)
;vOutput := JEE_SysGetRecentItems("`r`n", 30, "FD", vCount)
;vOutput := JEE_SysGetRecentItems("`r`n", 30, "D", vCount)
;Clipboard := vCount "`r`n" vOutput "`r`n"
MsgBox, % vOutput

;keep only txt files
vOutput := RegExReplace(vOutput, "m)^.*(?<!\.txt)$(`r`n)?")
Clipboard := vCount "`r`n" vOutput "`r`n"
MsgBox, % vOutput
return
==================================================

NOTEPAD - CLIPBOARD

[clipboard + menu items]

In Notepad's Edit menu, Cut and Copy are enabled/disabled based on whether any text is selected.

Code: Select all

q:: ;check whether text is selected
ControlGet, hCtl, Hwnd,, Edit1, A
VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0 ;(left, right)
vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
MsgBox, % vPos1 " " vPos2
MsgBox, % !(vPos1 = vPos2)
return

w:: ;check whether text is selected
;this method is probably more costly, it doesn't just get positions, but text
ControlGet, vText, Selected,, Edit1, A
MsgBox, % (vText = "")
return

e:: ;check whether text is on the clipboard
;note: it is unconfirmed whether this matches Notepad's behaviour exactly
;CF_UNICODETEXT := 0xD ;CF_OEMTEXT := 0x7 ;CF_TEXT := 0x1
if DllCall("user32\IsClipboardFormatAvailable", UInt,0x1)
|| DllCall("user32\IsClipboardFormatAvailable", UInt,0xD)
|| DllCall("user32\IsClipboardFormatAvailable", UInt,0x7)
	MsgBox, % "y"
else
	MsgBox, % "n"
return

;Standard Clipboard Formats (Windows)
;https://msdn.microsoft.com/en-us/library/windows/desktop/ff729168(v=vs.85).aspx

r:: ;check whether text is on the clipboard
;note: AutoHotkey differs from Notepad
;the variable Clipboard will contain text if files were copied to the clipboard
;but in such cases, Notepad perceives the Clipboard as having no text
MsgBox, % (Clipboard = "")
return
==================================================

NOTEPAD - UNDO STATE, UNSAVED STATE, READ-ONLY STATE

Code: Select all

q:: ;get undo/modified states
;get undo state
WinGet, hWnd, ID, A
SendMessage, 0xC6, 0, 0, Edit1, % "ahk_id " hWnd ;EM_CANUNDO := 0xC6 ;(get undo state)
vUndoState := ErrorLevel
MsgBox, % "undo available: " (vUndoState ? "y" : "n")

;get modified state
SendMessage, 0xB8, 0, 0, Edit1, % "ahk_id " hWnd ;EM_GETMODIFY := 0xB8 ;(get modified state)
vModState := ErrorLevel
MsgBox, % "unsaved changes: " (vModState ? "y" : "n")
return

Code: Select all

q:: ;Notepad - thinks the window has unsaved changes
WinGet, hWnd, ID, A
SendMessage, 0xB9, 1,, Edit1, % "ahk_id " hWnd ;EM_SETMODIFY := 0xB9
return

w:: ;Notepad - thinks the window has no unsaved changes
WinGet, hWnd, ID, A
SendMessage, 0xB9, 0,, Edit1, % "ahk_id " hWnd ;EM_SETMODIFY := 0xB9
return

e:: ;turn read-only mode on/off
WinGet, hWnd, ID, A
SendMessage, 0xCF, 1,, Edit1, % "ahk_id " hWnd ;EM_SETREADONLY := 0xCF
Sleep 2000
SendMessage, 0xCF, 0,, Edit1, % "ahk_id " hWnd ;EM_SETREADONLY := 0xCF
return
==================================================

INSERT DATE/TIME

Customise the F5 (Edit, Time/Date) functionality.

Code: Select all

F5::
q::
FormatTime, vDate,, HH:mm dd/MM/yyyy
SendInput, % vDate "`n"
return
==================================================

EDIT CONTROL - GET/SET ALL/SELECTED TEXT

Code: Select all

q:: ;get length/content of all/selected text
WinGet, hWnd, ID, A

;get all text
ControlGetText, vText, Edit1, % "ahk_id " hWnd
MsgBox, % vText

;get length of all text
SendMessage, 0xE, 0, 0, Edit1, % "ahk_id " hWnd ;WM_GETTEXTLENGTH := 0xE
vLen := ErrorLevel
MsgBox, % vLen

;get selected text
ControlGet, vText, Selected,, Edit1, % "ahk_id " hWnd
MsgBox, % vText

;get length of selected text
ControlGet, hCtl, Hwnd,, Edit1, % "ahk_id " hWnd
VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0 ;(left, right)
vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
MsgBox, % Abs(vPos2 - vPos1)
return

Code: Select all

q:: ;set all text
vText := "abcdefghijklmnopqrstuvwxyz"
ControlSetText, Edit1, % vText, ahk_class Notepad
return

w:: ;insert text (replace current selection)
vText := "abc"
Control, EditPaste, % vText, Edit1, A
return

e:: ;get selection (left/right)
ControlGet, hCtl, Hwnd,, Edit1, A
VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
SendMessage, 0xB0, % &vPos1, % &vPos2,, % "ahk_id " hCtl ;EM_GETSEL := 0xB0 ;(left, right)
vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
MsgBox, % vPos1 " " vPos2
return

r:: ;set selection (anchor/active)
;after 5th character to after 10th character
vPos1 := 5
vPos2 := 10
SendMessage, 0xB1, % vPos1, % vPos2,, % "ahk_id " hCtl ;EM_SETSEL := 0xB1 ;(anchor, active)
return

t:: ;select all text
PostMessage, 0xB1, 0, -1, Edit1, A ;EM_SETSEL := 0xB1 ;(anchor, active)
return

Code: Select all

;get position: current line/column/character
;get general Edit control/Notepad details

q::
WinGet, hWnd, ID, A

;get undo state (is undo available: yes/no)
SendMessage, 0xC6, 0, 0, Edit1, % "ahk_id " hWnd ;EM_CANUNDO := 0xC6 ;(get undo state)
vUndoState := ErrorLevel ? "yes" : "no"

;get modified state (are there unsaved changes: yes/no)
SendMessage, 0xB8, 0, 0, Edit1, % "ahk_id " hWnd ;EM_GETMODIFY := 0xB8 ;(get modified state)
vModState := ErrorLevel ? "YES" : "no"

;get word wrap state (word wrap on: yes/no)
ControlGet, vCtlStyle, Style,, Edit1, % "ahk_id " hWnd
;WS_HSCROLL := 0x100000
vWordWrapState := (vCtlStyle & 0x100000) ? "no" : "yes"

;get always on top state (is on top: yes/no)
WinGet, vWinExStyle, ExStyle, % "ahk_id " hWnd
;WS_EX_TOPMOST := 0x8
vOnTopState := (vWinExStyle & 0x8) ? "yes" : "no"

;get line count/current line number/current column
ControlGet, vCurrentLine, CurrentLine,, Edit1, % "ahk_id " hWnd
ControlGet, vLineCount, LineCount,, Edit1, % "ahk_id " hWnd
ControlGet, vCurrentCol, CurrentCol,, Edit1, % "ahk_id " hWnd

;get start/end (character positions) of text selection
;count selected characters
VarSetCapacity(vPos1, 4), VarSetCapacity(vPos2, 4)
SendMessage, 0xB0, % &vPos1, % &vPos2, Edit1, % "ahk_id " hWnd ;EM_GETSEL := 0xB0
vPos1 := NumGet(&vPos1, 0, "UInt"), vPos2 := NumGet(&vPos2, 0, "UInt")
vCharSelCount := vPos2 - vPos1

;count all characters
SendMessage, 0xE, 0, 0, Edit1, % "ahk_id " hWnd ;WM_GETTEXTLENGTH := 0xE
vCharCount := ErrorLevel

;count selected lines method 1 (including blank lines)
;ControlGet, vText, Selected,, Edit1, % "ahk_id " hWnd
;StrReplace(vText, "`n", "", vLineSelCount), vLineSelCount += 1

;re. method 1:
;this version is a sense more accurate,
;because the method below, includes lines that wrap
;(even when word wrap is off)
;because they are too long to display on one line,
;rather than the number of linefeed characters

;count selected lines method 2 (including blank lines)
SendMessage, 0xC9, % vPos1, 0, Edit1, % "ahk_id " hWnd ;EM_LINEFROMCHAR := 0xC9
vLine1 := ErrorLevel
SendMessage, 0xC9, % vPos2, 0, Edit1, % "ahk_id " hWnd ;EM_LINEFROMCHAR := 0xC9
vLine2 := ErrorLevel
vLineSelCount := vLine2 - vLine1 + 1

vOutput := "undo: " vUndoState ", changes: " vModState
. "`r`n" "wrap: " vWordWrapState ", on top: " vOnTopState
. "`r`n" "[P Ln] " vCurrentLine " / " vLineCount " col " vCurrentCol
. "`r`n" "[P Ch] " vPos1 " / " vCharCount
. "`r`n" "[S Lns] " vLineSelCount " / " vLineCount
. "`r`n" "[S Chs] " vCharSelCount " / " vCharCount
. "`r`n`r`n"

vFormat := "zh0 b1 c0 fs18" ;border + left
Progress, % vFormat, % vOutput
Sleep, 1000
Progress, Off
return
[See here for get selection (anchor/active) script:]
GUI COMMANDS: COMPLETE RETHINK - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 92#p138292

==================================================

CARET, CARET BLINK RATE

Code: Select all

q:: ;get caret blink rate
MsgBox, % DllCall("GetCaretBlinkTime")
return

w:: ;stop caret blinking
DllCall("SetCaretBlinkTime", UInt, -1)
return

e:: ;get physical position of caret
MsgBox, % A_CaretX " " A_CaretY
return
See also on this page: EM_SCROLLCARET, EM_GETSEL, EM_SETSEL.

==================================================

EDIT CONTROL - SCROLL

Code: Select all

;WM_HSCROLL := 0x114
;WM_VSCROLL := 0x115
;EM_SCROLL := 0xB5
;EM_LINESCROLL := 0xB6
;EM_SCROLLCARET := 0xB7

;==================================================

;scroll via WM messages

;scroll right
;SB_LINELEFT := 0 ;SB_LINERIGHT := 1
PostMessage, 0x114, 1,, Edit1, A ;WM_HSCROLL := 0x114

;scroll down one line
;SB_LINEUP := 0 ;SB_LINEDOWN := 1
PostMessage, 0x115, 1,, Edit1, A ;WM_VSCROLL := 0x115

;scroll down one page
;SB_PAGEUP := 2 ;SB_PAGEDOWN := 3
PostMessage, 0x115, 3,, Edit1, A ;WM_VSCROLL := 0x115

;==================================================

;scroll up/down via EM messages

;scroll down one line
;SB_LINEUP := 0 ;SB_LINEDOWN := 1
PostMessage, 0xB5, 1,, Edit1, A ;EM_SCROLL := 0xB5

;scroll down one page
;SB_PAGEUP := 2 ;SB_PAGEDOWN := 3
PostMessage, 0xB5, 3,, Edit1, A ;EM_SCROLL := 0xB5

;==================================================

;scroll down by 3 lines
PostMessage, 0xB6, 0, 3, Edit1, A ;EM_LINESCROLL := 0xB6

;scroll up by 3 lines
PostMessage, 0xB6, 0, -3, Edit1, A ;EM_LINESCROLL := 0xB6

;==================================================

;scroll the caret into view
PostMessage, 0xB7,,, Edit1, A ;EM_SCROLLCARET := 0xB7
==================================================

EDIT CONTROL - LEFT/RIGHT MARGINS

Code: Select all

q:: ;get/set left margin
WinGet, hWnd, ID, A

;EC_LEFTMARGIN  := 0x1 ;EC_RIGHTMARGIN := 0x2
SendMessage, 0xD4, 0x1,, Edit1, % "ahk_id " hWnd ;EM_GETMARGINS := 0xD4
vLeft := ErrorLevel & 0xFFFF

SendMessage, 0xD3, 0x1, 30, Edit1, % "ahk_id " hWnd ;EM_SETMARGINS := 0xD3
Sleep, 1000
SendMessage, 0xD3, 0x1, 0, Edit1, % "ahk_id " hWnd ;EM_SETMARGINS := 0xD3
Sleep, 1000
SendMessage, 0xD3, 0x1, % vLeft, Edit1, % "ahk_id " hWnd ;EM_SETMARGINS := 0xD3
return
==================================================

TEXT - UNICODE: UTF-8 / UTF-16

Code: Select all

q:: ;calculate which encoding will give the smallest file size
;note: depending on which characters are in the string, ANSI is lossy
ControlGetText, vText, Edit1, A
vSize16 := StrLen(vText)*2+2 ;UTF-16
vSize8 := StrPut(vText, "UTF-8")+3-1 ;UTF-8
vSizeA := StrPut(vText, "CP0")-1 ;ANSI
MsgBox, % Format("{} {} {}", vSize16, vSize8, vSizeA)
return
==================================================

NOTEPAD - DLL INJECTION

[set Edit control font]
[set Edit control background colour]

how to dll Inject - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 97#p166697

==================================================

NOTEPAD - IMPROVEMENTS - ENHANCING AN EDIT CONTROL

[ctrl+left/ctrl+right]

Code: Select all

;note in some versions of Windows (e.g. XP)
;it treats CR LF as separate blocks
;you end up deleting halves of enters

^Backspace:: ;delete previous word (ordinary inserts Chr(127))
q::
SendInput, ^+{Left}{Del}
return

^Del:: ;delete next word (ordinarily deletes all characters on line after caret, or deletes selection)
w::
SendInput, ^+{Right}{Del}
return
==================================================

NOTEPAD - IMPROVEMENTS - GET/SET/USE PATH

notepad get/set path (get/set text file path) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=30050

Some uses:
- rename file prompt (together with JEE_NotepadSetPath to reopen the file once it has a new name)
- jump to previous/next file (together with JEE_NotepadSetPath)
- check if file is already open in Notepad
- run current file in AutoHotkey (v1.0/v.1.1/v2.0 A32/U32/U64)
- compare Edit control text with saved text/backup file (e.g. via WinMerge) (put old contents onto the clipboard)
- open containing folder
- get file details e.g. encoding/size/date
- open with another program
- add to Recent folder
- save but maintain date
- reopen file, 'refresh' (together with JEE_NotepadSetPath)
- do something with current file (e.g.: move file, send to recycle bin, cut/copy to clipboard for Explorer file paste)

==================================================

NOTEPAD - IMPROVEMENTS - WARN DOUBLE OPEN

Code: Select all

q:: ;check if multiple Notepad windows with the same window title exist
DetectHiddenWindows, On
WinGet, vWinList, List, ahk_class Notepad
oArray := {}
Loop, % vWinList
{
	hWnd := vWinList%A_Index%
	WinGetTitle, vWinTitle, % "ahk_id " hWnd
	if oArray.HasKey("" vWinTitle)
		oArray["" vWinTitle]++
	else
		oArray["" vWinTitle] := 1
}
vOutput := ""
for vKey, vValue in oArray
	if (vValue > 1)
		vOutput .= vValue "`t" vKey "`r`n"
oArray := ""
MsgBox, % SubStr(vOutput, 1, -2)
return
==================================================

NOTEPAD - IMPROVEMENTS - GO-BETWEEN

[prevent double open]
[force open as ANSI]
[open with a different program if the file is too big]

Code: Select all

q:: ;check if a file is open with the same name as a certain file
vPath := A_ScriptFullPath
VarSetCapacity(vDName, 260*2, 0)
DllCall("comdlg32\GetFileTitle", Str,vPath, Str,vDName, UShort,260, Short)
WinGet, vWinList, List, % vDName " - Notepad ahk_class Notepad"
MsgBox, % "count: " vWinList
return

w:: ;force open a file as ANSI regardless of encoding
vPath := A_ScriptFullPath
Run, "notepad.exe" /a "%vPath%"
return

e:: ;open a file with Notepad if below 6MB, otherwise with WordPad
vPath := A_ScriptFullPath
vPath = %A_ScriptDir%\Exe\magnifier.exe
FileGetSize, vSize, % vPath
if (vSize > 6*1048576)
	Run, wordpad.exe "%vPath%"
else
	Run, notepad.exe "%vPath%"
return
==================================================

NOTEPAD - IMPROVEMENTS - AUTOSAVE

Code: Select all

q:: ;a basic Notepad autosave script
vNow := A_Now
DetectHiddenWindows, On
WinGet, vWinList, List, ahk_class Notepad
Loop, % vWinList
{
	hWnd := vWinList%A_Index%
	WinGetTitle, vWinTitle, % "ahk_id " hWnd

	vWinTitle := RegExReplace(vWinTitle, " - Notepad$")
	Loop, 31
		vWinTitle := StrReplace(vWinTitle, Chr(A_Index))
	Loop, Parse, % "\/:*?" Chr(34) "<>|"
		vWinTitle := StrReplace(vWinTitle, A_LoopField)
	ControlGetText, vText, Edit1, % "ahk_id " hWnd
	vPath = %A_Desktop%\z NP BU %vWinTitle% %hWnd% %vNow%.txt
	MsgBox, % vPath
	FileAppend, % vText, % "*" vPath, UTF-8
}
MsgBox, % "done"
return
==================================================

LINKS

notepad get/set path (get/set text file path) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=30050

windows - How to get Notepad to enter fullscreen? - Super User
https://superuser.com/questions/1114935 ... fullscreen

Edit Control Messages (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx

Return to “Tutorials”

Who is online

Users browsing this forum: No registered users and 6 guests