How To Determine If An LCD Is Off

weirddemon
weirddemon used Ask the Experts™
on
I asked this question yesterday and I thought I received a solution, but I did not.

I ran the code on my laptop that had an external monitor attached. When I ran the code, the PrimaryDevice (my laptop screen) showed a DeviceID of 1. When the lid was closed, it showed an DID of 0.

I thought this was perfect. But, it turns out that when I removed the external monitor, the DeviceID stays 5 and persists no matter the state of the monitor.

I tried this on 5 notebooks. All had the same info. No information changed and this has become very frustrating. So I'm hoping someone can can help me come up with a solution. I've attached the code I'm using.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2012
Top Expert 2008

Commented:
I would think that WMI and the Win32_DesktopMonitor class would be able to give you Availability.

Win32_DesktopMonitor class
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394122(v=VS.85).aspx

Author

Commented:
TheLearnedOne,

Unfortunately, that too does not work. It reports the same as the API. I tried that many days ago, with no luck.
Most Valuable Expert 2012
Top Expert 2008

Commented:
That's interesting, but understandable, since I hadn't looked at this specifically.  The Availability property is supposed to give you the monitor state.  With a little research, I see that detecting when the laptop lid is closed is not an easy proposition.  I would imagine that you have looked into ACPI events, and the like.  I would like to know what you have tried, and what didn't work.
Introduction to Web Design

Develop a strong foundation and understanding of web design by learning HTML, CSS, and additional tools to help you develop your own website.

Author

Commented:
TheLearnedOne,

I've tried the API I mentioned above, WMI and the WindProc method so far.

One person suggested that the top level window receives a WM_SYSCOMMAND message with wParam set to SC_MONITORPOWER whenever the power status of a display is changing. But I'm afraid I'm not 100% sure how to work with that.

With the WindProc function, I tried just seeing if the message matched SC_MONITORPOWER, but it didn't work. I tried a few other constants with it, but I can't remember them all and they didn't work.
Most Valuable Expert 2012
Top Expert 2008

Commented:
I saw the SC_MONITORPOWER suggestion, but there where comments that this didn't work.  I would have implemented this in an IMessageFilter, rather than overriding WndProc, but that is not important.

I wonder if monitoring for the WM_POWERBROADCAST system notification would work.

System Power Management Events
http://msdn.microsoft.com/en-us/library/windows/desktop/aa373223(v=vs.85).aspx
Most Valuable Expert 2012
Top Expert 2008

Commented:
http://social.msdn.microsoft.com/Forums/en-US/tabletandtouch/thread/0bbf90be-9322-47fb-bfa4-016b57211b3a

In Vista you can register for a callback for when the Lid Close Action changes.  This is done by calling RegisterPowerSettingNotification (see http://msdn2.microsoft.com/en-us/library/aa373196.aspx for details).  The GUID for this power setting you're interested in is GUID_LIDCLOSE_ACTION.  This is defined in wdm.h in the Platform SDK.  
 
Once registered, a WM_POWERBROADCAST will be sent to your application with wParam set to PBT_POWERSETTINGCHANGE.   This event is sent anytime the value for the lid close action changes.  The lParam contains a pointer to a POWERBROADCAST_SETTING structure (see http://msdn2.microsoft.com/en-us/library/aa372723.aspx) containing information on the setting change.

Author

Commented:
TheLearnedOne,

I forgotten to mention that I already looked into that method because I had given up on trying to determine if the lid had been closed.

I spent a lot of time trying to figure out how to put all the pieces together for that one, but I was unable to understand everything. I'm sure it could be done, but I lack the direct knowledge and I haven't received much help trying to piece it together.
Most Valuable Expert 2012
Top Expert 2008

Commented:
Aha, that's why I was asking what you tried, and didn't work.  Can you describe your requirement again, so that I may be certain what you are trying to do.  I picked out the "lid closed" comment, which is probably not what you are concerned with.  The Win32_DesktopMonitor.Availability didn't work for you, but I haven't tried it for myself.

Author

Commented:
TheLearnedOne,

Sure, no problem. I'm sorry I'm not being as clear as I can. I hope this description clears things up.

Basically, I need to determine when the lid of the laptop is closed. I need to force the users to close the lid 'n' amount of times and open it the same amount of times.

So when I first started looking this up, I went with that. But everything I came across either didn't work, or I wasn't able to get it to work.

So then I thought... when the lid is closed, the LCD turns off. So if I could figure out when the LCD turned off, that would amount to the same thing as determining when the lid was closed.

And so here we are. Does that help?
Top Expert 2016

Commented:
So then I thought... when the lid is closed, the LCD turns off. So if I could figure out when the LCD turned off, that would amount to the same thing as determining when the lid was closed.

all that happens when the lid is closed is the power to the lcd backlight is removed.

Author

Commented:
ve30fa,

And when the lid is closed, the back light turns off. So it was a reasonable method. I just can't figure out how to detect either/or.

Commented:
How to detect laptop lid closed?

Check this Blog...

How are power buttons reported in Windows?

POCLASS.H contains following flags:

#define SYS_BUTTON_LID              0x00000004L
#define SYS_BUTTON_WAKE             0x80000000L
#define SYS_BUTTON_LID_STATE_MASK   0x00030000L
#define SYS_BUTTON_LID_OPEN         0x00010000L
#define SYS_BUTTON_LID_CLOSED       0x00020000L
#define SYS_BUTTON_LID_INITIAL      0x00040000L
#define SYS_BUTTON_LID_CHANGED      0x00080000L

Commented:
Did you get further with your problem???
This was a long an arduous path. Mainly because the documentation for this is next to none. But, thankfully someone at VBF was able to solve my problem. It all basically came down to an API that registers the form to receive this particular power event. Along with this, I needed to not only capture the message, but also the wparam of the message.

I've attached the solution. The API just needs to be called during Form load or whenever. It returns a value that you can pass to another API, that will unregister the power event if you need it.
Const PBT_POWERSETTINGCHANGE As Integer = &H8013
Const WM_POWERBROADCAST As Integer = &H218
Const DEVICE_NOTIFY_WINDOW_HANDLE As Integer = &H0
Public Shared GUID_LIDSWITCH_STATE_CHANGE As New Guid(&HBA3E0F4DUI, &HB817, &H4094, &HA2, &HD1, &HD5, &H63, &H79, &HE6, &HA0, &HF3)

Protected Overrides Sub WndProc(ByRef msg As System.Windows.Forms.Message)
    If msg.Msg = WM_POWERBROADCAST And msg.WParam = PBT_POWERSETTINGCHANGE Then
       'Do whatever
    End If

    MyBase.WndProc(msg)
End Sub

RegisterPowerSettingNotification(Me.Handle, GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE)

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial