I'm still not happy with it not working on all PC's for my own library example, so I'm looking at this API: DeviceIoControl
With the constant: IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS http://msdn.microsoft.com/en-us/libr...04(VS.85).aspx
If you don't mind I'll post it here, if I can make it work.
That way future searchers will find both answers in one spot. Or not. lol
Well this is frustrating to say the least.
Vista/7 has a function SetMonitorBrightness, but I can't find any declarations or anything, so I gave up on that.
DeviceIoControl and CreateFile do so many things, it's hard to wrap a succinct snippet of code around it.
Here is what I have so far, but I can't get a device handle out of CreateFile.
It's almost as if everyone purposely leaves out how to get the correct device/driver name, or path. Like we are supposed to be mind readers.
Code:
'Code found http://www.dreamincode.net/forums/blog/126/entry-596-set-the-brightness-of-a-laptop-through-vbnet/
'Input Output control codes
Const IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS As Int32 = 2294940
Const IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS As Int32 = 2294936
Const IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS As Int32 = 2294932
'desired access param of create file
Const GENERIC_NONE As Int32 = 0 'This may gain access when GENERIC_READ fails because of access restriction
Const GENERIC_READ As Int32 = -2147483648
Const GENERIC_WRITE As Int32 = 1073741824
Const GENERIC_ALL As Int32 = GENERIC_READ Or GENERIC_WRITE
'share mode param of create file
Const FILE_SHARE_ALL As Int32 = 7
Const FILE_SHARE_READ As Int32 = 1
Const FILE_SHARE_WRITE As Int32 = 2
Const FILE_EXCLUSIVE_ACCESS As Int32 = 0 'Blocks others
'misc
Const OPEN_EXISTING As Int32 = 3 'creation method
Const INVALID_HANDLE_VALUE As Int32 = -1 'return of create file
Const FILE_ATTRIBUTE_NORMAL As Int32 = 128 'Possible file attribute for device?
Private Structure BRIGHTNESS
Public ucDisplayPolicy As Byte
Public ucACBrightness As Byte
Public ucDCBrightness As Byte
End Structure
'Private Declare Function apiCreateFileLong Lib "kernel32" Alias "CreateFileW" (ByVal lpFileName As String, ByVal dwDesiredAccess As Int32, ByVal dwShareMode As Int32, ByVal lpSecurityAttributes As Int32, ByVal dwCreationDisposition As Int32, ByVal dwFlagsAndAttributes As Int32, ByVal hTemplateFile As Int32) As Int32 'You can use paths longer than MAX_PATH characters by calling the wide (W) version(or Auto) of CreateFile and prepending “\\?\” to the path. The “\\?\” tells the function to turn off path parsing. This lets you use paths that are nearly 32,000 Unicode characters long. You must use fully-qualified paths with this technique. This also works with UNC names. The “\\?\” is ignored as part of the path. For example, “\\?\C:\myworld\private” is seen as “C:\myworld\private”, and “\\?\UNC\tom_1\hotstuff\coolapps” is seen as “\\tom_1\hotstuff\coolapps”.
Private Declare Function apiCreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Int32, ByVal dwShareMode As Int32, ByVal lpSecurityAttributes As Int32, ByVal dwCreationDisposition As Int32, ByVal dwFlagsAndAttributes As Int32, ByVal hTemplateFile As Int32) As Int32
Private Declare Function apiDeviceIoControl Lib "kernel32" Alias "DeviceIoControl" (ByVal hDevice As Int32, ByVal dwIoControlCode As Int32, ByRef lpInBuffer As BRIGHTNESS, ByVal nInBufferSize As Int32, ByVal lpOutBuffer As Int32, ByVal nOutBufferSize As Int32, ByRef lpBytesReturned As Int32, ByVal lpOverlapped As Int32) As Boolean
Private Declare Function apiCloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As Int32) As Boolean
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ret As Int32
ret = SetBrightness(75) ' Call the function.
If ret = 0 Then
MessageBox.Show("device operation failed or is busy pending...")
ElseIf ret = INVALID_HANDLE_VALUE Then
MessageBox.Show("invalid handle")
ElseIf ret = -2 Then
MessageBox.Show("device path does not exist")
Else
MessageBox.Show("success!")
'TODO-Get brightness
End If
End Sub
Private Function SetBrightness(ByRef bLvl As Int32) As Int32
Dim hDev, results, cbSize As Int32, b As New BRIGHTNESS
b.ucDCBrightness = bLvl ' The brightness on DC Power
b.ucACBrightness = bLvl ' The Brightness on AC Power
hDev = apiCreateFile("\\.\LCD", GENERIC_READ, FILE_SHARE_ALL, 0, OPEN_EXISTING, 0, 0) ' Get the display
If hDev = INVALID_HANDLE_VALUE Then Return -1
If hDev = 0 Then Return -2 'Since this is an invalid device handle too
cbSize = System.Runtime.InteropServices.Marshal.SizeOf(b)
SetBrightness = apiDeviceIoControl(hDev, IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS, b, cbSize, 0, 0, results, 0) ' Set the brightness.
apiCloseHandle(hDev) ' Close the handle.
End Function
Yep, documentation sucks!! I sympathise! I've been having the same problem!
Guess what, I got it working, OK, not me, a genius called Lingzhi Sun, over at MSDN forums! The whole problem was with the GetDeviceGammaRamp API, so freaking small!!
I had it declared as :
Code:
<DllImport("gdi32.dll")> _
Private Shared Function GetDeviceGammaRamp(ByVal hdc As Int32, ByVal lpv As Int32) As Int32
End Function
It should have been declared as a Boolean, like this :
Code:
<DllImport("gdi32.dll")> _
Private Shared Function GetDeviceGammaRamp(ByVal hdc As Int32, ByRef lpv As RAMP) As Boolean
End Function
So, my initial thoughts were correct, the GetDeviceGammaRamp never got the correct values!
He got the corect declaration for GetDeviceGammaRamp here :
You guys are AMAZING. It's why this forum is my goto for help. I feel bad that I'm not able to contribute much, but I do try.
Thanks again!
You're also amazing with all your effort you put in, if I had an employee such as you working for me, you'd have received a raise because of this porject
Helping others comes with time, heck, it took me 4 years to actually start trying to help other members here, I guess I was a bit too scared, or insecure. You'll be amazed what you can learn by helping others, and reading other people's questions. I have learnt a great deal with this thread, so I am happy and grateful to everyone that has contributed
Originally Posted by stin
Well, I tried opening your solution, but it open as a blank solution in VS 2008. I've been able to get them open before. Any thoughts?
Strange....
I am attaching a new zip here again. And I'm adding the full code now with this post as well ( to cover both bases )
Code:
Imports System.Runtime.InteropServices
Public Class Form1
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Private Structure RAMP
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
Public Red As UInt16()
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
Public Green As UInt16()
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
Public Blue As UInt16()
End Structure
<DllImport("gdi32.dll")> _
Private Shared Function SetDeviceGammaRamp(ByVal hDC As IntPtr, ByRef lpRamp As RAMP) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function GetDC(ByVal hWnd As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll")> _
Private Shared Function GetDeviceGammaRamp(ByVal hdc As Int32, ByRef lpv As RAMP) As Boolean
End Function
Private WithEvents TrackBar1 As System.Windows.Forms.TrackBar
'Private Shared Ramp1(0 To 255, 0 To 2) As RAMP
Private Shared s_ramp As New RAMP()
Private Shared MyRamp As New RAMP()
Private Shared Sub SetGamma(ByVal gamma As Integer)
s_ramp.Red = New UShort(255) {}
s_ramp.Green = New UShort(255) {}
s_ramp.Blue = New UShort(255) {}
For i As Integer = 1 To 255
' gamma is a value between 3 and 44
s_ramp.Red(i) = InlineAssignHelper(s_ramp.Green(i), InlineAssignHelper(s_ramp.Blue(i), CUShort((Math.Min(65535, Math.Max(0, Math.Pow((i + 1) / 256.0R, gamma * 0.1) * 65535 + 0.5))))))
Next
' Now set the value.
SetDeviceGammaRamp(GetDC(IntPtr.Zero), s_ramp)
End Sub
Private Shared Sub RestoreGamma(ByVal gamma As RAMP)
'MyRamp.Red = New UShort(255) {}
'MyRamp.Green = New UShort(255) {}
'MyRamp.Blue = New UShort(255) {}
'For x = 0 To 255
' 'MyRamp.Red(x) = Ramp1(x, 0)
' 'MyRamp.Green(x) = Ramp1(x, 1)
' 'MyRamp.Blue(x) = Ramp1(x, 2)
'Next
SetDeviceGammaRamp(GetDC(IntPtr.Zero), gamma)
End Sub
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function
Private Sub TrackBar1_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
SetGamma(TrackBar1.Value)
End Sub
Private Sub SetBrightness_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
RestoreGamma(MyRamp)
End Sub
Private Sub SetBrightness_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
GetDeviceGammaRamp(GetDC(IntPtr.Zero), MyRamp)
End Sub
End Class
Have a great night and weekend, and I'm looking forward to your next "complicated question"
PS: I'll pop in later tonight again to see if you have managed to open the zip
I don't think the Boolean type matters.
I did mention that my declaration works, which was ByRef.
ByVal would be if you were using a memory API, or were omitting the optional functionality of the parameter.(this can make other parameters work sometimes)
In your example you pass the structure, which I should have caught and mentioned though.
Last edited by TT(n); June 26th, 2010 at 12:14 AM.
One quick issue with the slider example.
Awesome work BTW!, I would have not figured out the InlineAssignHelper part. No, you're a genius, ... no you are, ... no YOU are.
BUG:
Trackbar can change before the load event is finished, thus locking in the wrong original ramp, which is nicely returned ofcourse, but to the wrong gamma.
Solution, put in a boolen.
Code:
Private IsLoaded As Boolean = False
In the load event switch it on.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
GetDeviceGammaRamp(GetDC(IntPtr.Zero), usrRamp)
IsLoaded = True
End Sub
In the trackbar scroll or valuechanged event put this:
Code:
Private Sub TrackBar2_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TrackBar2.ValueChanged
If IsLoaded = False Then Exit Sub
SetGamma(TrackBar2.Value)
End Sub
EDIT: Oh yeah, I noticed that it doesn't matter what device context you pass. Any works so far, although I prefer to use GetWindowDC(GetDeskTopWindow) which is at least supposed to be the whole desktop window.
Last edited by TT(n); June 25th, 2010 at 08:44 PM.
Reason: extra
{BATTERY LOW SOLUTION XP/Vista/7} {VB6}
Full slider dimmer solution shown later in this thread.
I brought in the structure in to my example, so that it would work on Vista/7. Great it works!
I did however notice a difference in the look between the two dimmings.
Here is an updated example, that toggle dims, without a slider.
It looks more like a laptop on battery power(the whites are dimmer!), but without the ability to adjust. {To come later}
Code:
Private usrRamp As New RAMP
Private Structure RAMP
<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=256)> _
Public Red As UShort()
<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=256)> _
Public Green As UShort()
<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=256)> _
Public Blue As UShort()
End Structure
Private Declare Function apiGetDeviceGammaRamp Lib "gdi32" Alias "GetDeviceGammaRamp" (ByVal hdc As Int32, ByRef lpv As RAMP) As Int32
Private Declare Function apiSetDeviceGammaRamp Lib "gdi32" Alias "SetDeviceGammaRamp" (ByVal hdc As Int32, ByRef lpv As RAMP) As Int32
Private Declare Function apiGetWindowDC Lib "user32" Alias "GetWindowDC" (ByVal hwnd As Int32) As Int32
Private Declare Function apiGetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Int32
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
apiGetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), usrRamp)
End Sub
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
apiSetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), usrRamp)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
HalfBright()
End Sub
Private Function HalfBright() As Int32
Dim rmp As New RAMP
apiGetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), rmp)
For iCtr As UShort = 0 To 255
rmp.Red(iCtr) = CUShort(rmp.Red(iCtr) / 2)
rmp.Green(iCtr) = CUShort(rmp.Green(iCtr) / 2)
rmp.Blue(iCtr) = CUShort(rmp.Blue(iCtr) / 2)
Next
Return apiSetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), rmp)
End Function
Last edited by TT(n); June 26th, 2010 at 07:24 PM.
I don't think the Boolean type matters.
I did mention that my declaration works, which was ByRef.
ByVal would be if you were using a memory API, or were omitting the optional functionality of the parameter.(this can make other parameters work sometimes)
Yeah, that till bothers me - it will probably keep on bothering me until I'm 60! Perhaps the whole problem was how I stored the retur value of GetDeviceGammaRamp. There is a change in one of the parameters' type as well, so that is more likely to have been the issue. I'm to scared to change it to any other datattype though! LOL! Maybe I should quickly have a look and see what effect it will have
Originally Posted by TT(n)
BUG:
Trackbar can change before the load event is finished, thus locking in the wrong original ramp, which is nicely returned ofcourse, but to the wrong gamma.
Solution, put in a boolen.
Never realised that, guess I had tunnel vision
Originally Posted by TT(n)
Okay, just when you thought this thread was safe. lol
So I brought in the structure in to my example, so that it would work on Vista/7. Great it works! both examples do.
I did however notice a difference in the look between the two dimmings.
Here is an updated example, that toggle dims, without a slider.
It looks more like a laptop on battery power(the whites are dimmer!), but without the ability to adjust.
Code:
Private usrRamp As New RAMP
Private Structure RAMP
<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=256)> _
Public Red As UShort()
<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=256)> _
Public Green As UShort()
<System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=256)> _
Public Blue As UShort()
End Structure
Private Declare Function apiGetDeviceGammaRamp Lib "gdi32" Alias "GetDeviceGammaRamp" (ByVal hdc As Int32, ByRef lpv As RAMP) As Int32
Private Declare Function apiSetDeviceGammaRamp Lib "gdi32" Alias "SetDeviceGammaRamp" (ByVal hdc As Int32, ByRef lpv As RAMP) As Int32
Private Declare Function apiGetWindowDC Lib "user32" Alias "GetWindowDC" (ByVal hwnd As Int32) As Int32
Private Declare Function apiGetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Int32
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
apiGetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), usrRamp)
End Sub
Private Sub Form1_FormClosed(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
apiSetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), usrRamp)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
HalfBright()
End Sub
Private Function HalfBright() As Int32
Dim rmp As New RAMP
apiGetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), rmp)
For iCtr As UShort = 0 To 255
rmp.Red(iCtr) = CUShort(rmp.Red(iCtr) / 2)
rmp.Green(iCtr) = CUShort(rmp.Green(iCtr) / 2)
rmp.Blue(iCtr) = CUShort(rmp.Blue(iCtr) / 2)
Next
Return apiSetDeviceGammaRamp(apiGetWindowDC(apiGetDesktopWindow), rmp)
End Function
Aha! I think the real problem(s) were :
1) As TT(n) pointed out, the second parameter of GetDeviceGammaRamp was supposed to be ByRef and not ByVal
2) The data type of the second parameter shouldn't have been Int32 but RAMP instead. - How could I miss that????
If I do this :
Code:
<DllImport("gdi32.dll")> _
Private Shared Function GetDeviceGammaRamp(ByVal hdc As Int32, ByRef lpv As RAMP) As Int32
End Function
I modified my original code.
It also works. TT(n) do you think my observations are correct? Do you agree?
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.