Blanking Monitor and Unblanking Monitor

  • Thread starter Thread starter Stewart Berman
  • Start date Start date
S

Stewart Berman

Is there a way to control blanking and unblanking a monitor -- basically override the power settings
and force the graphics card to blank out or to turn on?

I tried using the following:

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Int32,
ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Integer

Private Const SC_MONITORPOWER As Integer = &HF170&
Private Const HWND_BROADCAST As Integer = &HFFFF
Private Const WM_SYSCOMMAND As Integer = &H112

Public Enum MonitorStatus As Int32
Monitor_On = -1
Monitor_Low = 1
Monitor_Off = 2
End Enum


Public Sub SetMonitor(ByVal Monitor_Status As MonitorStatus)
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, Monitor_Status)
End Sub

Using:
SetMonitor(Wallpaper.MonitorStatus.Monitor_Off)
Sometimes only results in the graphics card blanking the screen for a few seconds.

Running a test loop:
Dim nCounter as Integer
For nCounter = 1 to 20
SetMonitor(Wallpaper.MonitorStatus.Monitor_Off)
Thread.Sleep(10000)
SetMonitor(Wallpaper.MonitorStatus.Monitor_On)
Thread.Sleep(10000)
Next nCounter
Seems to work -- at least after the first loop.

But
SetMonitor(Wallpaper.MonitorStatus.Monitor_On)
Does not unblank the screen if the power saver has blanked it.

The test machine is running Windows XP SP3 but the code needs to work for Vista as well.
 
Hello Stewart,

I have tested the codes and they work fine for me in my side. I use the
following codes to test,

Dim nCounter As Integer
For nCounter = 1 To 20
SetMonitor(MonitorStatus.Monitor_On)
Thread.Sleep(70000)
Next nCounter

Please note we should let the thread sleep more than 60 seconds because the
Power Saver Option's minium time of turning off the display is 1 minute. If
the thread only sleeps for 10 seconds for each of the loop. The SetMonitor
function will send message broadcastly and the left time of display turning
off is refreshed. So we will never see the Power Saver turning off the
monitor.

Actually, I do the following things to test.
1. I set my Power Saver to turn off the monitor after 1 minutes if no
inputs are detected
2. I run the above codes.

After 1 minute, I see the Power Saver turnning off my Monitor, and then
after another 10(70-60) seconds, I can observe that my Monitor is turned on
by my application.

So when you say "SetMonitor(Wallpaper.MonitorStatus.Monitor_On) Does not
unblank the screen if the power saver has blanked it", would you mind
letting us know more specific steps and information, like how many minutes
you set in the system's Power Saver option and what is the exact codes you
are executing, as well as your test steps.

By the way, if I running your codes, it turns off the monitor for ten
seconds and then trun on the monitor for ten seconds as a cycle. Just works
like the codes indicate to be.


Best regards,
Ji Zhou
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).
 
I have a little application I use to explore managed code. It has a background task that changes
the wallpaper and then runs a little loop with a Thread.Sleep(6000) in it ten times. I added the
monitor on call right after the wallpaper is changed.

The intention is to not have the monitor blank out if the application is running.

My power settings are:
Power scheme: Home/Office Desk
Turn off monitor: After 20 mins
Turn off hard disks: Never
System standby: Never

I left the application running and went out of the office for around a half hour. When I got back
the monitor was blank. I assume it was because the power saving feature blanked the monitor. I hit
the down arrow and the monitor unblanked.
 
Then I set the Turn off monitor setting to one minute.

The monitor went off. Then it briefly flashed but before it could synchronize it went off.

I changed the code to:
turn on monitor
sleep one second
turn on monitor

The monitor went blank. This time it flashed and then I saw the desktop for a second and it went
blank.

So the turn on monitor does unblank it but something blanks it immediately after it turns on.

I am running Windows XP Pro SP3 with all patches. The motherboard is an ASUS A8N32-SLI Deluxe and I
am using the on board graphics.

Stewart Berman said:
I have a little application I use to explore managed code. It has a background task that changes
the wallpaper and then runs a little loop with a Thread.Sleep(6000) in it ten times. I added the
monitor on call right after the wallpaper is changed.

The intention is to not have the monitor blank out if the application is running.

My power settings are:
Power scheme: Home/Office Desk
Turn off monitor: After 20 mins
Turn off hard disks: Never
System standby: Never

I left the application running and went out of the office for around a half hour. When I got back
the monitor was blank. I assume it was because the power saving feature blanked the monitor. I hit
the down arrow and the monitor unblanked.

[email protected] (Colbert Zhou [MSFT]) said:
Hello Stewart,

I have tested the codes and they work fine for me in my side. I use the
following codes to test,

Dim nCounter As Integer
For nCounter = 1 To 20
SetMonitor(MonitorStatus.Monitor_On)
Thread.Sleep(70000)
Next nCounter

Please note we should let the thread sleep more than 60 seconds because the
Power Saver Option's minium time of turning off the display is 1 minute. If
the thread only sleeps for 10 seconds for each of the loop. The SetMonitor
function will send message broadcastly and the left time of display turning
off is refreshed. So we will never see the Power Saver turning off the
monitor.

Actually, I do the following things to test.
1. I set my Power Saver to turn off the monitor after 1 minutes if no
inputs are detected
2. I run the above codes.

After 1 minute, I see the Power Saver turnning off my Monitor, and then
after another 10(70-60) seconds, I can observe that my Monitor is turned on
by my application.

So when you say "SetMonitor(Wallpaper.MonitorStatus.Monitor_On) Does not
unblank the screen if the power saver has blanked it", would you mind
letting us know more specific steps and information, like how many minutes
you set in the system's Power Saver option and what is the exact codes you
are executing, as well as your test steps.

By the way, if I running your codes, it turns off the monitor for ten
seconds and then trun on the monitor for ten seconds as a cycle. Just works
like the codes indicate to be.


Best regards,
Ji Zhou
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).
 
What the power saving process does is turn off the graphics output -- it does not power down the
monitor. When you watch the monitor and power saving kicks in it shows a signal loss message for a
few seconds and then blanks out. The monitor is still powered up.

The article you referenced says "attempting to trigger the system's monitor blank timeout", I take
that to mean blank the monitor. The reverse, which is what I am trying to do is unblank it.

So what is the difference between changing the Windows "power state" of the monitor and
blanking/unblanking it?

BTW, all of the links in the article to the dotnetjunkies.com site are broken..

Andrew Morton said:
Stewart said:
Is there a way to control blanking and unblanking a monitor --
basically override the power settings and force the graphics card to
blank out or to turn on?

http://blogs.msdn.com/oldnewthing/archive/2006/06/13/629451.aspx

(Note that you shouldn't refer to setting the power state of the monitor as
"[un]blanking" it, because that means something different.)

Andrew
 
Hi Stewart,

Sorry for the late response. But currently, based on my test, the
SendMessage with SC_MONITORPOWER being -1 works on Vista and Windows Server
2008. But, it indeed does not work for XP. I can reproduce it and also find
some previous discussion on the newsgroup about the same issue,

http://relatedterms.com/ViewThread.aspx?t=680395

http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=micros
oft.public.win32.programmer.kernel&tid=0e45deea-244b-4200-8c97-771e52e9257b&
cat=&lang=&cr=&sloc=&m=1&p=1

Because XP is out if its main product life cycle. So there will not be a SP
or hotfix to change this behavior. So, if our objective is keeping the
Monitor on when our applicatio running, we may have to find some
alternative ways to work around it. What about the approaches of the
"Keeping the Monitor Turned ON" comment in this article?
http://www.codeproject.com/KB/cs/Monitor_management_guide.aspx

For your convenience, I quote it here,
"Hi, My requirements are to keep the Monitor ON for the Lifetime of my App.
So how can it be done?

Thanks...

Re: Keeping the Monitor Turned ON Dalibor Drzik 12:22 6 Sep '07

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
switch (message)
{
case WM_SYSCOMMAND:

switch (wParam)
{
// disable screen saver and monitor power-saving mode
case SC_SCREENSAVE:
case SC_MONITORPOWER:

return 0;
}

break;

case WM_DESTROY:

PostQuitMessage(0);

return 0;
}

return DefWindowProc(hwnd, message, wParam, lParam);
}
"

The idea is just to hook the SC_MONITORPOWER and SC_SCREENSAVE message in
the application's message loop. Someone in the C# forum has a .NET version
codes to do this,
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/da9554dc-
1da8-4648-97a2-351d5656e15c


Best regards,
Colbert Zhou
Microsoft Newsgroup Support Team
 
http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=micros
oft.public.win32.programmer.kernel&tid=0e45deea-244b-4200-8c97-771e52e9257b&
cat=&lang=&cr=&sloc=&m=1&p=1

This thread has the following comment:

"As the only way out, I found an option of changing power policy settings
(because besides screen saver, the monitor itself can be shut off too, which
I should think of as well), but the problem is that if another program or a
user changes those power settings too while my app is running how would I
know that and not change it back to what it was at exit. Unfortunately, I
can't find any indication of notifications sent for power policy changes in
Windows XP. "

But does not include any code or even a hint of how to change power policy settings. (I already
have an application that blocks a screen saver from firing by wiggling the tail of the mouse.)

This thread uses the same method I tried -- it just provides ways different ways of sending the same
information to the defproc routine at the end of most window's message processing.

However, I think I found the answer here:
http://msdn.microsoft.com/en-us/library/aa373208(VS.85).aspx

Will try it later today and let you know if I can get it to work in my app.
 
There are two problems with this approach:
1. It requires deriving your own form class so you can override the winproc method.
2. The message is only sent to the active/foreground window. (Some places it says active and some
places it says foreground.)

BTW,
Microsoft Windows Vista and later: If password protection is enabled by policy, the screen saver is
started regardless of what an application does with the SC_SCREENSAVE notification?even if fails to
pass it to DefWindowProc.
 
It requires deriving your own form class so you can override the winproc
method.
No, we do not need to derive our own form class. We can directly override
the WndProc like this,
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
End Sub

Actually, we can subclass any window handle's wndproc in the same process
via NativeWindow class. For more detailed information, you can refer the
"Subclass Any HWND" part in the following KB article,
http://support.microsoft.com/kb/815775
Yes, these two are disadvantages of this approaches.


And what about the SetThreadExecutionState you found and mentioned in your
previous reply. We can P/Invoke the API in VB.NET,
http://www.pinvoke.net/default.aspx/kernel32/SetThreadExecutionState.html

Have a nice day!

Best regards,
Colbert Zhou
Microsoft Newsgroup Support Team
 
No, we do not need to derive our own form class. We can directly override
the WndProc like this,

Interesting -- good to know.
"Subclass Any HWND" part in the following KB article,
http://support.microsoft.com/kb/815775

This appears to apply to C# only. It requires changing the designer generated portion of the
program's .cs file. In VB this is a separate file and includes the following comments:
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.

And what about the SetThreadExecutionState you found and mentioned in your
previous reply. We can P/Invoke the API in VB.NET,
http://www.pinvoke.net/default.aspx/kernel32/SetThreadExecutionState.html

That is the method I have working. Actually, I have two options:
1. Reset the Screen Saver timer -- which uses SystemParametersInfo
2. Reset the Power Saver timer -- which uses SetThreadExecutionState

The only problem is that (1) is effectively a subset of (2). If you reset the Power Saver timer you
reset the Screen Saver timer. So effectively the options are:
1. Block the screen saver or
2. Block the power saver and the screen saver
 
Actually the "Subclass Any HWND" approach in that KB article should work no
matter VB.NET or C# used. I have a test in my side to prove that,

Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim scWindow As New SubclassHWND
scWindow.AssignHandle(Me.Handle)
End Sub
End Class

Public Class SubclassHWND
Inherits NativeWindow
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
' Perform whatever custom processing you must have for this message
System.Diagnostics.Debug.WriteLine(m.ToString())
' forward message to base WndProc
MyBase.WndProc(m)
End Sub
End Class

So as long as the HWND belongs to window in the current process, we create
a new instance of SubclassHWND and call AssignHandle to that window. Then
we can subclass that window's message in the overrided WndProc.


Best regards,
Colbert Zhou
Microsoft Newsgroup Support Team
 
Back
Top