开始
ahk本身并未提供亮度控制的快捷api,但有以下三种方式可能实现:
- 使用DllCall调用win32函数。
- 使用ComObj调用cmd。
- 使用Run调用cmd。
由于我没有找到合适的win32dll,最终是使用了后两种。两种方法各有优缺,下面我们来说说细节。
代码见最后一节
脚本是通过调用cmd来获取和设置屏幕亮度的,通过以下命令可以完成所需功能:
- 设置
WMIC /NAMESPACE:\\root\wmi PATH WmiMonitorBrightnessMethods WHERE "Active=TRUE" CALL WmiSetBrightness Brightness=30 Timeout=0
- 获取
WMIC /NAMESPACE:\\root\wmi PATH WmiMonitorBrightness WHERE "Active=TRUE" GET /value
注意: 这是cmd而不是powershell
有了cmd命令后,就可以使用AHK调用cmd,传递此命令行。
官网上有一个调用示例,使用的是下面的方法:
- 使用com对象执行一条cmd。
- 使用com对象执行多条cmd。
class ShellRun {
static RunWaitOne(command) {
shell := ComObject("WScript.Shell")
exec := shell.Exec(A_ComSpec " /C " command)
return exec.StdOut.ReadAll()
}
static RunWaitMany(commands) {
shell := ComObject("WScript.Shell")
exec := shell.Exec(A_ComSpec " /Q /K echo off")
exec.StdIn.WriteLine(commands "`nexit")
return exec.StdOut.ReadAll()
}
}
但它的缺点是会出现cmd窗口的闪屏。
所以我们只适合使用它完成get
任务,而set
任务使用run
更好。
但,还有一种方法不会出现cmd窗口:
RunCMD(CmdLine, WorkingDir := "", Codepage := "CP0", Fn := "RunCMD_Output", Slow := 1) {
; RunCMD v0.97 by SKAN on D34E/D67E
; @ autohotkey.com/boards/viewtopic.php?t=74647
; Based on StdOutToVar.ahk by Sean
; @ autohotkey.com/board/topic/15455-stdouttovar
; Modified by TAC109 to not use A_Args (disrupts Ahk2Exe)
Slow := !!Slow, Fn := IsFunction(Fn) ? Fn : 0, P8 := (A_PtrSize = 8)
, DllCall("CreatePipe", "ptr*", &hPipeR := 0, "ptr*", &hPipeW := 0, "Ptr", 0, "Int", 0)
, DllCall("SetHandleInformation", "Ptr", hPipeW, "Int", 1, "Int", 1)
, DllCall("SetNamedPipeHandleState", "Ptr", hPipeR, "UIntP", PIPE_NOWAIT := 1, "Ptr", 0, "Ptr", 0)
, SI := Buffer(P8 ? 104 : 68, 0) ; STARTUPINFO structure
, NumPut('uint', P8 ? 104 : 68, SI) ; size of STARTUPINFO
, NumPut('uint', STARTF_USESTDHANDLES := 0x100, SI, P8 ? 60 : 44) ; dwFlags
, NumPut('uint', hPipeW, SI, P8 ? 88 : 60) ; hStdOutput
, NumPut('uint', hPipeW, SI, P8 ? 96 : 64) ; hStdError
, PI := Buffer(P8 ? 24 : 16) ; PROCESS_INFORMATION structure
If !DllCall("CreateProcess", "Ptr", 0, "Str", CmdLine, "Ptr", 0, "Int", 0, "Int", 1
, "Int", 0x08000000 | DllCall("GetPriorityClass", "Ptr", -1, "UInt"), "Int", 0
, "Ptr", WorkingDir ? StrPtr(WorkingDir) : 0, "Ptr", SI.Ptr, "Ptr", PI.Ptr)
Return Format("{1:}", "", ErrorLevel := -1
, DllCall("CloseHandle", "Ptr", hPipeW), DllCall("CloseHandle", "Ptr", hPipeR))
DllCall("CloseHandle", "Ptr", hPipeW)
, RnCMD := { PID: NumGet(PI, P8 ? 16 : 8, "UInt") }
, File := FileOpen(hPipeR, "h", Codepage), LineNum := 1, sOutput := ""
While (RnCMD.PID | DllCall("Sleep", "Int", Slow))
and DllCall("PeekNamedPipe", "Ptr", hPipeR, "Ptr", 0, "Int", 0, "Ptr", 0
, "Ptr", 0, "Ptr", 0)
While RnCMD.PID and StrLen(Line := File.ReadLine())
sOutput .= Fn ? Fn.Call(Line, LineNum++) : Line
RnCMD.PID := 0, hProcess := NumGet(PI, 0, 'uint'), hThread := NumGet(PI, A_PtrSize, 'uint')
, DllCall("GetExitCodeProcess", "Ptr", hProcess, "ptr*", &ExitCode := 0)
, DllCall("CloseHandle", "Ptr", hProcess), DllCall("CloseHandle", "Ptr", hThread)
, DllCall("CloseHandle", "Ptr", hPipeR), ErrorLevel := ExitCode
Return sOutput
}
我们选择第一种,因为闪屏在整个脚本运行期间只会出现一次。
Run
适合完成设置任务,比如将亮度设置为30:
Run(A_ComSpec ' /c "WMIC /NAMESPACE:\\root\wmi PATH WmiMonitorBrightnessMethods WHERE "Active=TRUE" CALL WmiSetBrightness Brightness=30 Timeout=0"', , 'Hide')
最后的参数Hide
设定窗口为隐藏执行。
完整代码
此脚本位于仓库ahk-scripts/lightCtrl.ahk
仓库:https://gitee.com/dkwd/ahk-scripts.git
#Requires AutoHotkey v2.0
#Include G:\AHK\git-ahk-lib\Tip.ahk
#Include G:\AHK\git-ahk-lib\ShellRun.ahk
^Home:: LightCtrl.Set(LightCtrl.Inc)
^End:: LightCtrl.Set(LightCtrl.Desc)
^SC046:: LightCtrl.Set(LightCtrl.Toggle) ; ^scrollock
class LightCtrl {
static cur := 0, low := 6, high := 30, inc := 0, desc := 1, toggle := 2
static Get() {
fields := ShellRun.RunWaitOne('WMIC /NAMESPACE:\\root\wmi PATH WmiMonitorBrightness WHERE "Active=TRUE" GET /value')
return +Rtrim(SubStr(fields, InStr(fields, match := 'CurrentBrightness=') + StrLen(match), 2), '`r`n')
}
static Set(action, param := 2) {
cur := this.cur || this.Get()
switch action {
case LightCtrl.Toggle: cur := _toggle()
case LightCtrl.Inc: cur := _inc(param)
case LightCtrl.Desc: cur := _desc(param)
default: throw Error('unsupport action')
}
Run(A_ComSpec
' /c "WMIC /NAMESPACE:\\root\wmi PATH WmiMonitorBrightnessMethods WHERE "Active=TRUE" CALL WmiSetBrightness Brightness='
cur ' Timeout=0"', , 'Hide')
this.cur := cur, _showTip()
_inc(val) => cur + val > 70 ? cur : cur + val
_desc(val) => cur - val <= 0 ? cur : cur - val
_toggle() => cur < 15 ? LightCtrl.high : LightCtrl.low
_showTip() {
dili := this.cur >= 10 ? ' ' : ' '
raw := '+===+`n'
. ' |' dili this.cur dili '|`n'
. '+===+`n'
Tip.ShowTip(raw)
}
}
}