18

How do I turn off a monitor using VB.NET code? OK, actually I found the C# solution. But I need the VB.NET solution. I have tried an online C# to VB.NET converter, but the converter is complaining that there are errors in it.

How can the following C# code be translated to VB.NET?

using System.Runtime.InteropServices; //to DllImport

public int WM_SYSCOMMAND = 0x0112;
public int SC_MONITORPOWER = 0xF170; //Using the system pre-defined MSDN constants that can be used by the SendMessage() function .

[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);
//To call a DLL function from C#, you must provide this declaration.

private void button1_Click(object sender, System.EventArgs e)
{
    SendMessage( this.Handle.ToInt32() , WM_SYSCOMMAND , SC_MONITORPOWER ,2 );//DLL function
}

UPDATE:

I use the online developer Fusion converter.

Lennart
  • 9,657
  • 16
  • 68
  • 84
user774411
  • 1,749
  • 6
  • 28
  • 47
  • 2
    The converter probably complains because there is no class-construct in this code. Try wrapping everything from after the using-statement to after the last line in this: `class MonitorShutdown { ...code here }`. – Alxandr Jun 03 '11 at 00:17
  • 1
    Note that both the C# code and the translated code are moderately horrible. A `hWnd` should be an `IntPtr`, not an `int`. And having a magic constant (`2`) in the code also isn’t such a good idea. – Konrad Rudolph Jul 04 '11 at 15:59
  • @Konrad Rudolph: I don't know C# or Win32 API. If you can perfect the answer, then please do it. It will help me and any future visitors. – user774411 Jul 04 '11 at 20:25
  • try out http://codechanger.com/ - I removed the code comments and it converted perfectly;) – Jeremy Thompson Apr 15 '12 at 04:01
  • In reference to checking the current monitor state, this may be relevant http://stackoverflow.com/questions/203355/is-there-any-way-to-detect-the-monitor-state-in-windows-on-or-off – Jodrell Apr 19 '12 at 08:27

3 Answers3

17

Try this

Public WM_SYSCOMMAND As Integer = &H112
Public SC_MONITORPOWER As Integer = &Hf170

<DllImport("user32.dll")> _
Private Shared Function SendMessage(hWnd As Integer, hMsg As Integer, wParam As Integer, lParam As Integer) As Integer
End Function

Private Sub button1_Click(sender As Object, e As System.EventArgs)
    SendMessage(Me.Handle.ToInt32(), WM_SYSCOMMAND, SC_MONITORPOWER, 2)
End Sub
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • @konrad Rudolph: It works perfectly well, but I'm stuck at a point. Please resolve this query. http://stackoverflow.com/questions/8280799/vb-net-how-to-know-time-for-which-system-is-idle – Viral Jain Nov 27 '11 at 09:37
7

Yes, the declarations in the accepted answer are not correct. Random failure is possible on a 64-bit version of Windows since the passed arguments have the wrong size. They should look like this:

Private Const WM_SYSCOMMAND As Integer = &H112
Private Const SC_MONITORPOWER As Integer = &HF170
Private Const MonitorToLowPower As Integer = 1
Private Const MonitorShutoff As Integer = 2

<DllImport("user32.dll")> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal hMsg As Integer, _
                          ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    SendMessage(Me.Handle, WM_SYSCOMMAND, 
                CType(SC_MONITORPOWER, IntPtr), CType(MonitorShutoff, IntPtr))
End Sub

You could add a check on the return value of SendMessage(), it should return IntPtr.Zero. Not so sure it is useful, it will be pretty obvious to the user that the command didn't work for some reason.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I understand why you changed `Me.Handle.ToInt32()` to `Me.Handle`. But is it necessary to cast/convert `SC_MONITORPOWER` and `MonitorShutoff` to `IntPtr`? – Nicholas Apr 16 '12 at 14:56
  • Yes, the two last arguments of SendMessage are IntPtr, not Integer. The message constants are actually Integer. So a conversion is required. From 4 bytes to 4 bytes in 32-bit mode, from 4 bytes to 8 bytes in 64-bit mode. CType() takes care of that, there is no CIntPtr() function. SendMessage just isn't very pretty. – Hans Passant Apr 16 '12 at 16:01
  • Just an idea, would using the `IntPtr` constructor instead of the explicit conversion be slightly neater? i.e. `New IntPtr(SC_MONITORPOWER)`, I think its 3 less charachters (+1 either way) – Jodrell Apr 19 '12 at 08:33
  • Is there any way to wake the monitor up again? – Alexander Johansen Jun 03 '15 at 09:07
0

this one works on Windows 7 using VB 2008. and dont worry about turning the monitor back on again because this is just like "turn off the display" in the power options. the monitor turns off and to turn it back on you have to either press any key on the keyboard or move your mouse.

Imports System.Runtime.InteropServices

Public Class Monitoroff

Public WM_SYSCOMMAND As Integer = &H112

Public SC_MONITORPOWER As Integer = &HF170

<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function SendMessage(ByVal hWnd As Integer, ByVal hMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    SendMessage(Me.Handle.ToInt32(), WM_SYSCOMMAND, SC_MONITORPOWER, 2)
End Sub
End Class