Create mobile apps with HTML5, JavaScript and Visual Studio

(Elle) #1

18 msdn magazine Windows with C++


Traditionally, Direct2D applications simply retrieved the DPI


values from the Direct2D factory, which in turn simply called


GetDeviceCaps, as I illustrated earlier. But this is no longer suffi -


cient. As I’ve shown, the DPI values may now change on the fl y, and


the value provided by GetDeviceCaps is only useful if you’re trying


to fi t in with the rendering of a system DPI-aware application.


Instead, right aft er you’ve created your Direct2D render target, you


need to query the DPI value for the monitor nearest your window:


auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);

Given this monitor handle, you can call the GetDpiForMonitor


function to retrieve the DPI values for this specifi c monitor:


auto x = unsigned {};
auto y = unsigned {};
VERIFY_(S_OK, GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &x, &y));

Th e eff ective DPI value for a given monitor won’t necessarily


correspond exactly to options presented in Figure 4. It again


depends on a number of factors, including resolution, the phys-


ical DPI of the display and the assumed distance to the display


surface. Finally, you can call the Direct2D render target’s SetDpi


method and Direct2D will take care of properly


scaling your content as needed.


I did mention this can all happen dynamically.


Your application may be running and suddenly the


user changes the scale with the window shown in


Figure 3 or drags your window to another monitor


with a diff erent DPI scaling factor. In those cases, the


Windows shell will send per-monitor DPI-aware


application windows a new window message called


WM_DPICHANGED.


Inside your message handler, you can once again call


the MonitorFromWindow and GetDpiForMonitor


functions to get the eff ective DPI values for the current


monitor and then simply update your Direct2D ren-


der target with its SetDpi method again. Alternatively,


the message’s WPARAM packs both the x and y DPI


values so this becomes a simple matter of extracting


the low and high order words:


auto x = LOWORD(wparam);
auto y = HIWORD(wparam);

Th e WM_DPICHANGED message’s LPARAM is,


however, indispensable. It provides a new suggested


position and size of your window based on the new


scale factor that’s now in eff ect. Th is ensures that while


Direct2D takes care of scaling your content, you can


also scale your window’s actual size on the desktop


and position it appropriately. Th e message’s LPARAM


is just a pointer to a RECT structure:


auto rect = *reinterpret_cast<RECT *>(lparam);

You can then simply call the SetWindowPos function to update


your window’s position and size:


VERIFY(SetWindowPos(window,
0, // No relative window
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER));

And that’s all it takes. If you’ve invested in Direct2D, you’re just


a few steps away from being per-monitor DPI-aware. Few appli-


cations have made the leap, so your application is bound to stand


out! If you’ve got an existing Windows Presentation Foundation


(WPF) application, there’s also a sample available at bit.ly/IPDN3p that


shows you how to integrate these same principles outlined in this


article into your WPF code base.


Figure 9 provides an example of a per-monitor DPI-aware applica-


tion, automatically scaling both its content and its window size based


on WM_DPICHANGED messages. Th e emoticon indicates which


monitor the window is currently positioned on. For a more interactive


example, please check out my Pluralsight course at bit.ly/1fgTifi , where


you can also get the sample code for this application. Q


KENNY KERR is a computer programmer based in Canada, as well as an author for


Pluralsight and a Microsoft MVP. He blogs at kennykerr.ca and you can follow


him on Twitter at twitter.com/kennykerr.


THANKS to the following technical expert for reviewing this article:


James Clarke (Microsoft )


Figure 9 Per-Monitor DPI-Aware Application


If you’ve invested in Direct2D,


you’re just a few steps away from


being per-monitor DPI-aware.

Free download pdf