Detecting if laptop lid is closed/integrated screen is off Detecting if laptop lid is closed/integrated screen is off windows windows

Detecting if laptop lid is closed/integrated screen is off


Sounds like you don't really care if the lid is closed or not and just want to know if the screen area where you are about to launch your application is available or not.

If the OS "still uses the shut off screen for its extended desktop" then that means (from the OS's point of view) that the screen is available to be used for applications. In other words - your application would not be the only one suffering from that issue. Though I have to say I have never observed that particular behavior first-hand.

If you need to move your application while it is running then you can register for the RegisterPowerSettingNotification and act on it.

However if you are launching and need to know if the screen is on or off you have two options:

EnumDisplayDevices

This will provide you with the information on whether your screen is attached to a desktop and is active. This is "system info" that you get from the API in User32.dll

DISPLAY_DEVICE ddi;ddi.cb = sizeof(ddi);DWORD iDevNum = 0; // or iterate 0..15EnumDisplayDevices(NULL, iDevNum, &ddi, /*EDD_GET_DEVICE_INTERFACE_NAME*/0);if( (ddi.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0 &&    (ddi.StateFlags & DISPLAY_DEVICE_ACTIVE) != 0 ){...}

DXGI (DX11)

This gives you basically the same info as above but with a more modern approach (and potentially fewer false positives). Of course that would require you to link-in DXGI for this to work and include the header which will increase your application size:

#include <atltypes.h>IDXGIAdapter * pAdapter; std::vector <IDXGIAdapter*> vAdapters; IDXGIFactory* pFactory = NULL; // Create a DXGIFactory object.if(FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory) ,(void**)&pFactory))){    return;}for(UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i){    DXGI_ADAPTER_DESC ad = {0};    if(SUCCEEDED(pAdapter->GetDesc(&ad))){        UINT j = 0;        IDXGIOutput * pOutput;        while(pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND)        {            DXGI_OUTPUT_DESC od = {0};            if(SUCCEEDED(pOutput->GetDesc(&od))){                // in here you can access od.DesktopCoordinates                // od.AttachedToDesktop tells you if the screen is attached            }            pOutput->Release();            ++j;        }    }    pAdapter->Release();} if(pFactory){    pFactory->Release();}

Hope that helps.

Direct3D9

This method also provides display information but in a slightly different way - via a list of adapters and monitors attached to those adapters. Remember to link-in d3d9 library for this to work:

void d3d_adapterInfo(IDirect3D9 * _pD3D9, UINT _n){    D3DADAPTER_IDENTIFIER9 id;    const DWORD flags = 0;    if(SUCCEEDED(_pD3D9->GetAdapterIdentifier(_n, flags, &id))){        // id provides info on Driver, Description, Name        HMONITOR hm = _pD3D9->GetAdapterMonitor(_n);        // and based on that hm you get the same monitor info as        // with the first method    }}void d3d_enumDisplays(){    cout << endl << "--- Information by Direct3D9 ---" << endl;    IDirect3D9 * pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);    const auto nAdapters = pD3D9->GetAdapterCount();    cout << "A total of " << nAdapters << " adapters are listed by Direct3D9" << endl;    for(UINT i = 0; i < nAdapters; ++i){        d3d_adapterInfo(pD3D9, i);    }    pD3D9->Release();}

All 3 code snippets are from some of my projects so you can just copy-paste the code and it should work (baring some minor fixes for missing functions or variables as I was modifying the code on-the-fly to reduce its size when posted it here)