-
-
Save qwerty12/4b3f41eb61724cd9e8f2bb5cc15c33c2 to your computer and use it in GitHub Desktop.
| 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() | |
| } |
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?
Hi @qwerty12, @Arkaprava-Gupta, @Minibus93!
I had fixed this on my local setup earlier but forgot to push it to my repo until now! Sharing it here in case anyone else needs it.
If anyone is running this on Windows 11 and finding that showOSD triggers the Volume OSD / Volume Mute instead of the Brightness OSD, here is the fix:
In Windows 11, Microsoft updated the IFlyoutDisplay COM interface enum mapping and shell hook parameters:
-
Change the COM flyout index to
3:
Inside_RealiseOSDWindowIfNeeded(), change parameter0to3:; 0 = Volume, 1 = Airplane Mode, 3 = Display Brightness OSD Flyout DllCall(NumGet(NumGet(flyoutDisp+0)+3*A_PtrSize), "Ptr", flyoutDisp, "Int", 3, "UInt", 0)
-
Change
WM_SHELLHOOKparameter to0x38:
Inside_ShowBrightnessOSD(), change0x37to0x38:; 0x38 = Native Brightness OSD Flyout (0x37 was Volume OSD Flyout) if (BrightnessSetter._osdHwnd) DllCall(PostMessagePtr, "Ptr", BrightnessSetter._osdHwnd, "UInt", WM_SHELLHOOK, "Ptr", 0x38, "Ptr", 0)
-
Set
showOSD := TrueinSetBrightness.
You can check out the full working script here:
https://github.com/Arora-Sir/AutoHotKey-Windows-Scripts/blob/master/AllScripts/Brightness.ahk
With these changes, the official native Windows 11 Brightness OSD Flyout (the sun icon with cyan slider bar) renders correctly on modern Windows 11 builds without triggering the Volume OSD!
Hi! Thanks for the reply and thanks for fixing the script, it's just so awesome!
Hi @Minibus93 , You're most welcome! I'm really glad to hear it's working awesome for you! :)
If you have a quick moment, could you help me test one thing on your laptop to confirm?
When you press and hold down F1 (or Shift + F1), does the brightness adjust continuously and smoothly (like volume control keys do), or does it step slowly one increment at a time?
On my laptop (an Acer Predator Helios 300 - 2021 Model - i7 10th Gen), holding down F1 / Shift + F1 feels very slow now (taking input step-by-step rather than smoothly ramping up/down). It used to be fast in the past, so I'm trying to figure out whether a recent Windows update (few months back) slowed down WMI brightness inputs globally, or if it's just specific to my Acer Predator hardware/drivers. Because even if I use the laptop official keymaps which are fn + left/right key, they are actually too slow from the starting of the laptop. But this script previously fixed this issue (Maybe I've changed my motherboard that can also be the issue I don't know).
If you could test it on your laptop and let me know that in your laptop does it goes smoothly increase/decrease of brightness or like with steps (slowly) as I said above, that would be super helpful! Thanks again!
@Arora-Sir yes of course I can test it, however it may have to wait a few days as I'm currently on vacation and only have my mac with me so I don't have access to my windows pc, but I will indeed test it :D
Thank you @Minibus93, waiting for your reply then ππ
@perplex3
try
BS := new BrightnessSetter()
CapsLock::BS.SetBrightness(+1)