[Class] Monitor (Brightness, Contrast, Gamma Ramp)

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

[Class] Monitor (Brightness, Contrast, Gamma Ramp)

26 May 2015, 06:02

Class Monitor
AutoHotkey wrapper for Monitor Configuration API Functions (msdn-docs)


Source
Mirror: Release on GitHub

Code: Select all

; ===============================================================================================================================
; AutoHotkey wrapper for Monitor Configuration API Functions
;
; Author ....: jNizM
; Released ..: 2015-05-26
; Modified ..: 2020-07-29
; Github ....: https://github.com/jNizM/Class_Monitor
; Forum .....: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=62955
; ===============================================================================================================================


class Monitor
{

	; ===== PUBLIC METHODS ======================================================================================================

	GetBrightness(Display := "")
	{
		if (hMonitor := this.GetMonitorHandle(Display))
		{
			PhysicalMonitors := this.GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor)
			hPhysicalMonitor := this.GetPhysicalMonitorsFromHMONITOR(hMonitor, PhysicalMonitors, PHYSICAL_MONITOR)
			Brightness := this.GetMonitorBrightness(hPhysicalMonitor)
			this.DestroyPhysicalMonitors(PhysicalMonitors, PHYSICAL_MONITOR)
			return Brightness
		}
		return false
	}


	GetContrast(Display := "")
	{
		if (hMonitor := this.GetMonitorHandle(Display))
		{
			PhysicalMonitors := this.GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor)
			hPhysicalMonitor := this.GetPhysicalMonitorsFromHMONITOR(hMonitor, PhysicalMonitors, PHYSICAL_MONITOR)
			Contrast := this.GetMonitorContrast(hPhysicalMonitor)
			this.DestroyPhysicalMonitors(PhysicalMonitors, PHYSICAL_MONITOR)
			return Contrast
		}
		return false
	}


	GetGammaRamp(Display := "")
	{
		if (DisplayName := this.GetDisplayName(Display))
		{
			if (hDC := this.CreateDC(DisplayName))
			{
				GammaRamp := this.GetDeviceGammaRamp(hDC)
				this.DeleteDC(hDC)
				return GammaRamp
			}
			this.DeleteDC(hDC)
		}
		return false
	}


	RestoreFactoryDefault(Display := "")
	{
		if (hMonitor := this.GetMonitorHandle(Display))
		{
			PhysicalMonitors := this.GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor)
			hPhysicalMonitor := this.GetPhysicalMonitorsFromHMONITOR(hMonitor, PhysicalMonitors, PHYSICAL_MONITOR)
			this.RestoreMonitorFactoryDefaults(hPhysicalMonitor)
			this.DestroyPhysicalMonitors(PhysicalMonitors, PHYSICAL_MONITOR)
			return true
		}
		return false
	}


	SetBrightness(Brightness, Display := "")
	{
		if (hMonitor := this.GetMonitorHandle(Display))
		{
			PhysicalMonitors := this.GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor)
			hPhysicalMonitor := this.GetPhysicalMonitorsFromHMONITOR(hMonitor, PhysicalMonitors, PHYSICAL_MONITOR)
			GetBrightness    := this.GetMonitorBrightness(hPhysicalMonitor)
			Brightness := (Brightness < GetBrightness["Minimum"]) ? GetBrightness["Minimum"]
						: (Brightness > GetBrightness["Maximum"]) ? GetBrightness["Maximum"]
						: (Brightness)
			this.SetMonitorBrightness(hPhysicalMonitor, Brightness)
			this.DestroyPhysicalMonitors(PhysicalMonitors, PHYSICAL_MONITOR)
			return Brightness
		}
		return false
	}


	SetContrast(Contrast, Display := "")
	{
		if (hMonitor := this.GetMonitorHandle(Display))
		{
			PhysicalMonitors := this.GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor)
			hPhysicalMonitor := this.GetPhysicalMonitorsFromHMONITOR(hMonitor, PhysicalMonitors, PHYSICAL_MONITOR)
			GetContrast      := this.GetMonitorContrast(hPhysicalMonitor)
			Contrast := (Contrast < GetContrast["Minimum"]) ? GetContrast["Minimum"]
					  : (Contrast > GetContrast["Maximum"]) ? GetContrast["Maximum"]
					  : (Contrast)
			this.SetMonitorContrast(hPhysicalMonitor, Contrast)
			this.DestroyPhysicalMonitors(PhysicalMonitors, PHYSICAL_MONITOR)
			return Contrast
		}
		return false
	}


	SetGammaRamp(Red, Green, Blue, Display := "")
	{
		if (DisplayName := this.GetDisplayName(Display))
		{
			if (hDC := this.CreateDC(DisplayName))
			{
				this.SetDeviceGammaRamp(hDC, Red, Green, Blue)
				this.DeleteDC(hDC)
				return true
			}
			this.DeleteDC(hDC)
		}
		return false
	}
	

	; ===== PRIVATE METHODS =====================================================================================================

	CreateDC(DisplayName)
	{
		if (hDC := DllCall("gdi32\CreateDC", "str", DisplayName, "ptr", 0, "ptr", 0, "ptr", 0, "ptr"))
			return hDC
		return false
	}


	DeleteDC(hDC)
	{
		if (DllCall("gdi32\DeleteDC", "ptr", hDC))
			return true
		return false
	}


	DestroyPhysicalMonitors(PhysicalMonitorArraySize, PHYSICAL_MONITOR)
	{
		if (DllCall("dxva2\DestroyPhysicalMonitors", "uint", PhysicalMonitorArraySize, "ptr", &PHYSICAL_MONITOR))
			return true
		return false
	}


	EnumDisplayMonitors(hMonitor := "")
	{
		static EnumProc := RegisterCallback(Monitor.EnumProc)
		static DisplayMonitors := {}

		if (MonitorNumber = "")
			DisplayMonitors := {}

		if (DisplayMonitors.MaxIndex() = "")
			if (DllCall("user32\EnumDisplayMonitors", "ptr", 0, "ptr", 0, "ptr", EnumProc, "ptr", &DisplayMonitors, "uint"))
				return (MonitorNumber = "") ? DisplayMonitors : DisplayMonitors.HasKey(MonitorNumber) ? DisplayMonitors[MonitorNumber] : false
		return false
	}


	EnumProc(hDC, RECT, ObjectAddr)
	{
		DisplayMonitors := Object(ObjectAddr)
		MonitorInfo := Monitor.GetMonitorInfo(this)
		DisplayMonitors.Push(MonitorInfo)
		return true
	}


	GetDeviceGammaRamp(hMonitor)
	{
		VarSetCapacity(GAMMA_RAMP, 1536, 0)
		if (DllCall("gdi32\GetDeviceGammaRamp", "ptr", hMonitor, "ptr", &GAMMA_RAMP))
		{
			GammaRamp := []
			GammaRamp["Red"]   := NumGet(GAMMA_RAMP,        2, "ushort") - 128
			GammaRamp["Green"] := NumGet(GAMMA_RAMP,  512 + 2, "ushort") - 128
			GammaRamp["Blue"]  := NumGet(GAMMA_RAMP, 1024 + 2, "ushort") - 128
			return GammaRamp
		}
		return false
	}


	GetDisplayName(Display := "")
	{
		DisplayName := ""

		if (Enum := this.EnumDisplayMonitors()) && (Display != "")
		{
			for k, Mon in Enum
				if (InStr(Mon["Name"], Display))
					DisplayName := Mon["Name"]
		}
		if (DisplayName = "")
			if (hMonitor := this.MonitorFromWindow())
				DisplayName := this.GetMonitorInfo(hMonitor)["Name"]

		return DisplayName
	}


	GetMonitorBrightness(hMonitor)
	{
		if (DllCall("dxva2\GetMonitorBrightness", "ptr", hMonitor, "uint*", Minimum, "uint*", Current, "uint*", Maximum))
			return { "Minimum": Minimum, "Current": Current, "Maximum": Maximum }
		return false
	}


	GetMonitorContrast(hMonitor)
	{
		if (DllCall("dxva2\GetMonitorContrast", "ptr", hMonitor, "uint*", Minimum, "uint*", Current, "uint*", Maximum))
			return { "Minimum": Minimum, "Current": Current, "Maximum": Maximum }
		return false
	}


	GetMonitorHandle(Display := "")
	{
		hMonitor := 0

		if (Enum := this.EnumDisplayMonitors()) && (Display != "")
		{
			for k, Mon in Enum
				if (InStr(Mon["Name"], Display))
					hMonitor := Mon["Handle"]
		}
		if !(hMonitor)
			hMonitor := this.MonitorFromWindow()

		return hMonitor
	}


	GetMonitorInfo(hMonitor)
	{
		NumPut(VarSetCapacity(MONITORINFOEX, 40 + (32 << !!A_IsUnicode)), MONITORINFOEX, 0, "uint")
		if (DllCall("user32\GetMonitorInfo", "ptr", hMonitor, "ptr", &MONITORINFOEX))
		{
			MONITORINFO := []
			MONITORINFO["Handle"]   := hMonitor
			MONITORINFO["Name"]     := Name := StrGet(&MONITORINFOEX + 40, 32)
			MONITORINFO["Number"]   := RegExReplace(Name, ".*(\d+)$", "$1")
			MONITORINFO["Left"]     := NumGet(MONITORINFOEX,  4, "int")
			MONITORINFO["Top"]      := NumGet(MONITORINFOEX,  8, "int")
			MONITORINFO["Right"]    := NumGet(MONITORINFOEX, 12, "int")
			MONITORINFO["Bottom"]   := NumGet(MONITORINFOEX, 16, "int")
			MONITORINFO["WALeft"]   := NumGet(MONITORINFOEX, 20, "int")
			MONITORINFO["WATop"]    := NumGet(MONITORINFOEX, 24, "int")
			MONITORINFO["WARight"]  := NumGet(MONITORINFOEX, 28, "int")
			MONITORINFO["WABottom"] := NumGet(MONITORINFOEX, 32, "int")
			MONITORINFO["Primary"]  := NumGet(MONITORINFOEX, 36, "uint")
			return MONITORINFO
		}
		return false
	}


	GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor)
	{
		if (DllCall("dxva2\GetNumberOfPhysicalMonitorsFromHMONITOR", "ptr", hMonitor, "uint*", NumberOfPhysicalMonitors))
			return NumberOfPhysicalMonitors
		return false
	}


	GetPhysicalMonitorsFromHMONITOR(hMonitor, PhysicalMonitorArraySize, ByRef PHYSICAL_MONITOR)
	{
		VarSetCapacity(PHYSICAL_MONITOR, (A_PtrSize + 256) * PhysicalMonitorArraySize, 0)
		if (DllCall("dxva2\GetPhysicalMonitorsFromHMONITOR", "ptr", hMonitor, "uint", PhysicalMonitorArraySize, "ptr", &PHYSICAL_MONITOR))
			return NumGet(PHYSICAL_MONITOR, 0, "ptr")
		return false
	}


	MonitorFromWindow(hWindow := 0)
	{
		static MONITOR_DEFAULTTOPRIMARY := 0x00000001

		if (hMonitor := DllCall("user32\MonitorFromWindow", "ptr", hWindow, "uint", MONITOR_DEFAULTTOPRIMARY))
			return hMonitor
		return false
	}


	RestoreMonitorFactoryDefaults(hMonitor)
	{
		if (DllCall("dxva2\RestoreMonitorFactoryDefaults", "ptr", hMonitor))
			return false
		return true
	}


	SetDeviceGammaRamp(hMonitor, Red, Green, Blue)
	{
		loop % VarSetCapacity(GAMMA_RAMP, 1536, 0) / 6
		{
			NumPut((r := (red   + 128) * (A_Index - 1)) > 65535 ? 65535 : r, GAMMA_RAMP,        2 * (A_Index - 1), "ushort")
			NumPut((g := (green + 128) * (A_Index - 1)) > 65535 ? 65535 : g, GAMMA_RAMP,  512 + 2 * (A_Index - 1), "ushort")
			NumPut((b := (blue  + 128) * (A_Index - 1)) > 65535 ? 65535 : b, GAMMA_RAMP, 1024 + 2 * (A_Index - 1), "ushort")
		}
		if (DllCall("gdi32\SetDeviceGammaRamp", "ptr", hMonitor, "ptr", &GAMMA_RAMP))
			return true
		return false
	}


	SetMonitorBrightness(hMonitor, Brightness)
	{
		if (DllCall("dxva2\SetMonitorBrightness", "ptr", hMonitor, "uint", Brightness))
			return true
		return false
	}


	SetMonitorContrast(hMonitor, Contrast)
	{
		if (DllCall("dxva2\SetMonitorContrast", "ptr", hMonitor, "uint", Contrast))
			return true
		return false
	}

}

; ===============================================================================================================================

For AHK v2
Monitor Class v2 by Tigerlily


Questions / Bugs / Issues
If you notice any kind of bugs or issues, report them here. Same for any kind of questions.


Copyright and License
The Unlicense
Last edited by jNizM on 02 Jun 2015, 08:49, edited 1 time in total.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

27 May 2015, 12:59

Examples
Retrieves a (particular) monitor's minimum, maximum, and current brightness settings.

Code: Select all

for k, v in Monitor.GetBrightness("\\.\DISPLAY2")   ; or just "2"
	MsgBox % k ": " v

Retrieves the defaults (primary) monitor's minimum, maximum, and current brightness settings.

Code: Select all

for k, v in Monitor.GetBrightness()   ; empty parameter
	MsgBox % k ": " v

Retrieves a (particular) monitor's minimum, maximum, and current contrast settings.

Code: Select all

for k, v in Monitor.GetContrast("\\.\DISPLAY2")   ; or just "2"
	MsgBox % k ": " v

Retrieves the defaults (primary) monitor's minimum, maximum, and current contrast settings.

Code: Select all

for k, v in Monitor.GetContrast()   ; empty parameter
	MsgBox % k ": " v

Retrieves a (particular) monitor's red, green and blue gamma ramp settings.

Code: Select all

for k, v in Monitor.GetGammaRamp("\\.\DISPLAY2")   ; or just "2"
	MsgBox % k ": " v

Retrieves the defaults (primary) monitor's red, green and blue gamma ramp settings.

Code: Select all

for k, v in Monitor.GetGammaRamp()   ; empty parameter
	MsgBox % k ": " v

Sets a (particular) monitor's brightness value.

Code: Select all

Monitor.SetBrightness(50, "\\.\DISPLAY2")   ; or just "2"

Sets the defaults (primary) monitor's brightness value.

Code: Select all

Monitor.SetBrightness(50)   ; empty parameter

Sets a (particular) monitor's contrast value.

Code: Select all

Monitor.SetContrast(50, "\\.\DISPLAY2")   ; or just "2"

Sets the defaults (primary) monitor's contrast value.

Code: Select all

Monitor.SetContrast(50)   ; empty parameter

Sets a (particular) monitor's red, green and blue gamma ramp value.

Code: Select all

Monitor.SetGammaRamp(100, 100, 80, "\\.\DISPLAY2")   ; or just "2"

Sets the defaults (primary) monitor's red, green and blue gamma ramp value.

Code: Select all

Monitor.SetGammaRamp(100, 100, 80)   ; empty parameter

Restores a (particular) monitor's settings to their factory defaults (brightness and contrast).

Code: Select all

Monitor.RestoreFactoryDefault(\\.\DISPLAY2")   ; or just "2"

Restores the defaults (primary) monitor's settings to their factory defaults (brightness and contrast).

Code: Select all

Monitor.RestoreFactoryDefault()   ; empty parameter

Todo
- tba
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

27 May 2015, 14:16

!!! DEPRECATED !!!


While I'm search more about this feature I found another interesting thing.
You don't need to call GetProcAddress. You can use the HANDLE + PROC_OFFSET

Code: Select all

hGDI32 := DllCall("kernel32.dll\GetModuleHandle", "Str", "gdi32.dll", "Ptr")
_GetDeviceGammaRamp := DllCall("kernel32.dll\GetProcAddress", "Ptr", hGDI32, "Ptr", 1472, "Ptr")
DllCall(_GetDeviceGammaRamp, "Ptr", hDC, "Ptr", &buf)

; ===============================================================================================================================

hGDI32 := DllCall("kernel32.dll\LoadLibrary", "Str", "gdi32.dll", "Ptr")
DllCall(hGDI32 + 0x0002B524, "Ptr", hDC, "Ptr", &buf)

Working Example:

Code: Select all

MsgBox % GetDeviceGammaRamp()

GetDeviceGammaRamp()
{
    static hGDI32 := DllCall("kernel32.dll\GetModuleHandle", "Str", "gdi32.dll", "Ptr")
    static _GetDeviceGammaRamp := DllCall("kernel32.dll\GetProcAddress", "Ptr", hGDI32, "Ptr", 1472, "Ptr")
    hDC := DllCall("user32.dll\GetDC", "Ptr", 0, "Ptr")
    VarSetCapacity(buf, 1536, 0)
    if !(DllCall(_GetDeviceGammaRamp, "Ptr", hDC, "Ptr", &buf))
        return "*" DllCall("kernel32.dll\GetLastError")
    DllCall("user32.dll\ReleaseDC", "Ptr", 0, "Ptr", hDC)
    return NumGet(buf, 2, "UShort") - 128
}

; ===============================================================================================================================

MsgBox % GetDeviceGammaRamp_2()

GetDeviceGammaRamp_2()
{
    static hGDI32 := DllCall("kernel32.dll\LoadLibrary", "Str", "gdi32.dll", "Ptr")
    hDC := DllCall("user32.dll\GetDC", "Ptr", 0, "Ptr")
    VarSetCapacity(buf, 1536, 0)
    if !(DllCall(hGDI32 + 0x0002B524, "Ptr", hDC, "Ptr", &buf))
        return "*" DllCall("kernel32.dll\GetLastError")
    DllCall("user32.dll\ReleaseDC", "Ptr", 0, "Ptr", hDC)
    DllCall("kernel32.dll\FreeLibrary", "Ptr", hGDI32)
    return NumGet(buf, 2, "UShort") - 128
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Class Monitor (Brightness, Contrast & Gamma)

27 May 2015, 17:32

i'm a big f.lux user, i wonder if that just uses these apis

question:

normally i see GetProcAddress passed the function name, but it looks like you are passing an integer number.

1. how did you get this number?
2. is there any benefit to doing that instead of passing the function name as a string?


jNizM wrote:With Dependency Walker
Gotcha, was not aware of that program. Thanks
jNizM wrote:While I'm search more about this feature I found another interesting thing.
You don't need to call GetProcAddress. You can use the HANDLE + PROC_OFFSET
Interesting. I guess the same question, how do you get the PROC_OFFSET?
Last edited by jNizM on 29 Jul 2020, 07:43, edited 1 time in total.
Reason: merged posts

User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 00:45

See picture above: "Entry Point" ;)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 02:04

guest3456 wrote:normally i see GetProcAddress passed the function name, but it looks like you are passing an integer number.
[...]
2. is there any benefit to doing that instead of passing the function name as a string?
No, there isn't.
jNizM wrote:You don't need to call GetProcAddress. You can use the HANDLE + PROC_OFFSET
What do you think happens when your users have a different version of the DLL? The entry point offset is not always going to be the same, unlike the name and ordinal.

I think you can spare a few microseconds per function. If you stored the function addresses in static variables, it would be only once per run of the script (instead of each time a Monitor object is created).

It's also completely ineffective to do the GetProcAddress "optimization" for functions in DLLs which AutoHotkey imports (i.e. because they are always resolved at startup). At minimum, that includes User32.dll, Kernel32.dll, ComCtl32.dll, and Gdi32.dll. That is, unless the function name is an expression/variable.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 02:13

Thanks for info.
This above was just an example. It can be done with every other dll. (I want just show another way how to do this)
Found it here: blogs.msdn.com (Using exported DLL functions)

And about ordinal vs name. I read that using ordinal is also a few (microseconds) bit faster than using the name.
If I found the link, I post it.

nothing more and nothing less
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 04:00

Sorry for going off-topic; GetProcAddress by name doesn't even take "a few microseconds" on my system, so a few microseconds faster would be very impressive. :crazy:
Spoiler
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 04:45

As long I can learn more I got no problems with off-topics in my topics.
But if you want to split them into "Ask For Help" you can. (Maybe with Topicname "GetProcAddress & LoadLibrary" or something). Your choice =)

About LoadLibrary:
The most functions out there in ahk forums look like this:

Code: Select all

; GLOBAL SETTINGS ===============================================================================================================

#Warn
#NoEnv
#Persistent
#SingleInstance Force

global ClientName := ClientAddr := ""

; SCRIPT ========================================================================================================================

SetTimer, WTSCall, 1000
return

WTSCall:
    WTSQuery(ClientName, ClientAddr)
    MsgBox % "ClientName:`t" ClientName "`nClientAddr:`t" ClientAddr
return

; FUNCTIONS =====================================================================================================================

WTSQuery(ByRef WTSClientName, ByRef WTSClientAddress)
{
    static hModule := DllCall("LoadLibrary", "Str", "wtsapi32.dll", "Ptr")     ; sometimes with - sometimes without static
    ;static WTS_CURRENT_SERVER_HANDLE := 0
    ;static WTS_CURRENT_SESSION       := -1
    ;static WTSClientName             := 10
    ;static WTSClientAddress          := 14
    static AF_INET := 2

    buf := size := ""

    if !(DllCall("wtsapi32.dll\WTSQuerySessionInformation", "Ptr", 0, "UInt", -1, "Int", 10, "Ptr*", buf, "UInt*", size))
        return "*" DllCall("GetLastError"), WTSClientName := ""
    WTSClientName := StrGet(buf + 0)
    DllCall("wtsapi32.dll\WTSFreeMemory", "Ptr", buf)

    if !(DllCall("wtsapi32.dll\WTSQuerySessionInformation", "Ptr", 0, "UInt", -1, "Int", 14, "Ptr*", buf, "UInt*", size))
        return "*" DllCall("GetLastError"), WTSClientAddress := ""
    if (NumGet(buf + 0, 0, "UInt") = AF_INET)
    {
        WTSClientAddress :=
        (Join`s"."`s
        NumGet(buf + 6, 0, "UChar")
        NumGet(buf + 7, 0, "UChar")
        NumGet(buf + 8, 0, "UChar")
        NumGet(buf + 9, 0, "UChar")
        )
    }
    DllCall("wtsapi32.dll\WTSFreeMemory", "Ptr", buf)
    DllCall("FreeLibrary", "Ptr", hModule)                                     ; Free handle @the end of each function
    return true
}
But isn't it better to make it global and delete it with OnExit?

Code: Select all

; GLOBAL SETTINGS ===============================================================================================================

#Warn
#NoEnv
#Persistent
#SingleInstance Force

global hModule := DllCall("LoadLibrary", "Str", "wtsapi32.dll", "Ptr")         ; make it global
global ClientName := ClientAddr := ""

OnExit("ExitFunc")                                                             ; free it with OnExit

; SCRIPT ========================================================================================================================

SetTimer, WTSCall, 1000
return

WTSCall:
    WTSQuery(ClientName, ClientAddr)
    MsgBox % "ClientName:`t" ClientName "`nClientAddr:`t" ClientAddr
return

; FUNCTIONS =====================================================================================================================

WTSQuery(ByRef WTSClientName, ByRef WTSClientAddress)
{
    ;static WTS_CURRENT_SERVER_HANDLE := 0
    ;static WTS_CURRENT_SESSION       := -1
    ;static WTSClientName             := 10
    ;static WTSClientAddress          := 14
    static AF_INET := 2

    buf := size := ""

    if !(DllCall("wtsapi32.dll\WTSQuerySessionInformation", "Ptr", 0, "UInt", -1, "Int", 10, "Ptr*", buf, "UInt*", size))
        return "*" DllCall("GetLastError"), WTSClientName := ""
    WTSClientName := StrGet(buf + 0)
    DllCall("wtsapi32.dll\WTSFreeMemory", "Ptr", buf)

    if !(DllCall("wtsapi32.dll\WTSQuerySessionInformation", "Ptr", 0, "UInt", -1, "Int", 14, "Ptr*", buf, "UInt*", size))
        return "*" DllCall("GetLastError"), WTSClientAddress := ""
    if (NumGet(buf + 0, 0, "UInt") = AF_INET)
    {
        WTSClientAddress :=
        (Join`s"."`s
        NumGet(buf + 6, 0, "UChar")
        NumGet(buf + 7, 0, "UChar")
        NumGet(buf + 8, 0, "UChar")
        NumGet(buf + 9, 0, "UChar")
        )
    }
    DllCall("wtsapi32.dll\WTSFreeMemory", "Ptr", buf)
    return true
}

ExitFunc()
{
    DllCall("FreeLibrary", "Ptr", hModule)
}
Or which way of Load- and FreeLibrary should we use?
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 07:19

Hi jNizM,

the first example doesn't make sense. Since hModule is declared as static, the DLL will be loaded only once, but FreeLibrary will (try to) unload the DLL on every function call. After the first function call the DLL isn't loaded any more, so each DllCall() statement within the function will load and unload the DLL.

In your second example, if the only purpose of ExitFunc() is to unload the DLL, it isn't actually needed, because the system will do it automatically when the thread terminates.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 07:33

Ok. Example:
Script is Persistent and calls the func every 1 Minute via SetTimer

Is it better to call the LoadLibrary global

Code: Select all

global hModule := DllCall("LoadLibrary", "Str", "wtsapi32.dll", "Ptr")

WTSQuery(ByRef WTSClientName, ByRef WTSClientAddress)
{
    ; some code
}
Or should I call LoadLibrary everytime the func get calls and free it for the rest of the time

Code: Select all

WTSQuery(ByRef WTSClientName, ByRef WTSClientAddress)
{
    hModule := DllCall("LoadLibrary", "Str", "wtsapi32.dll", "Ptr")

    ; some code

    DllCall("FreeLibrary", "Ptr", hModule)
}

I think the problem is here that there are to many different (and wrong) ways someone use DllCall's and post them into this forum.
And user see this way and think that's the right way, but it isnt.

Meine Englisch-Skills sind wieder richtig hervorragend :think:
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 09:21

I believe that most of the load/unload stuff arised at times when resources and in particular memory where lean. AHK is still loading and unloading the gdiplus.dll whenever it is used though real loading costs a notable amount of time. Some DLLs initialize memory when loaded and store values in it between function calls internally. These DLLs must not be freed before all associated function calls are done.

IMO, a DLL should be loaded only once (subsequent calls of LoadLibrary will only increase the reference counter) and, if you like, free it only once when you are sure that it won't be used any more.

I think this whole discussion should be stripped from the thread and moved to "Ask For Help".
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

28 May 2015, 09:28

Maybe an admin can split it from here http://ahkscript.org/boards/viewtopic.p ... 465#p46465 in "Ask for help" with topic name "GetProcAddress & LoadLibrary" or something
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Skrell
Posts: 302
Joined: 23 Jan 2014, 12:05

Re: Class Monitor (Brightness, Contrast & Gamma)

01 Jun 2015, 08:08

Should this class work on XP too? I just tried your GUI and nothing happens. This is what i see:
screenshot.png
screenshot.png (207 KiB) Viewed 28218 times
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

01 Jun 2015, 08:16

@Skrell
Sorry no.
MSDN SetMonitorBrightness function
Minimum supported client:
Windows Vista [desktop apps only]
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class Monitor (Brightness, Contrast & Gamma)

02 Jun 2015, 03:42

Hi jNizM,

trying your sample script to find an answer for your related question in "Ask For Help" I ran into an issue with GetDeviceGammaRamp(). If I use the class as is, the returned value is *0, and if I change the DllCall to use the original function name, the returned value is -128.

The array filled by the function contains (order: index - R value - G value - B value):

Code: Select all

0 - 0 - 0 - 0
1 - 0 - 0 - 0
2 - 0 - 0 - 0
3 - 0 - 0 - 0
4 - 256 - 256 - 256
5 - 256 - 256 - 256
6 - 256 - 256 - 256
7 - 256 - 256 - 256
8 - 512 - 512 - 512
9 - 512 - 512 - 512
10 - 512 - 512 - 512
11 - 768 - 768 - 768
12 - 768 - 768 - 768
13 - 768 - 768 - 768
14 - 1024 - 1024 - 1024
15 - 1024 - 1024 - 1024
16 - 1024 - 1024 - 1024
17 - 1280 - 1280 - 1280
18 - 1280 - 1280 - 1280
19 - 1536 - 1536 - 1536
20 - 1536 - 1536 - 1536
21 - 1792 - 1792 - 1792
22 - 1792 - 1792 - 1792
23 - 2048 - 2048 - 2048
24 - 2048 - 2048 - 2048
25 - 2304 - 2304 - 2304
26 - 2304 - 2304 - 2304
27 - 2560 - 2560 - 2560
28 - 2560 - 2560 - 2560
29 - 2816 - 2816 - 2816
30 - 2816 - 2816 - 2816
31 - 3072 - 3072 - 3072
32 - 3072 - 3072 - 3072
33 - 3328 - 3328 - 3328
34 - 3328 - 3328 - 3328
35 - 3584 - 3584 - 3584
36 - 3840 - 3840 - 3840
37 - 3840 - 3840 - 3840
38 - 4096 - 4096 - 4096
39 - 4096 - 4096 - 4096
40 - 4352 - 4352 - 4352
41 - 4608 - 4608 - 4608
42 - 4608 - 4608 - 4608
43 - 4864 - 4864 - 4864
44 - 5120 - 5120 - 5120
45 - 5120 - 5120 - 5120
46 - 5376 - 5376 - 5376
47 - 5632 - 5632 - 5632
48 - 5632 - 5632 - 5632
49 - 5888 - 5888 - 5888
50 - 6144 - 6144 - 6144
51 - 6144 - 6144 - 6144
52 - 6400 - 6400 - 6400
53 - 6656 - 6656 - 6656
54 - 6656 - 6656 - 6656
55 - 6912 - 6912 - 6912
56 - 7168 - 7168 - 7168
57 - 7424 - 7424 - 7424
58 - 7424 - 7424 - 7424
59 - 7680 - 7680 - 7680
60 - 7936 - 7936 - 7936
61 - 8192 - 8192 - 8192
62 - 8192 - 8192 - 8192
63 - 8448 - 8448 - 8448
64 - 8704 - 8704 - 8704
65 - 8960 - 8960 - 8960
66 - 8960 - 8960 - 8960
67 - 9216 - 9216 - 9216
68 - 9472 - 9472 - 9472
69 - 9728 - 9728 - 9728
70 - 9984 - 9984 - 9984
71 - 9984 - 9984 - 9984
72 - 10240 - 10240 - 10240
73 - 10496 - 10496 - 10496
74 - 10752 - 10752 - 10752
75 - 11008 - 11008 - 11008
76 - 11264 - 11264 - 11264
77 - 11264 - 11264 - 11264
78 - 11520 - 11520 - 11520
79 - 11776 - 11776 - 11776
80 - 12032 - 12032 - 12032
81 - 12288 - 12288 - 12288
82 - 12544 - 12544 - 12544
83 - 12800 - 12800 - 12800
84 - 12800 - 12800 - 12800
85 - 13056 - 13056 - 13056
86 - 13312 - 13312 - 13312
87 - 13568 - 13568 - 13568
88 - 13824 - 13824 - 13824
89 - 14080 - 14080 - 14080
90 - 14336 - 14336 - 14336
91 - 14592 - 14592 - 14592
92 - 14848 - 14848 - 14848
93 - 15104 - 15104 - 15104
94 - 15104 - 15104 - 15104
95 - 15360 - 15360 - 15360
96 - 15616 - 15616 - 15616
97 - 15872 - 15872 - 15872
98 - 16128 - 16128 - 16128
99 - 16384 - 16384 - 16384
100 - 16640 - 16640 - 16640
101 - 16896 - 16896 - 16896
102 - 17152 - 17152 - 17152
103 - 17408 - 17408 - 17408
104 - 17664 - 17664 - 17664
105 - 17920 - 17920 - 17920
106 - 18176 - 18176 - 18176
107 - 18432 - 18432 - 18432
108 - 18688 - 18688 - 18688
109 - 18944 - 18944 - 18944
110 - 19200 - 19200 - 19200
111 - 19456 - 19456 - 19456
112 - 19712 - 19712 - 19712
113 - 19968 - 19968 - 19968
114 - 20224 - 20224 - 20224
115 - 20480 - 20480 - 20480
116 - 20736 - 20736 - 20736
117 - 20992 - 20992 - 20992
118 - 21248 - 21248 - 21248
119 - 21504 - 21504 - 21504
120 - 21760 - 21760 - 21760
121 - 22016 - 22016 - 22016
122 - 22272 - 22272 - 22272
123 - 22528 - 22528 - 22528
124 - 22784 - 22784 - 22784
125 - 23040 - 23040 - 23040
126 - 23296 - 23296 - 23296
127 - 23552 - 23552 - 23552
128 - 23808 - 23808 - 23808
129 - 24064 - 24064 - 24064
130 - 24320 - 24320 - 24320
131 - 24576 - 24576 - 24576
132 - 25088 - 25088 - 25088
133 - 25344 - 25344 - 25344
134 - 25600 - 25600 - 25600
135 - 25856 - 25856 - 25856
136 - 26112 - 26112 - 26112
137 - 26368 - 26368 - 26368
138 - 26624 - 26624 - 26624
139 - 26880 - 26880 - 26880
140 - 27136 - 27136 - 27136
141 - 27392 - 27392 - 27392
142 - 27904 - 27904 - 27904
143 - 28160 - 28160 - 28160
144 - 28416 - 28416 - 28416
145 - 28672 - 28672 - 28672
146 - 28928 - 28928 - 28928
147 - 29184 - 29184 - 29184
148 - 29440 - 29440 - 29440
149 - 29696 - 29696 - 29696
150 - 30208 - 30208 - 30208
151 - 30464 - 30464 - 30464
152 - 30720 - 30720 - 30720
153 - 30976 - 30976 - 30976
154 - 31232 - 31232 - 31232
155 - 31488 - 31488 - 31488
156 - 31744 - 31744 - 31744
157 - 32256 - 32256 - 32256
158 - 32512 - 32512 - 32512
159 - 32768 - 32768 - 32768
160 - 33024 - 33024 - 33024
161 - 33280 - 33280 - 33280
162 - 33792 - 33792 - 33792
163 - 34048 - 34048 - 34048
164 - 34304 - 34304 - 34304
165 - 34560 - 34560 - 34560
166 - 34816 - 34816 - 34816
167 - 35328 - 35328 - 35328
168 - 35584 - 35584 - 35584
169 - 35840 - 35840 - 35840
170 - 36096 - 36096 - 36096
171 - 36352 - 36352 - 36352
172 - 36864 - 36864 - 36864
173 - 37120 - 37120 - 37120
174 - 37376 - 37376 - 37376
175 - 37632 - 37632 - 37632
176 - 37888 - 37888 - 37888
177 - 38400 - 38400 - 38400
178 - 38656 - 38656 - 38656
179 - 38912 - 38912 - 38912
180 - 39168 - 39168 - 39168
181 - 39680 - 39680 - 39680
182 - 39936 - 39936 - 39936
183 - 40192 - 40192 - 40192
184 - 40448 - 40448 - 40448
185 - 40960 - 40960 - 40960
186 - 41216 - 41216 - 41216
187 - 41472 - 41472 - 41472
188 - 41728 - 41728 - 41728
189 - 42240 - 42240 - 42240
190 - 42496 - 42496 - 42496
191 - 42752 - 42752 - 42752
192 - 43264 - 43264 - 43264
193 - 43520 - 43520 - 43520
194 - 43776 - 43776 - 43776
195 - 44032 - 44032 - 44032
196 - 44544 - 44544 - 44544
197 - 44800 - 44800 - 44800
198 - 45056 - 45056 - 45056
199 - 45568 - 45568 - 45568
200 - 45824 - 45824 - 45824
201 - 46080 - 46080 - 46080
202 - 46592 - 46592 - 46592
203 - 46848 - 46848 - 46848
204 - 47104 - 47104 - 47104
205 - 47360 - 47360 - 47360
206 - 47872 - 47872 - 47872
207 - 48128 - 48128 - 48128
208 - 48384 - 48384 - 48384
209 - 48896 - 48896 - 48896
210 - 49152 - 49152 - 49152
211 - 49408 - 49408 - 49408
212 - 49920 - 49920 - 49920
213 - 50176 - 50176 - 50176
214 - 50432 - 50432 - 50432
215 - 50944 - 50944 - 50944
216 - 51200 - 51200 - 51200
217 - 51712 - 51712 - 51712
218 - 51968 - 51968 - 51968
219 - 52224 - 52224 - 52224
220 - 52736 - 52736 - 52736
221 - 52992 - 52992 - 52992
222 - 53248 - 53248 - 53248
223 - 53760 - 53760 - 53760
224 - 54016 - 54016 - 54016
225 - 54272 - 54272 - 54272
226 - 54784 - 54784 - 54784
227 - 55040 - 55040 - 55040
228 - 55552 - 55552 - 55552
229 - 55808 - 55808 - 55808
230 - 56064 - 56064 - 56064
231 - 56576 - 56576 - 56576
232 - 56832 - 56832 - 56832
233 - 57344 - 57344 - 57344
234 - 57600 - 57600 - 57600
235 - 57856 - 57856 - 57856
236 - 58368 - 58368 - 58368
237 - 58624 - 58624 - 58624
238 - 59136 - 59136 - 59136
239 - 59392 - 59392 - 59392
240 - 59648 - 59648 - 59648
241 - 60160 - 60160 - 60160
242 - 60416 - 60416 - 60416
243 - 60928 - 60928 - 60928
244 - 61184 - 61184 - 61184
245 - 61696 - 61696 - 61696
246 - 61952 - 61952 - 61952
247 - 62208 - 62208 - 62208
248 - 62720 - 62720 - 62720
249 - 62976 - 62976 - 62976
250 - 63488 - 63488 - 63488
251 - 63744 - 63744 - 63744
252 - 64256 - 64256 - 64256
253 - 64512 - 64512 - 64512
254 - 65024 - 65024 - 65024
255 - 65280 - 65280 - 65280
Also, after changing the gamma settings using the graphics driver the values keep unchanged.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

02 Jun 2015, 08:34

Update:
- Changed to original GetDeviceGammaRamp & SetDeviceGammaRamp function names
- Changed GetLastError to A_LastError
- Shorter msdn-links
- Update Example Script: Check if OS is >= Vista
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Bleep

Re: Class Monitor (Brightness, Contrast & Gamma)

02 Sep 2015, 06:48

@ jNizM - would you happen to know what AHK script would be required to adjust just the monitor brightness incrementally up/down via a hotkey, without a GUI?

Your script incorporates a number of monitor controls so I was hoping you may be able to shed some light on this.

All the best :)
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Class Monitor (Brightness, Contrast & Gamma)

02 Sep 2015, 07:56

I hope this is what you want

Code: Select all

; GLOBAL SETTINGS ===============================================================================================================

#Warn
#NoEnv
#SingleInstance Force

#Include Class_Monitor.ahk                                                   ; include the class here

global cnt := DllCall("user32.dll\GetSystemMetrics", "Int", 80)              ; get the number of display monitors on a desktop
global tmp := []                                                             ; initialize an Array

OnExit, EOF                                                                  ; set onexit to the label "EOF"
Display := New Monitor()                                                     ; initialize / start the class

; SCRIPT ========================================================================================================================

loop % cnt                                                                   ; loop throw all monitors
    tmp[A_Index] := Display.GetMonitorBrightness(1).CurrentBrightness        ; get the current brightness for all monitors


#Numpad4::                                                                   ; hotkey: win + numpad4 / win + numpad left
#NumpadLeft::
    loop % tmp.MaxIndex()                                                    ; loop throw all monitors
        Display.SetMonitorBrightness(A_Index, --tmp[A_Index])                ; decrease the brightness by 1 for all monitors
return

#Numpad6::                                                                   ; hotkey: win + numpad6 / win + numpad right
#NumpadRight::
    loop % tmp.MaxIndex()                                                    ; loop throw all monitors
        Display.SetMonitorBrightness(A_Index, ++tmp[A_Index])                ; increase the brightness by 1 for all monitors
return

#Numpad5::                                                                   ; hotkey: win + numpad5
    loop % tmp.MaxIndex()                                                    ; loop throw all monitors
        Display.SetMonitorBrightness(A_Index, tmp[A_Index] := 50)            ; set the brightness back to 50 for all monitors
return

; EXIT ==========================================================================================================================

EOF:                                                                         ; on exit
Display.OnExit()                                                             ; release and free the library
ExitApp                                                                      ; exit the app
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Bleep

Re: Class Monitor (Brightness, Contrast & Gamma)

02 Sep 2015, 09:45

jNizM wrote:I hope this is what you want
Looks very much what I was looking for, thanks for the reply.

Unfortunately it doesn't seem to have any effect on my monitor's backlight brightness however :( Also tried the GUI version which had no effect. Perhaps it only works for laptop monitors?

The only program I've tested so far that is effective at changing the brightness is a Rainmeter widget called Backlight but was hoping I could find a way to hotkey the same functionality in Autohotkey.

I asked on IRC about it and someone suggested the SetColorAdjustment call but I'm not sure how that's related. Any ideas?

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 128 guests