Last active
July 25, 2023 13:06
-
-
Save qwerty12/4b3f41eb61724cd9e8f2bb5cc15c33c2 to your computer and use it in GitHub Desktop.
BrightnessSetter: set laptop brightness and show Windows 10's native brightness OSD (https://github.com/qwerty12/AutoHotkeyScripts/tree/master/LaptopBrightnessSetter)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BrightnessSetter { | |
; qwerty12 - 27/05/17 | |
; https://github.com/qwerty12/AutoHotkeyScripts/tree/master/LaptopBrightnessSetter | |
static _WM_POWERBROADCAST := 0x218, _osdHwnd := 0, hPowrprofMod := DllCall("LoadLibrary", "Str", "powrprof.dll", "Ptr") | |
__New() { | |
if (BrightnessSetter.IsOnAc(AC)) | |
this._AC := AC | |
if ((this.pwrAcNotifyHandle := DllCall("RegisterPowerSettingNotification", "Ptr", A_ScriptHwnd, "Ptr", BrightnessSetter._GUID_ACDC_POWER_SOURCE(), "UInt", DEVICE_NOTIFY_WINDOW_HANDLE := 0x00000000, "Ptr"))) ; Sadly the callback passed to *PowerSettingRegister*Notification runs on a new threadl | |
OnMessage(this._WM_POWERBROADCAST, ((this.pwrBroadcastFunc := ObjBindMethod(this, "_On_WM_POWERBROADCAST")))) | |
} | |
__Delete() { | |
if (this.pwrAcNotifyHandle) { | |
OnMessage(BrightnessSetter._WM_POWERBROADCAST, this.pwrBroadcastFunc, 0) | |
,DllCall("UnregisterPowerSettingNotification", "Ptr", this.pwrAcNotifyHandle) | |
,this.pwrAcNotifyHandle := 0 | |
,this.pwrBroadcastFunc := "" | |
} | |
} | |
SetBrightness(increment, jump := False, showOSD := True, autoDcOrAc := -1, ptrAnotherScheme := 0) | |
{ | |
static PowerGetActiveScheme := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerGetActiveScheme", "Ptr") | |
,PowerSetActiveScheme := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerSetActiveScheme", "Ptr") | |
,PowerWriteACValueIndex := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerWriteACValueIndex", "Ptr") | |
,PowerWriteDCValueIndex := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerWriteDCValueIndex", "Ptr") | |
,PowerApplySettingChanges := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerApplySettingChanges", "Ptr") | |
if (increment == 0 && !jump) { | |
if (showOSD) | |
BrightnessSetter._ShowBrightnessOSD() | |
return | |
} | |
if (!ptrAnotherScheme ? DllCall(PowerGetActiveScheme, "Ptr", 0, "Ptr*", currSchemeGuid, "UInt") == 0 : DllCall("powrprof\PowerDuplicateScheme", "Ptr", 0, "Ptr", ptrAnotherScheme, "Ptr*", currSchemeGuid, "UInt") == 0) { | |
if (autoDcOrAc == -1) { | |
if (this != BrightnessSetter) { | |
AC := this._AC | |
} else { | |
if (!BrightnessSetter.IsOnAc(AC)) { | |
DllCall("LocalFree", "Ptr", currSchemeGuid, "Ptr") | |
return | |
} | |
} | |
} else { | |
AC := !!autoDcOrAc | |
} | |
currBrightness := 0 | |
if (jump || BrightnessSetter._GetCurrentBrightness(currSchemeGuid, AC, currBrightness)) { | |
maxBrightness := BrightnessSetter.GetMaxBrightness() | |
,minBrightness := BrightnessSetter.GetMinBrightness() | |
if (jump || !((currBrightness == maxBrightness && increment > 0) || (currBrightness == minBrightness && increment < minBrightness))) { | |
if (currBrightness + increment > maxBrightness) | |
increment := maxBrightness | |
else if (currBrightness + increment < minBrightness) | |
increment := minBrightness | |
else | |
increment += currBrightness | |
if (DllCall(AC ? PowerWriteACValueIndex : PowerWriteDCValueIndex, "Ptr", 0, "Ptr", currSchemeGuid, "Ptr", BrightnessSetter._GUID_VIDEO_SUBGROUP(), "Ptr", BrightnessSetter._GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS(), "UInt", increment, "UInt") == 0) { | |
; PowerApplySettingChanges is undocumented and exists only in Windows 8+. Since both the Power control panel and the brightness slider use this, we'll do the same, but fallback to PowerSetActiveScheme if on Windows 7 or something | |
if (!PowerApplySettingChanges || DllCall(PowerApplySettingChanges, "Ptr", BrightnessSetter._GUID_VIDEO_SUBGROUP(), "Ptr", BrightnessSetter._GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS(), "UInt") != 0) | |
DllCall(PowerSetActiveScheme, "Ptr", 0, "Ptr", currSchemeGuid, "UInt") | |
} | |
} | |
if (showOSD) | |
BrightnessSetter._ShowBrightnessOSD() | |
} | |
DllCall("LocalFree", "Ptr", currSchemeGuid, "Ptr") | |
} | |
} | |
IsOnAc(ByRef acStatus) | |
{ | |
static SystemPowerStatus | |
if (!VarSetCapacity(SystemPowerStatus)) | |
VarSetCapacity(SystemPowerStatus, 12) | |
if (DllCall("GetSystemPowerStatus", "Ptr", &SystemPowerStatus)) { | |
acStatus := NumGet(SystemPowerStatus, 0, "UChar") == 1 | |
return True | |
} | |
return False | |
} | |
GetDefaultBrightnessIncrement() | |
{ | |
static ret := 10 | |
DllCall("powrprof\PowerReadValueIncrement", "Ptr", BrightnessSetter._GUID_VIDEO_SUBGROUP(), "Ptr", BrightnessSetter._GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS(), "UInt*", ret, "UInt") | |
return ret | |
} | |
GetMinBrightness() | |
{ | |
static ret := -1 | |
if (ret == -1) | |
if (DllCall("powrprof\PowerReadValueMin", "Ptr", BrightnessSetter._GUID_VIDEO_SUBGROUP(), "Ptr", BrightnessSetter._GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS(), "UInt*", ret, "UInt")) | |
ret := 0 | |
return ret | |
} | |
GetMaxBrightness() | |
{ | |
static ret := -1 | |
if (ret == -1) | |
if (DllCall("powrprof\PowerReadValueMax", "Ptr", BrightnessSetter._GUID_VIDEO_SUBGROUP(), "Ptr", BrightnessSetter._GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS(), "UInt*", ret, "UInt")) | |
ret := 100 | |
return ret | |
} | |
_GetCurrentBrightness(schemeGuid, AC, ByRef currBrightness) | |
{ | |
static PowerReadACValueIndex := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerReadACValueIndex", "Ptr") | |
,PowerReadDCValueIndex := DllCall("GetProcAddress", "Ptr", BrightnessSetter.hPowrprofMod, "AStr", "PowerReadDCValueIndex", "Ptr") | |
return DllCall(AC ? PowerReadACValueIndex : PowerReadDCValueIndex, "Ptr", 0, "Ptr", schemeGuid, "Ptr", BrightnessSetter._GUID_VIDEO_SUBGROUP(), "Ptr", BrightnessSetter._GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS(), "UInt*", currBrightness, "UInt") == 0 | |
} | |
_ShowBrightnessOSD() | |
{ | |
static PostMessagePtr := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "user32.dll", "Ptr"), "AStr", A_IsUnicode ? "PostMessageW" : "PostMessageA", "Ptr") | |
,WM_SHELLHOOK := DllCall("RegisterWindowMessage", "Str", "SHELLHOOK", "UInt") | |
if A_OSVersion in WIN_VISTA,WIN_7 | |
return | |
BrightnessSetter._RealiseOSDWindowIfNeeded() | |
; Thanks to YashMaster @ https://github.com/YashMaster/Tweaky/blob/master/Tweaky/BrightnessHandler.h for realising this could be done: | |
if (BrightnessSetter._osdHwnd) | |
DllCall(PostMessagePtr, "Ptr", BrightnessSetter._osdHwnd, "UInt", WM_SHELLHOOK, "Ptr", 0x37, "Ptr", 0) | |
} | |
_RealiseOSDWindowIfNeeded() | |
{ | |
static IsWindow := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "user32.dll", "Ptr"), "AStr", "IsWindow", "Ptr") | |
if (!DllCall(IsWindow, "Ptr", BrightnessSetter._osdHwnd) && !BrightnessSetter._FindAndSetOSDWindow()) { | |
BrightnessSetter._osdHwnd := 0 | |
try if ((shellProvider := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{00000000-0000-0000-C000-000000000046}"))) { | |
try if ((flyoutDisp := ComObjQuery(shellProvider, "{41f9d2fb-7834-4ab6-8b1b-73e74064b465}", "{41f9d2fb-7834-4ab6-8b1b-73e74064b465}"))) { | |
DllCall(NumGet(NumGet(flyoutDisp+0)+3*A_PtrSize), "Ptr", flyoutDisp, "Int", 0, "UInt", 0) | |
,ObjRelease(flyoutDisp) | |
} | |
ObjRelease(shellProvider) | |
if (BrightnessSetter._FindAndSetOSDWindow()) | |
return | |
} | |
; who knows if the SID & IID above will work for future versions of Windows 10 (or Windows 8). Fall back to this if needs must | |
Loop 2 { | |
SendEvent {Volume_Mute 2} | |
if (BrightnessSetter._FindAndSetOSDWindow()) | |
return | |
Sleep 100 | |
} | |
} | |
} | |
_FindAndSetOSDWindow() | |
{ | |
static FindWindow := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "user32.dll", "Ptr"), "AStr", A_IsUnicode ? "FindWindowW" : "FindWindowA", "Ptr") | |
return !!((BrightnessSetter._osdHwnd := DllCall(FindWindow, "Str", "NativeHWNDHost", "Str", "", "Ptr"))) | |
} | |
_On_WM_POWERBROADCAST(wParam, lParam) | |
{ | |
;OutputDebug % &this | |
if (wParam == 0x8013 && lParam && NumGet(lParam+0, 0, "UInt") == NumGet(BrightnessSetter._GUID_ACDC_POWER_SOURCE()+0, 0, "UInt")) { ; PBT_POWERSETTINGCHANGE and a lazy comparison | |
this._AC := NumGet(lParam+0, 20, "UChar") == 0 | |
return True | |
} | |
} | |
_GUID_VIDEO_SUBGROUP() | |
{ | |
static GUID_VIDEO_SUBGROUP__ | |
if (!VarSetCapacity(GUID_VIDEO_SUBGROUP__)) { | |
VarSetCapacity(GUID_VIDEO_SUBGROUP__, 16) | |
,NumPut(0x7516B95F, GUID_VIDEO_SUBGROUP__, 0, "UInt"), NumPut(0x4464F776, GUID_VIDEO_SUBGROUP__, 4, "UInt") | |
,NumPut(0x1606538C, GUID_VIDEO_SUBGROUP__, 8, "UInt"), NumPut(0x99CC407F, GUID_VIDEO_SUBGROUP__, 12, "UInt") | |
} | |
return &GUID_VIDEO_SUBGROUP__ | |
} | |
_GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS() | |
{ | |
static GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__ | |
if (!VarSetCapacity(GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__)) { | |
VarSetCapacity(GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__, 16) | |
,NumPut(0xADED5E82, GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__, 0, "UInt"), NumPut(0x4619B909, GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__, 4, "UInt") | |
,NumPut(0xD7F54999, GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__, 8, "UInt"), NumPut(0xCB0BAC1D, GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__, 12, "UInt") | |
} | |
return &GUID_DEVICE_POWER_POLICY_VIDEO_BRIGHTNESS__ | |
} | |
_GUID_ACDC_POWER_SOURCE() | |
{ | |
static GUID_ACDC_POWER_SOURCE_ | |
if (!VarSetCapacity(GUID_ACDC_POWER_SOURCE_)) { | |
VarSetCapacity(GUID_ACDC_POWER_SOURCE_, 16) | |
,NumPut(0x5D3E9A59, GUID_ACDC_POWER_SOURCE_, 0, "UInt"), NumPut(0x4B00E9D5, GUID_ACDC_POWER_SOURCE_, 4, "UInt") | |
,NumPut(0x34FFBDA6, GUID_ACDC_POWER_SOURCE_, 8, "UInt"), NumPut(0x486551FF, GUID_ACDC_POWER_SOURCE_, 12, "UInt") | |
} | |
return &GUID_ACDC_POWER_SOURCE_ | |
} | |
} | |
BrightnessSetter_new() { | |
return new BrightnessSetter() | |
} |
why am i unable to get this script working when compiled
is it just me?
i like this code and i have been using it for literally years now
but i have nvr been able to compile it, so ive just been cramming it into other scripts i leave uncompiled
[not a great plan]
@perplex3
try
BS := new BrightnessSetter()
CapsLock::BS.SetBrightness(+1)
Hey 53901, thanks a lot!!
it works with
!up::BS.SetBrightness(+1)
!down::BS.SetBrightness(-1)
cheers!
Hi @Arora-Sir,
Thanks for letting me know. I can't promise I can fix the script for Windows 11 (displaying the brightness OSD on demand was a hack that YashMaster came up with), but I'll try and take a look over the weekend...
please fix it
Hello, is there any news/workaround to have this (osd) working on W11?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi everyone,
I'm quite new to AHK and have only basic skills in scripting. I tried to implement the script but if I try to assign a hotkey to the SetBrightness function (i.e. "CapsLock & v:: SetBrightness(1)") it gives me an error saying
"Error: Call to nonexisting function.
Specifically: SetBrightness(1)"
I have no clue what to do with this, because I rely mostly on try and error :-) Does anyone have a suggestion?
Thanks a lot!