March 20th, 2024

Using the Display­Information class from a desktop Win32 application, part 1

For UWP apps, the Windows Runtime Display­Information class provides information about the display that the app is running one. In particular, the Orientation property tells you whether the screen is running in landscape, portrait, landscape-flipped, or portrait-flipped orientation.

For Win32 desktop apps, you can obtain a Display­Information object corresponding to a window handle or a display monitor with the assistance of the IDisplay­Information­Statics­Interop interface. This interface follows the usual pattern for interop interfaces: Query for the interface from the class activation factory and then use the desired Get­For­... method.

Let’s try that in our scratch program.

#include <windows.graphics.display.interop.h>
#include <winrt/Windows.Graphics.Display.h>

namespace winrt
{
    using namespace winrt::Windows::Graphics::Display;
}

winrt::DisplayInformation g_info{ nullptr };

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) try
{
    winrt::check_hresult(                                        
        winrt::get_activation_factory<winrt::DisplayInformation, 
            ::IDisplayInformationStaticsInterop>()->GetForWindow(
        hwnd, winrt::guid_of<decltype(g_info)>(),                
        winrt::put_abi(g_info)));                                
    return TRUE;
}
catch (...)      
{                
    return FALSE;
}                

We are following the principle of starting by doing nothing: Our first step is simply to create the Display­Information. We don’t do anything with it.

Our OnCreate can be simplified by taking advantage of the capture_interop helper.

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) noexcept
{
    g_info = wil::capture_interop<winrt::DisplayInformation>     
        (&IDisplayInformationStaticsInterop::GetForWindow, hwnd);

    return TRUE;
}
catch (...)
{
    return FALSE;
}

And when the window is destroyed, we clean up the Display­Information.

void
OnDestroy(HWND hwnd)
{
    g_info = nullptr;
    PostQuitMessage(0);
}

If we run this program, we get a “not implemented” exception when we call Get­For­Window(). Phew, good thing we didn’t get in too deep. We added only a few lines of code, so it’s easy to narrow in on the lines that are the source of the problem. And if it turns out that the entire undertaking is not implemented, well, we saved ourselves a lot of trouble: It took us only a few lines of code to discover this.

If you watch the debugger, you see a helpful message:

onecoreuap\windows\wgi\winrt\display\displayinformation.cpp(101)\Windows.Graphics.dll!00007FFFAB1BC87B: (caller: 00007FFFAB1BB741) ReturnHr(2) tid(6f04) 80004001 Not implemented
    Msg:[A DispatcherQueue is required for DisplayInformation created from an HWND] 

Aha, so the problem is that we need the thread to have a dispatcher queue. We’ll take up the story next time.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • alan robinson

    Pretty clear example of Microsoft ignoring the win32 api here - nobody would design this from first principles as the right way to do this for win32 apps. If microsoft won't provide a new GetWindowExStyle (or maybe GetWindowExExStyle) then I guess a third party will have to.

    ps I realize GetWindowExStyle is the wrong place for this return value, I just wanted to be able to invent a function with ExEx...

    Read more
    • Jan RingoÅ¡

      Those functions in Win32 API already exist. MonitorFromWindow, EnumDisplaySettings, etc.

  • Antonio Rodríguez

    s/the app is running one/the app is running on/