GetParameterFloat returning invalid status when attempting to use Voicemeeter API with AHK - autohotkey

I am attempting to right a simple script in AutoHotKey (AHK) that I can use to switch sources a bit more easily that with the Voicemeeter Remote panel that is included. I am using Voicemeeter Potato. After some mucking around, I was able to get the SetParameterFloat API call to work. For some reason I cannot get the GetParameterFloat call to work when trying to retrieve the status of the input selection (A1, A2, etc). GetParameterFloat just returns 0 regardless of whether the input is enabled. Is there something I have missed here?
Here is my full code (most promising version to date)
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance Force
WinWait, ahk_exe voicemeeter8.exe ; wait for voicemeeter
DllLoad := DllCall("LoadLibrary", "Str", "C:\Program Files (x86)\VB\Voicemeeter\VoicemeeterRemote64.dll")
MsgBox, LoadLibrary: %ErrorLevel%
VMLogin()
OnExit("VMLogout")
Result := DllCall("VoicemeeterRemote64\VBVMR_SetParameterFloat", "AStr", "Bus[0].Gain", "Float", 0.0)
Result := DllCall("VoicemeeterRemote64\VBVMR_SetParameterFloat", "AStr", "Bus[1].Gain", "Float", 0.0)
Result := DllCall("VoicemeeterRemote64\VBVMR_SetParameterFloat", "AStr", "Strip[3].A1", "Float", 1.0)
Result := DllCall("VoicemeeterRemote64\VBVMR_SetParameterFloat", "AStr", "Strip[3].A2", "Float", 0.0)
VMLogin() {
Login := DllCall("VoicemeeterRemote64\VBVMR_Login")
MsgBox,Login: %ErrorLevel%
}
VMLogout() {
Logout := DllCall("VoicemeeterRemote64\VBVMR_Logout")
MsgBox, Logout: %ErrorLevel%
}
!s::
DllCall("VoicemeeterRemote64\VBVMR_IsParametersDirty")
MsgBox, IsParameterDirty: %ErrorLevel%
Result := DllCall("VoicemeeterRemote64\VBVMR_GetParameterFloat", "AStr", "Strip[1].A1", "Ptr", &str1stat, "Int")
MsgBox, GetParameterFloat: %ErrorLevel%
str1stat := NumGet(str1stat, 0, "Float")
MsgBox, NumGet: %str1stat%
MsgBox, GetResult: %Result%
Result := DllCall("VoicemeeterRemote64\VBVMR_SetParameterFloat", "AStr", "Strip[1].A1", "Float", 1.0)
MsgBox, SetParameterFloat: %ErrorLevel%
return
Majority of this code has been gleaned from here: https://gist.github.com/dcragusa/f3ab67ba1ed692cb628d1ef45dc9fac1
I am very new to using API calls so I would not be surprised if I missed something simple.

Related

Autohotkey DLLcall to CreateCaret returns 0 (The function failed) but A_LastError is also 0 (The function succeeded)

I'm trying to use a simple AHK DLLCall to the user32 api function CreateCaret. I want it to give notepad a thick text caret.
caretWidth := 10
NULL := 0
Ptr := A_PtrSize ? "Ptr" : "UInt" ; If A_PtrSize is not defined, use UInt instead.
WinHwnd := WinExist("A")
result := Dllcall("CreateCaret", Ptr, WinHwnd, Ptr, NULL, "Int", caretWidth, "Int", 0)
msgbox % "LE " A_lasterror ; Gives LE 0
msgbox % result ; Gives 0
This should be equivalent to the following c++ call:
CreateCaret(0x37072c, NULL, 10, 0);
Purposefully screwing up the function name makes result blank, so I believe the function is being called correctly. I just don't know why it is failing
Using similar code for GetCursorBlinkRate returns a sensible number.
I have also tried with caretWidth := 0
Similar questions about GetLastError are c++ calls, and AHK supposedly ensures that GetLastError is called in a timely enough manner to ensure A_lasterror is set correctly. Why is it showing no error code when the function apparently fails?
You can't change the caret of an external process.
If you try this for example, you'll see it works just fine if you own the process:
#Persistent
Gui, +hwndHWND
Gui, Add, Edit
Gui, Show
DllCall("CreateCaret", Ptr, HWND, Ptr, 0, Int, 50, Int, 50)
DllCall("ShowCaret", Ptr, HWND)
ESC::
GuiClose:
ExitApp

Switch keyboard layout Works but NOT Always

I'm a bit new to Autohotkey.
I have 3 Language installed, one of them I use very rarely. so I want to Toggle switch only between 2 languages (EN-RU) using WIN+Space.
I searched web found code which was short and logically close to my need, I done some modification to be more object like and personalised conditions.
Code: Select all - Expand View
#Space::
SetFormat, Integer, H
Lang := { "EN" : "0x4090409" , "RU" : "0x4190419", "HE": "0x40D040D" }
WinGet, WinID,, A
ThreadID:=DllCall("GetWindowThreadProcessId", "Int", WinID, "Int", "0")
InputLocaleID:=DllCall("GetKeyboardLayout", "Int", ThreadID)
if(InputLocaleID=Lang.RU OR InputLocaleID=Lang.HE)
SendMessage, 0x50,, % Lang.EN,, A
else if(InputLocaleID=Lang.EN)
SendMessage, 0x50,, % Lang.RU,, A
Exit
it works well with most of programs but with few of them it only get switch to RU.
Works Well: Chrome, notePad, notePad++, Notion, VScode, Android Studio, IntelliJ IDEA,
Doesn't Work: OneNote Windows 10 app (even so in Onenote 2016 it works fine)
If someone can help me with it I would Greatly appreciate it.
Thanks in Advance!
related answer Autohotkey Forum
#Space:: ; Switch keyboard (EN-RU)
Lang := { "EN": 0x4090409, "RU": 0x4190419 }
; For compatibility with UWP apps, get the thread of the focused
; control, not the active window. This is necessary because those
; apps are hosted within a window owned by a different process.
ControlGetFocus Focused, A
ControlGet CtrlID, Hwnd,, % Focused, A
; Using Ptr vs. Int vs. UInt won't matter in these cases
ThreadID := DllCall("GetWindowThreadProcessId", "Ptr", CtrlID, "Ptr", 0)
; HKL is a handle type (64-bit on x64)
InputLocaleID := DllCall("GetKeyboardLayout", "UInt", ThreadID, "Ptr")
if (InputLocaleID != Lang.EN)
SendMessage, 0x50,, % Lang.EN,, ahk_id %CtrlID%
else
SendMessage, 0x50,, % Lang.RU,, ahk_id %CtrlID%
Exit

Toggle HighContrast Theme - windows 10

I want to be able to toggle the HighContrast Theme in Windows 10, by pressing F1.
The shortcut for toggling the HighContrast Theme in Windows 10 is:
Left Alt + Left Shift + Print Screen
https://msdn.microsoft.com/en-us/library/hh923906.aspx
Here is my script:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; Toggle HighContrast Theme: Alt + Shift + PrintScreen
F1::
Send !+{PrintScreen}
Return
You can apply the setting by manually running the .theme file. The problem is that it will open the Settings dialog. This script will run the high contrast 1 theme file, wait for the Settings dialog to open, then close it.
Edit: Added code to toggle between two themes
hc := false
hctheme := "C:\Windows\Resources\Ease of Access Themes\hc1.theme"
stdtheme := "C:\Windows\Resources\Themes\theme1.theme"
; your personalized theme may be in
; C:\Users\{user.name}\AppData\Local\Microsoft\Windows\Themes\Custom.theme
F1::
hc := !hc
if (hc)
run %hctheme%
else
run %stdtheme%
WinWait Settings
WinClose Settings
return
In testing this, it seems that the Alt+PrtScr keyboard combo is hooked too low in the OS to be overridden by AutoHotKey to add in the Shift modifier before it just goes with the default of taking a screenshot of the active window. (Looking around the AHK forums, this seems to be the consensus as well.)
I did manage to find some script suggestions here, of which this slight modification does work for me on Win10 Pro:
F1:: ;toggle high contrast
vSize := A_PtrSize=8?16:12
VarSetCapacity(HIGHCONTRAST, vSize, 0)
NumPut(vSize, &HIGHCONTRAST, 0, "UInt") ;cbSize
;SPI_GETHIGHCONTRAST := 0x42
DllCall("user32\SystemParametersInfo", UInt,0x42, UInt,vSize, Ptr,&HIGHCONTRAST, UInt,0)
vFlags := NumGet(&HIGHCONTRAST, 4, "UInt") ;dwFlags
;JEE_Progress(vFlags, 1000)
if (vFlags & 1) ;HCF_HIGHCONTRASTON := 0x1
vFlags -= 1
else
vFlags += 1
;JEE_Progress(vFlags, 1000)
VarSetCapacity(HIGHCONTRAST, vSize, 0)
NumPut(vSize, &HIGHCONTRAST, 0, "UInt") ;cbSize
NumPut(vFlags, &HIGHCONTRAST, 4, "UInt") ;dwFlags
;SPI_SETHIGHCONTRAST := 0x43
DllCall("user32\SystemParametersInfo", UInt,0x43, UInt,vSize, Ptr,&HIGHCONTRAST, UInt,0)
return
Use this:
F1::
Send {LAlt down}{LShift down}{PrintScreen}{LAlt Up}{LShift Up}
return
From official documentation:
Press use down like : {LWin down} {RWin down}
Release use up like : {LWin up} {RWin up}

Autohotkey: How can I get the positions of win 7 desktop icons

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

Get String Value of passed ByRef Variable

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"
}