Because times to times, I need to translate text into different languages using special characters not present on the keyboard, like ı, ş, ñ, ğ.
I created a script with AutoHotKey, transforming the combination of ^ + ^ + s -> into ş, in the same way for the others characters.
The script is working fine, but only working if the character preceding the first ^ is a space or the first letter. For example, when typing ma^^n <- this will not transform my character, whereas ^^n <- will transform it.
Here is the script, I specify that I only learned this language when creating the script:
:*c:^^S::
SendUnicodeChar(0x015E)
Return
:*c:^^s::
SendUnicodeChar(0x015F)
Return
:*c:^^i::
SendUnicodeChar(0x131)
Return
:*c:^^I::
SendUnicodeChar(0x130)
Return
:*c:^^g::
SendUnicodeChar(0x011F)
Return
:*c:^^G::
SendUnicodeChar(0x011E)
Return
:*c:^^n::
SendUnicodeChar(0x00F1)
Return
:*c:^^N::
SendUnicodeChar(0x00D1)
Return
:*c:^^c::
SendUnicodeChar(0x00E7)
Return
:*c:^^C::
SendUnicodeChar(0x00C7)
Return
; Find the corresponding letter from the unicode
; and send the input back
SendUnicodeChar(charCode)
{
VarSetCapacity(ki, 28 * 2, 0)
EncodeInteger(&ki + 0, 1)
EncodeInteger(&ki + 6, charCode)
EncodeInteger(&ki + 8, 4)
EncodeInteger(&ki +28, 1)
EncodeInteger(&ki +34, charCode)
EncodeInteger(&ki +36, 4|2)
DllCall("SendInput", "UInt", 2, "UInt", &ki, "Int", 28)
}
EncodeInteger(ref, val)
{
DllCall("ntdll\RtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}
As per the AHK docs on hotstring options:
? (question mark): The hotstring will be triggered even when it is
inside another word; that is, when the character typed immediately
before it is alphanumeric. For example, if :?:al::airline is a
hotstring, typing "practical " would produce "practicairline ". Use ?0
to turn this option back off.
Consequentially, your hotstrings should look like this:
:?*c:^^S::
SendUnicodeChar(0x015E)
Return
You may also want to globally set the options, so that you won't have to apply them to every hotstring individually:
#Hotstring ?*c
::^^S::
SendUnicodeChar(0x015E)
Return
::^^s::
SendUnicodeChar(0x015F)
Return
Related
I use this script to track the keyboard layout on Win 7, it works ok:
getactiveKL() {
active_hwnd := WinExist("A")
threadID := dllCall("GetWindowThreadProcessId", "uint", active_hwnd)
code := dllCall("GetKeyboardLayout", "uint", threadID, "uint") & 0xFFFF
return code
}
; 1049 - RU (hex: 419)
; 1033 - EN (hex: 409)
loop {
sleep, 600
KL := getactiveKL()
tooltip, %KL%
}
But it dooes not work on win 10. Namely it works only once - if I set the layout to RU, and then run this script, it detects correctly, but when I switch the layout - nothing changes.
Do you know how to make it work on windows 10?
The problem was in this line:
threadID := dllCall("GetWindowThreadProcessId", "uint", active_hwnd)
It should be:
threadID := dllCall("GetWindowThreadProcessId", "uint", active_hwnd, "uint", 0)
There are many examples in the web with different spelling of this dll call, so the latter works on windows 10 correctly.
I'd like to remap the numeric keypad with Numlock On to behave like the numeric keypad with Numlock Off, including being able to extend the selection with Shift/Ctrl held down.
The problem I have is the following
Numpad8::Up
Doesn't have correct behaviour when shift+numpad8 is pressed, the cursor moves up, but no text is selected. The following also don't work as I'd like (same behaviour as Numpad::8).
+Numpad8::Up
+Numpad8::+Up
If I remap a normal key, the selection behaviour is correct when shift is pressed:
w::Up
Any hints?
The reason I'm doing this is to make a CoolerMaster QuickFire TK's numeric keypad behave like it has a standard numeric keypad layout (I've some registry keyboard remapping happening as well, which is why I want the navigation behaviour with Numlock On).
It's possible, but it's a pain in the ass... compared to normal remapping.
Here is the normal behaviour of the Numpad8-key:
With numpad on:
num8: up
shift+num8: mark up
With numpad off:
num8: 8
shift+num8:up
So if you want to reverse that, what we want is this:
With numpad on:
num8: 8
shift+num8:up
With numpad off:
num8: up
shift+num8: mark up
This is how it could be achived:
*NumpadUp::
If GetKeyState("NumLock", "T")
SendInput, {Shift Down}{Up}
Else If GetKeyState("Shift")
SendInput, {Shift Up}{NumpadUp}
Else
SendInput, {Shift Up}{Numpad8}
Return
*Numpad8::
If GetKeyState("Shift")
SendInput, {Shift Down}{NumpadUp}
Else
SendInput, {NumpadUp}
Return
Now you just need to do the same thing for the other numpad keys that you want to reverse.
Here is a different approach that uses a little hack to make it look like the Numpad toggles when pressing the numlock key. But it ensures that the numlock actually is always off and only the numlock light is changed.
SetNumLockState, Off
fakeNumlockOn := False
Return
NumLock::
SetNumLockState, Off
fakeNumlockOn := !fakeNumlockOn
SetNumLockLEDs(fakeNumlockOn ? "on" : "off")
Sleep, 100
SetNumLockLEDs(fakeNumlockOn ? "on" : "off")
Return
SetNumLockLEDs(state) {
Loop, 11
KeyboardLED(2,state,A_Index-1)
}
/*
Keyboard LED control for AutoHotkey_L
http://www.autohotkey.com/forum/viewtopic.php?p=468000#468000
KeyboardLED(LEDvalue, "Cmd", Kbd)
LEDvalue - ScrollLock=1, NumLock=2, CapsLock=4
Cmd - on/off/switch
Kbd - index of keyboard (probably 0 or 2)
*/
KeyboardLED(LEDvalue, Cmd, Kbd=0) {
SetUnicodeStr(fn,"\Device\KeyBoardClass" Kbd)
h_device := NtCreateFile(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,0)
If (Cmd = "switch") ;switches every LED according to LEDvalue
KeyLED:= LEDvalue
If (Cmd = "on") ;forces all choosen LED's to ON (LEDvalue= 0 ->LED's according to keystate)
KeyLED:= LEDvalue | (GetKeyState("ScrollLock", "T") + 2*GetKeyState("NumLock", "T") + 4*GetKeyState("CapsLock", "T"))
If (Cmd = "off") { ;forces all choosen LED's to OFF (LEDvalue= 0 ->LED's according to keystate)
LEDvalue := LEDvalue ^ 7
KeyLED := LEDvalue & (GetKeyState("ScrollLock", "T") + 2*GetKeyState("NumLock", "T") + 4*GetKeyState("CapsLock", "T"))
}
success := DllCall( "DeviceIoControl" , "ptr", h_device , "uint", CTL_CODE( 0x0000000b , 2 , 0 , 0 ) , "int*", KeyLED << 16 , "uint", 4 , "ptr", 0 , "uint", 0 , "ptr*", output_actual , "ptr", 0 )
NtCloseFile(h_device)
return success
}
CTL_CODE( p_device_type, p_function, p_method, p_access ) {
return, ( p_device_type << 16 ) | ( p_access << 14 ) | ( p_function << 2 ) | p_method
}
NtCreateFile(ByRef wfilename,desiredaccess,sharemode,createdist,flags,fattribs) {
VarSetCapacity(objattrib,6*A_PtrSize,0)
VarSetCapacity(io,2*A_PtrSize,0)
VarSetCapacity(pus,2*A_PtrSize)
DllCall("ntdll\RtlInitUnicodeString","ptr",&pus,"ptr",&wfilename)
NumPut(6*A_PtrSize,objattrib,0)
NumPut(&pus,objattrib,2*A_PtrSize)
status:=DllCall("ntdll\ZwCreateFile","ptr*",fh,"UInt",desiredaccess,"ptr",&objattrib ,"ptr",&io,"ptr",0,"UInt",fattribs,"UInt",sharemode,"UInt",createdist ,"UInt",flags,"ptr",0,"UInt",0, "UInt")
return % fh
}
NtCloseFile(handle) {
return DllCall("ntdll\ZwClose","ptr",handle)
}
SetUnicodeStr(ByRef out, str_) {
VarSetCapacity(out,2*StrPut(str_,"utf-16"))
StrPut(str_,&out,"utf-16")
}
I want to implement a poor mans "Windows Fences" (by stardock software) using autohotkey.
It can be as ineffective as it can as far as programming goes. I just want to get the positions of each desktop icon upon running a ahk code snippet and using another code snippet, I'd like to put them back to where they were.
I looked at the ahk code contributions and didn't see anything like this. But again, my search terms might be a little off. Assuming no such code exists, is there a way to get the screen positions of each icon and their identifying information in autohotkey ? This will at least help me start. I am sure more questions will come.
Example
Try the following with the function posted below :
icons := getDeskIconsPos()
chromePos := icons["Google Chrome"]
for k, pos in chromePos
{
msgbox % "Google Chrome.lnk is at X: " pos.x " Y: " pos.y
}
Description
The function returns an object (thanks to MCL) with each item being identified by name. Under each name item is an array of all occurring instances. Each array item will have an X and Y containing the corresponding coordinates.
See code for THE_ITEMNAME, THE_X_COORD and THE_Y_COORD.
I have used these names to clarify where the information is stored.
The Function
getDeskIconsPos() {
Critical
static MEM_COMMIT := 0x1000, PAGE_READWRITE := 0x04, MEM_RELEASE := 0x8000
static LVM_GETITEMPOSITION := 0x00001010, LVM_SETITEMPOSITION := 0x0000100F, WM_SETREDRAW := 0x000B
ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
if !hwWindow ; #D mode
ControlGet, hwWindow, HWND,, SysListView321, A
IfWinExist ahk_id %hwWindow% ; last-found window set
WinGet, iProcessID, PID
hProcess := DllCall("OpenProcess" , "UInt", 0x438 ; PROCESS-OPERATION|READ|WRITE|QUERY_INFORMATION
, "Int", FALSE ; inherit = false
, "ptr", iProcessID)
ret := {}
if hwWindow and hProcess
{
ControlGet, list, list,Col1
VarSetCapacity(iCoord, 8)
pItemCoord := DllCall("VirtualAllocEx", "ptr", hProcess, "ptr", 0, "UInt", 8, "UInt", MEM_COMMIT, "UInt", PAGE_READWRITE)
Loop, Parse, list, `n ;Loop through items in list and get the information from the POINT structures
{
SendMessage, %LVM_GETITEMPOSITION%, % A_Index-1, %pItemCoord%
DllCall("ReadProcessMemory", "ptr", hProcess, "ptr", pItemCoord, "UInt", &iCoord, "UInt", 8, "UIntP", cbReadWritten)
;<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
THE_ITEMNAME := A_LoopField
THE_X_COORD := NumGet(iCoord,"Int")
THE_Y_COORD := Numget(iCoord, 4,"Int")
;<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>
if(!ret.HasKey(THE_ITEMNAME))
{
ret[THE_ITEMNAME] := []
}
ret[THE_ITEMNAME].Insert({x: THE_X_COORD, y: THE_Y_COORD})
}
DllCall("VirtualFreeEx", "ptr", hProcess, "ptr", pItemCoord, "ptr", 0, "UInt", MEM_RELEASE)
}
DllCall("CloseHandle", "ptr", hProcess)
return ret
}
Extra
If you simply want to save and restore the desktop icon positions, you may try DeskIcons() here :
http://ahkscript.org/boards/viewtopic.php?f=6&t=3529
Example usage of DeskIcons() :
; save positions
coords := DeskIcons()
MsgBox now move the icons around yourself
; load positions
DeskIcons(coords)
I don't think there's an easy way to achieche this. But ImageSearch should work quite well if performance isn't an issue (even if it is: for smaller numbers of icons, it should still perform acceptably). The only problem I see is the desktop background: If it changes, ImageSearch will most likely fail, except for perfectly quadratic/nontransparent icons. There are three workarounds for that:
Never change your desktop background. The easiest way but most likely not an option if you are a frequent desktop restyler.
Take new screenshots of the icons every time you change the background. Very high maintenance depending on your need to change the desktop.
Let the script change the desktop background to a default color before it runs ImageSearch. My favorite since it's easy to implement and you won't have to worry about anything.
After you've found the position of the respective icon, the rest is pretty trivial: MouseClickDrag it from its old position to the target position.
References:
ImageSearch
docs
MouseClickDrag docs
Changing the desktop background with AHK
Say I call a function that uses a byref modifier. Once in the function, I want to fetch the string value of the passed variable.
myvar := "george"
passit(myvar)
passit(byref whatvar){
msgbox % %whatvar% ;I should see a messagebox reporting the string "myvar"
}
Getting the string value of the variable works fine if I'm not passing the variable byref.
Maybe I'm going about this the wrong way. I want the function to know the string name for the variable being referenced.
This approch uses the buildin ListLines-Command to access the needed metadata.
The command ListLines opens the main window of the current script and displays the last executed script lines.
Content looks like this:
Script lines most recently executed (oldest first). Press [F5] to refresh. The seconds elapsed between a line and the one after it is in parentheses to the right (if not 0). The bottommost line's elapsed time is the number of seconds since it executed.
---- D:\Eigene_Dateien\ahk scripts\test3.ahk
002: myvar := "george"
003: passit(myvar)
007: MsgBox,GetOriginalVariableNameForSingleArgumentOfCurrentCall(A_ThisFunc)
012: lines := ListLines()
Press [F5] to refresh.
This data can be parsed to extract the wanted information (what is passed to 'passit').
One problem here is, that there is no buildin programmatically way of access this info.
The function ListLines overrides temporary User32.ShowWindow and User32.SetForgroundWindow to return simply true, so the buildin command ListLines can be used without displaying its window (Might produce problems with multithreaded scripts). From this 'hidden' window its text is received and cleaned up. Function is written by Lexikos (http://www.autohotkey.com/board/topic/20925-listvars/#entry156570 http://www.autohotkey.com/board/topic/58110-printing-listlines-into-a-file/#entry365156).
GetOriginalVariableNameForSingleArgumentOfCurrentCall extracts the variable name with a regular expression, which searches the first call to the passed function above the current call (call to GetOriginalVariableNameForSingleArgumentOfCurrentCall).
myvar := "george"
passit(myvar)
return
passit(whatvar){
msgbox % GetOriginalVariableNameForSingleArgumentOfCurrentCall(A_ThisFunc)
}
GetOriginalVariableNameForSingleArgumentOfCurrentCall(callerFuncName)
{
lines := ListLines()
pattern = O)%callerFuncName%\((.*?)\).*?%A_ThisFunc%\(.*?\)
RegExMatch(lines, pattern, match)
return match[1]
}
; Originally written by Lexikos / Copy of ListGlobalVars http://www.autohotkey.com/board/topic/20925-listvars/#entry156570
; with modifications from here http://www.autohotkey.com/board/topic/58110-printing-listlines-into-a-file/#entry365156
; Tested/Modified for AHK Unicode 64bit v1.1.14.03
ListLines()
{
static hwndEdit, pSFW, pSW, bkpSFW, bkpSW
ListLines Off
if !hwndEdit
{
dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
Process, Exist
ControlGet, hwndEdit, Hwnd,, Edit1, ahk_class AutoHotkey ahk_pid %ErrorLevel%
DetectHiddenWindows, %dhw%
astr := A_IsUnicode ? "astr":"str"
ptr := A_PtrSize=8 ? "ptr":"uint"
hmod := DllCall("GetModuleHandle", "str", "user32.dll")
pSFW := DllCall("GetProcAddress", ptr, hmod, astr, "SetForegroundWindow")
pSW := DllCall("GetProcAddress", ptr, hmod, astr, "ShowWindow")
DllCall("VirtualProtect", ptr, pSFW, ptr, 8, "uint", 0x40, "uint*", 0)
DllCall("VirtualProtect", ptr, pSW, ptr, 8, "uint", 0x40, "uint*", 0)
bkpSFW := NumGet(pSFW+0, 0, "int64")
bkpSW := NumGet(pSW+0, 0, "int64")
}
if (A_PtrSize=8) {
NumPut(0x0000C300000001B8, pSFW+0, 0, "int64") ; return TRUE
NumPut(0x0000C300000001B8, pSW+0, 0, "int64") ; return TRUE
} else {
NumPut(0x0004C200000001B8, pSFW+0, 0, "int64") ; return TRUE
NumPut(0x0008C200000001B8, pSW+0, 0, "int64") ; return TRUE
}
ListLines
NumPut(bkpSFW, pSFW+0, 0, "int64")
NumPut(bkpSW, pSW+0, 0, "int64")
; Retrieve ListLines text and strip out some unnecessary stuff:
ControlGetText, ListLinesText,, ahk_id %hwndEdit%
RegExMatch(ListLinesText, ".*`r`n`r`n\K[\s\S]*(?=`r`n`r`n.*$)", ListLinesText)
StringReplace, ListLinesText, ListLinesText, `r`n, `n, All
ListLines On
return ListLinesText ; This line appears in ListLines if we're called more than once.
}
The closest to what you would want...? This reminds of a question I had.
See http://ahkscript.org/boards/viewtopic.php?f=14&t=3651
myvar:="test"
passit("myvar") ; display value, and change it
msgbox % "myvar = " myvar
passit(byref whatvar){ ; no more need for byref here...
msgbox % whatvar " = " (%whatvar%)
%whatvar%:="blah" ; edit globalvar "hack"
}
in this script that I use i can replace only one word teams--> milan, juventus, inter..
But i want replace many words (not only one word) for example:
[simply word replacement jack-->beta]
alfa-->beta
[sentence replacement jack-->jack,john,alfa]
jack
jack
john
alfa
This is actually code that i use
loop {
While !RegexMatch(strCapture, "teams$") {
Input, strUserInput, V L1, {BackSpace} ; V: visible, L1: Character length 1
If ErrorLevel = Endkey:BackSpace
strCapture := SubStr(strCapture, 1, StrLen(strUserInput) - 1)
else
strCapture .= strUserInput
; tooltip % ErrorLevel "`n" strUserInput "`n" strCapture "`n" ; enable this to see what actually happens
}
SendInput,
(Ltrim
{Backspace 5}
milan
juventus
inter
roma
lazio
napoli
mantova
)
strCapture := ""
}
How can I modify the code?
It is also possible to run the script integrating copy-paste?
You could use a For loop to replace the contents, but this would become increasingly tedious to maintain at scale, so YMMV.
The following will use the clipboard contents as the to/from variables, but you can swap it out with a variable as desired (replace "clipboard" with your string variable).
F3::
{
replace := {"alfa":"beta", "gamma":"delta"}
For start, end in replace {
StringReplace, clipboard, clipboard, %start%, %end%, All
}}
Return