What window message applications receive on screen text size change - windows

A user has an ability to change a scale of displayed text (via Settings → Display → Change the size of text, apps and other items on Windows 10, for example).
What window message should I process to be aware of such changes?
I have a stuff which size depends on actual font height. However, size ajustments are time consuming so I would prefer not to perform them on each WM_PAINT arrival.

Isn't it WM_DPICHANGED?
Sent when the effective dots per inch (dpi) for a window has changed. The DPI is the scale factor for a window.
- The window is moved to a new monitor that has a different DPI.
- The DPI of the monitor hosting the window changes.

Related

Win32: How to make popup window match monitor DPI

I'm working on a Win32 app with multiple windows, some of which use WS_POPUPWINDOW style (no caption) and some of which use WS_OVERLAPPEDWINDOW style. The app has System DPI awareness.
When I move the overlapped windows between monitors, they scale to match the current monitor DPI as expected. But the popup windows only do this if there are no other open overlapped windows. Otherwise, they always try to match the scaling of the last active overlapped window in the same process, even if it's on another monitor with a different scale factor.
I guess this makes sense for some use cases, since you'd always want eg. a popup menu to match the scale of the current window. But I want my popups to behave as independent windows with their own scale factor.
How do I make popup windows always match the DPI of the monitor that they're positioned on?
As a quick fix before I eventually convert the app to per-monitor DPI awareness, I created an invisible overlapped owner window for the popup that tracks its position / size. This ensures that whenever the popup is active, it updates to use its owner's scaling, which always matches the current monitor.

MFC application not supporting wide monitors

I have an MFC application that works fine when the monitor resolution is 1280 x 1024.
If I change the monitor resolution to 1920 x 1200, the application window will not fit the complete monitor. So I want to know what changes I need to do in my code so that it fits to any resolution monitor.
There's a good chance that your MFC app is limiting the size of it's window.
I'd look at handlers for
WM_GETMINMAXINFO (the most likely culprit)Sent to a window when the size or position of the window is about to change. An application can use this message to override the window's default maximized size and position, or its default minimum or maximum tracking sizehttps://msdn.microsoft.com/en-us/library/windows/desktop/ms632626(v=vs.85).aspx
WM_SIZE https://msdn.microsoft.com/en-us/library/windows/desktop/ms632646(v=vs.85).aspx
WM_SIZING https://msdn.microsoft.com/en-us/library/windows/desktop/ms632647(v=vs.85).aspx
WM_WINDOWPOSCHANGED https://msdn.microsoft.com/en-us/library/windows/desktop/ms632652(v=vs.85).aspx
WM_WINDOWPOSCHANGING https://msdn.microsoft.com/en-us/library/windows/desktop/ms632653(v=vs.85).aspx

Win32: Displaying a Stock Icon in a Dialog Box under High DPI

I've got a dialog box where I need to display the standard Information icon. Here's my RC code:
ICON "",IDC_ICON_INFORMATION,18,70,21,20
I process the WM_INITDIALOG message as follows:
HICON aIcn = LoadIcon(NULL, IDI_INFORMATION);
SendDlgItemMessage(m_hWnd, IDC_ICON_INFORMATION, STM_SETICON, (WPARAM) aIcn, 0);
Everything works great under 96 DPI: the static control displays a 32x32-pixel icon.
However, when I switch to higher DPI's (through right-clicking on the Desktop, choosing Screen resolution, and clicking Make or other items larger or smaller) the icon does not scale! Since everything else scales nicely, the icon looks visually much smaller than the neighboring text. I would expect that on 144 DPI (150%) the icon dimensions will be 48x48 pixels. I did declare my application as DPI-aware through an XML manifest.
The damnedest thing is that when I use my own custom-made icon (also coming from the RC file), everything scales perfectly. Furthermore, the MessageBox function called with the MB_ICONINFORMATION flag does display a scaled version of the icon, as well.
Given these thoughts, I assume of the following:
The static control with the SS_ICON style can display scaled versions of icons.
The icon resource that contains the standard Information icon has a scaled version of the icon (48x48).
What am I doing wrong then?
Use LoadImage() instead of LoadIcon(), and specify the cxDesired and cyDesired params with the values you get from GetSystemMetrics(SM_CYICON) and GetSystemMetrics(SM_CXICON).
Or maybe just declaring your app as DPI aware could be enough? You can try that easily by simple creating a text file making it a manifest file.
See the example in the remarks section for the SetProcessDPIAware API

Full-screen window sizing in screen (pixel) units with VS6 C++ GUI editor, MFC?

I am trying to create a full-screen control panel window with many controls: buttons, sliders, list boxes, etc.
I can create a dialog window and add controls to it, but everything is scaled in dialog units. I just want to create a window in the GUI editor that is scaled in pixels, not derived units like dialog units.
I can sort of lay out all the controls in the GUI editor and then resize the window programmatically to full-screen using SetWindowPos, but the dialog window in the GUI editor will not look the same as the final product. I want it to be WYSIWIG in the GUI editor.
This is the front end for a small dedicated instrument control computer running XP. The SDK is written in MFC. I have to add and change controls frequently. The screen is small, 7" # 800 x 600, so of course I am developing the program on a different computer. I don't want the program window to change when I change monitors -- I want it fixed at 800 x 600, and I want the controls to be fixed in size and layout as well.
There must be a way -- this is more basic than the default functionality.
Thanks.
Dialog Units are based on properties of the font used by the dialog. A horizontal dialog unit is equal to 1/4th the average width of the current font.
A vertical dialog unit is equal to 1/8th the average character height of the current font.
I'd recommend using method 2 (MapDialogRect() for a 4 x 8 dialog) to figure out how many DLUs 800x600 corresponds to on your output display then make a reference form equal to that size. You can later use that reference form while you're designing.
p.s.-I'm glad Visual Studio no longer emphasizes dialog units since they were always a pain to deal with.
Thanks. I was able to make a reference form by just resizing the form manually in the GUI editor over and over again until it exactly filled the screen... No kidding that dialog units are a pain. From your response, I guess in the current Visual Studio there is a better way to do this? (This is my first experience with Windows programming).

Auto-Hide taskbar not appearing when my application is maximized

My application draws all its own window borders and decorations. It works fine with Windows taskbars that are set to auto-hide, except when my application window is maximized. The taskbar won't "roll up". It will behave normally if I have the application not maximized, even when sized all the way to the bottom of the screen. It even works normally if I just resize the window to take up the entire display (as though it was maximized).
I found the problem. My application was handling the WM_GETMINMAXINFO message, and was overriding the values in the parameter MINMAXINFO record. The values that were in the record were inflated by 7 (border width) the screen pixel resolution. That makes sense in that when maximized, it pushes the borders of the window beyond the visible part of the screen. It also set the ptMaxPosition (point that the window origin is set to when maximized) to -7, -7. My application was setting that to 0,0, and the max height and width to exactly the screen resolution size (not inflated). Not sure why this was done; it was written by a predecessor. If I comment out that code and don't modify the MINMAXINFO structure, the Auto-hide works.
As to why, I'm not entirely sure. It's possible that the detection for popping up an "autohidden" taskbar is hooked into the mechanism for handling WM_MOUSEMOVE messages, and not for WM_NCMOUSEMOVE. With my application causing the maximize to park my border right on the bottom of the screen, I would have been generating WM_NCMOUSEMOVE events; with the MINMAXINFO left alone, I would have been generating WM_MOUSEMOVE.
This is dependant on whether 'Keep the taskbar on top of other windows' is checked on the taskbar properties. If it's checked then the taskbar will appear.
But don't be tempted to programmatically alter this setting on an end users machine just to suit your needs, it's considered rude and bad practice. Your app should fit whatever environment it gets deployed to.

Resources