DPI scaling issues

Pages: 12
I am not getting the scale ratio right, what am I doing wrong?.
The button always moves at a different scale ratio.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#ifndef UNICODE
#define UNICODE
#endif 

#include <windows.h>

// Forward declarations of functions included in this code module:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int DpiScaleX(int val);
int DpiScaleY(int val);

 //int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
 int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
    // Register the window class.
    const wchar_t CLASS_NAME[] = L"Sample Window Class";
      WNDCLASSEX wcex = { };
                 wcex.cbSize = sizeof(WNDCLASSEX);
                 wcex.style = CS_HREDRAW | CS_VREDRAW;
                 wcex.lpfnWndProc = WindowProc;
                 wcex.cbClsExtra = NULL;
                 wcex.cbWndExtra = NULL;
                 wcex.hInstance = hInstance;
                 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
                 wcex.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
                 wcex.lpszMenuName = NULL;
                 wcex.lpszClassName = CLASS_NAME;
                 wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
                 wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
      RegisterClassEx(&wcex);
    
    // Create the window.
    HWND hwnd_Main = CreateWindowEx(
        0,                                        // Optional window styles.
        CLASS_NAME,                               // Window class
        L"C++ Window with a button",              // Window text
        WS_OVERLAPPEDWINDOW,                      // Window style
        0, 0, DpiScaleX(500), DpiScaleY(400),     // Size and position
        NULL,                                     // Parent window    
        NULL,                                     // Menu
        hInstance,                                // Instance handle
        NULL);                                    // Additional application data
   
    if (hwnd_Main == NULL){return 0;}
    
    // Adds a button
    HWND hwndButton = CreateWindowEx(
        NULL,                                                   // Optional window styles.
        L"BUTTON",                                              // Predefined class; Unicode assumed 
        L"&Close",                                              // Button text  
        WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles  
        DpiScaleX(350),                                         // x position
        DpiScaleY(250),                                         // y position
        DpiScaleX( 75),                                         // Button width
        DpiScaleY( 23),                                         // Button height
        hwnd_Main,                                              // Parent window
        (HMENU)IDCANCEL,                                        // handle to menu, or child-window identifier
        GetModuleHandle(NULL),                                  // handle to application instance
        NULL);                                                  // pointer to window-creation data
    
     // Display the window
     ShowWindow(hwnd_Main, nCmdShow);
      UpdateWindow(hwnd_Main);

    // Dispatch Windows messages
    MSG msg = { };
    while (GetMessage(&msg, 0, 0, 0))
    {
        if (IsDialogMessage(hwnd_Main, &msg) == 0) { 
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return 0;
}

 int DpiScaleX(int val)
{
    const HDC hDC = ::GetDC(NULL);
    const UINT dpix = ::GetDeviceCaps(hDC, LOGPIXELSX);
    ::ReleaseDC(NULL, hDC);
    return ::MulDiv(val, dpix, 96);
}

 int DpiScaleY(int val)
 {
     const HDC hDC = ::GetDC(NULL);
     const UINT dpiy = ::GetDeviceCaps(hDC, LOGPIXELSY);
     ::ReleaseDC(NULL, hDC);
     return ::MulDiv(val, dpiy, 96);
 }

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
 
    case WM_COMMAND:

        switch (LOWORD(wParam)) 
        {
         case IDCANCEL:
           SendMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;  //break;
        }

    case WM_SIZE:
    {
            RECT client_rectangle;
            ::GetClientRect(hwnd, &client_rectangle);

            int width = client_rectangle.right - client_rectangle.left;
            int height = client_rectangle.bottom - client_rectangle.top;
       
            ::MoveWindow(GetDlgItem(hwnd, IDCANCEL), width - 150, height - 50, DpiScaleX(75), DpiScaleY(23), TRUE);
    }
        return 0;  // break;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Last edited on
Your issue is not clear, the button moves exactly as you programmed it.

What's an obvious issue here is that it looks like you're trying to adjust window and button dimensions according to DPI change, but it doesn't work when you change DPI in Settings app, is that right?

Also when changing DPI you button is blur and window size does not change.
In other words your window and button is not DPI aware..

If yes this is because DPI must be handled in WM_DPICHANGED
But there is much more to proper DPI handling, so until you confirm this is your issue I'll skip that.

EDIT:
See these links:
https://docs.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process
https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
https://docs.microsoft.com/en-us/windows/win32/learnwin32/dpi-and-device-independent-pixels

After you studied those links, here is sample code:
https://github.com/tringi/win32-dpi
Last edited on

but it doesn't work when you change DPI in Settings app, is that right?

if I set my screen to 150% scale ratio, the button is in a different position than at 200%.
I always restart the program after adjusting the scaling ratio, after that the button is no longer in position.

I am aware of WM_DPICHANGED, not important at this stage I think.
I am aware of WM_DPICHANGED, not important at this stage I think.

If it's not important then how is your code notified about DPI change?

Anyway, I edited my post with few links that you should read, in particular this one:
https://docs.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process

What happens is that DWM (Desktop Window Manager) automatically resizes your window (and thus makes it look bad) because your window is not DPI aware.
Last edited on
I found the problem, now it works as it should.

1
2
3
4
5
6
7
 int DpiScale(int val)
 {
     const HDC hDC = ::GetDC(HWND_DESKTOP);
     const float dpix = ::GetDeviceCaps(hDC, LOGPIXELSX) / 96.0f;
     ::ReleaseDC(HWND_DESKTOP, hDC);
     return static_cast<int> (val * dpix); 
 }


The button stays at the same location with every scale ratio without WM_DPICHANGED
Last edited on
Thanks for posting your solution (in case somebody else happens to stumble upon this thread).
The button stays at the same location with every scale ratio without WM_DPICHANGED

There was no need to write any code, your functions "DpiScale" are redundant, all you had to do is add manifest to executable, to disable DWM behavior.
Last edited on
No, I have correctly set up in Microsoft Visual Studio that he creates a mainfest file with HIGH DPI Aware active.
so that I don't get blurry text and always see the button in the correct position.

But if that's not necessary I want to see code
Last edited on
I posted on this topic here quite a while ago and presented quite a lot of code...

http://www.cplusplus.com/forum/windows/160413/

I think it's all correct, but I want to revisit this issue as soon as I get time. Microsoft added a few more functions and functionality (and complexity) since I last dealt with all this. One can manage it without a manifest, although MS pushes using one.
in the end I didn't use the built-in manifest tool in Microsoft Visual Studio, I created a resource file and referenced it to my own manifest file.
I don't want to waste time figuring out exactly how the built-in manifest tool works.

For some reason the system theme colors were not included, it works fine now

append to rc file
1
2
3
4
5
6
//=============================================================================
// Manifest
//=============================================================================
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ".\manifest.xml"


The link to your article is very interesting
As I said in reply #9 above, I needed to look into this issue again. I know JohnOfc marked this thread as solved, but I decided (and hoped) my new work on this topic might benifit someone, so I wanted to share my code. I worked on this topic about five years ago in the hope of making my GUIs at work look better for my users who changed the default resolution or fonts on their machines for whatever reason, i.e., poor eyesight, personal preference, whatever. The code I originally wrote worked good I think but never accounted for the situation - becomming more and more common nowadays, if not universal, of folks using multiple monitors, where DPIs can change during the run of a program - or if the user changes DPI settings through Control Panel during the single run of a program. I can't say I really enjoy this kind of coding - I take it more or less like medicine, but I read up on the topic again (using Malibor's links), and tried to put together a skeleton GUI showing how to make one's code Multiple Monitor Version 2 Aware.

The provided code just creates a 'Log On' form with labels for user name and password, text boxes for user entry of the same, and a submit and cancel button. The first version of the code is the 'Release' version not corrupted with tons of debug output statements, and the second version has conditional Debug Output Log statements, without which I would have never have been able to figure this stuff out and get it working.

My plan of attack was to start the program at some particular font size and resolution - such as the recommended 100% in ...

Control Panel >> Settings >> System >> Display

...of my Dell Inspiron 17" laptop (1920 x 1080), then go back into Control Panel and change either or both the 'Scale And Layout' or screen resolution while the propgram is running. This causes the WM_DPICHANGED message to fire, and one can view on screen either the damage done or correctness of one's code in response to those actions. Here is an example of the Debug Log file created by such a run...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
Entering fnWndProc_OnCreate()
  Wea.hWnd      = 0000000000030382
  blnDpiAware   = 1
  iDpi          = 96
  Siz(10)       = 10

  Entering FindFont()
    rc.bottom     = 16
    rc.right      = 156

    Next Iteration...
    iFont           = 8
    nHeight           = -11
    hTmp              = 00000000058A0098
    tm.tmHeight       = 13
    iDiff             = 3

    Next Iteration...
    iFont           = 9
    nHeight           = -12
    hTmp              = 00000000058A0098
    tm.tmHeight       = 14
    iDiff             = 2

    Next Iteration...
    iFont           = 10
    nHeight           = -13
    hTmp              = 00000000058A0098
    tm.tmHeight       = 16
    iDiff             = 0
    Got In Where iDiff <=0!!!
    hFont             = FFFFFFFFE30A0993
    hTmp              = 00000000058A0098
  Leaving FindFont()

  hFont         = FFFFFFFFE30A0993
  iWidth        = 300
  iHeight       = 124

  Entering SizeWindows()
    iDpi          = 96
    Siz(10)       = 10
    pRect->left   = 200
    pRect->top    = 100
    pRect->right  = 500
    pRect->bottom = 224
    iWidth        = 300
    iHeight       = 124
  Leaving SizeWindows()
Leaving fnWndProc_OnCreate()

Entering btnSubmit_Click()
  Wea.hWnd      = 0000000000030382
  bRet          = 1
  iDpi          = 96
  Siz(10)       = 1
  iWidth        = 300
  iHeight       = 124
Leaving btnSubmit_Click()

Entering fnWndProc_OnDpiChanged()
  Wea.hWnd      = 0000000000030382
  iDpi          = 144
  Siz(10)       = 15
  pRect->left   = 200
  pRect->top    = 100
  pRect->right  = 650
  pRect->bottom = 286
  iWidth        = 450
  iHeight       = 186
  Entering FindFont()
    rc.bottom     = 26
    rc.right      = 236

    Next Iteration...
    iFont           = 8
    nHeight           = -16
    hTmp              = 00000000058A0098
    tm.tmHeight       = 19
    iDiff             = 7

    Next Iteration...
    iFont           = 9
    nHeight           = -18
    hTmp              = 00000000058A0098
    tm.tmHeight       = 22
    iDiff             = 4

    Next Iteration...
    iFont           = 10
    nHeight           = -20
    hTmp              = 00000000058A0098
    tm.tmHeight       = 24
    iDiff             = 2

    Next Iteration...
    iFont           = 11
    nHeight           = -22
    hTmp              = 00000000058A0098
    tm.tmHeight       = 27
    iDiff             = -1
    Got In Where iDiff <=0!!!
    hFont             = 00000000050A13BF
    hTmp              = 00000000058A0098
  Leaving FindFont()

  Entering SizeWindows()
    iDpi          = 144
    Siz(10)       = 15
    pRect->left   = 200
    pRect->top    = 100
    pRect->right  = 650
    pRect->bottom = 286
    iWidth        = 450
    iHeight       = 186
  Leaving SizeWindows()
Leaving fnWndProc_OnDpiChanged()

Entering btnSubmit_Click()
  Wea.hWnd      = 0000000000030382
  bRet          = 1
  iDpi          = 144
  Siz(10)       = 1
  iWidth        = 450
  iHeight       = 186
Leaving btnSubmit_Click()

Entering fnWndProc_OnDestroy()
  Wea.hWnd      = 0000000000030382
  hFont         = 00000000050A13BF
Leaving fnWndProc_OnDestroy()


That run started at 96 DPI resolution, then changed to 144 which ups the sizing factor for everything by a factor of 1.5. Anyway, next post is the release version with no output log statements...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// cl NewDpi6.cpp /O1 /Os kernel32.lib user32.lib gdi32.lib                  92,672 Bytes; Release; x64; VC19; LIBCMT Static Linkage /MT
// cl NewDpi6.cpp /O1 /Os /GS- TCLib.lib kernel32.lib user32.lib gdi32.lib    9,216 Bytes; Release; x64; VC19; TCLib  Static Linkage
#ifndef UNICODE
   #define UNICODE            
#endif                        
#ifndef _UNICODE              
   #define _UNICODE           
#endif 
#include <Windows.h>
//#define TCLib                        
#ifdef TCLib  
   #pragma warning(disable:4996 4565 4244 4100)         
   #include "stdlib.h"        
   #include "stdio.h"         
#else 
   #pragma warning(disable:4244 4100 4996)  
   #include <stdlib.h> 
   #include <stdio.h>
#endif   
#include "NewDpi6.h"          
    
                        
HFONT FindFont(WndEventArgs& Wea, int& iDpi)
{
 HWND       hCtl        = NULL;
 HFONT      hFont       = NULL;
 HFONT      hTmp        = NULL;
 HDC        hDC         = NULL;
 int        iFont       = 8; 
 TEXTMETRIC tm;
 RECT       rc;
 int        nHeight; 
 int        iDiff;
 
 hFont=(HFONT)GetWindowLongPtr(Wea.hWnd,GWLP_USERDATA);
 if(hFont)
    DeleteObject(hFont);
 hCtl=CreateWindowEx(WS_EX_CLIENTEDGE,L"edit",L"",WS_CHILD,Siz(110),Siz(10),Siz(160),Siz(20),Wea.hWnd,(HMENU)IDC_TEST,Wea.hIns,0);
 GetClientRect(hCtl,&rc);
 DestroyWindow(hCtl);
 hDC = GetDC(NULL); 
 do  
 {
    nHeight=-MulDiv(iFont, iDpi, 72.0);
    hFont=CreateFont(nHeight,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,0,0,0,0,L"Tahoma");     
    hTmp=(HFONT)SelectObject(hDC,hFont);
    GetTextMetrics(hDC,&tm);
    iDiff=rc.bottom-tm.tmHeight;
    if(iDiff<=1)
    {
       SetWindowLongPtr(Wea.hWnd,GWLP_USERDATA,(LONG_PTR)hFont);
       SelectObject(hDC,hTmp);
       break; 
    }                                                            
    else
    {  
       DeleteObject(SelectObject(hDC,hTmp));   
       iFont++;
    }   
 }while(true);
 ReleaseDC(Wea.hWnd,hDC);
 
 return hFont;	
}

 
void SizeWindows(HWND hWnd, RECT* pRect, int& iDpi)
{
 HFONT hFont = NULL;
 HWND  hCtl  = 0;
  
 MoveWindow(hWnd,pRect->left,pRect->top,pRect->right-pRect->left,pRect->bottom-pRect->top,TRUE);
 hFont=(HFONT)GetWindowLongPtr(hWnd,GWLP_USERDATA);
 hCtl=GetDlgItem(hWnd,IDC_lblUserName);
 MoveWindow(hCtl,Siz(10),Siz(12),Siz(90),Siz(16),TRUE);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 SetWindowText(hCtl,L"User Name");
 hCtl=GetDlgItem(hWnd,IDC_txtUserName);
 MoveWindow(hCtl,Siz(110),Siz(10),Siz(160),Siz(20),TRUE);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=GetDlgItem(hWnd,IDC_lblPassWord);
 MoveWindow(hCtl,Siz(10),Siz(36),Siz(90),Siz(16),TRUE);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 SetWindowText(hCtl,L"Password");
 hCtl=GetDlgItem(hWnd,IDC_txtPassWord);
 MoveWindow(hCtl,Siz(110),Siz(34),Siz(160),Siz(20),TRUE);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=GetDlgItem(hWnd,IDC_btnSubmit);
 MoveWindow(hCtl,Siz(120),Siz(60),Siz(60),Siz(20),TRUE);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 SetWindowText(hCtl,L"Submit");
 hCtl=GetDlgItem(hWnd,IDC_btnCancel);
 MoveWindow(hCtl,Siz(200),Siz(60),Siz(60),Siz(20),TRUE);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 SetWindowText(hCtl,L"Cancel");
 
 return;
}


LRESULT fnWndProc_OnCreate(WndEventArgs& Wea)
{
 int        iDpi        = 0;
 HWND       hCtl        = NULL;
 HFONT      hFont       = NULL;
 RECT       rc;
 
 Wea.hIns    = ((LPCREATESTRUCT)Wea.lParam)->hInstance;
 iDpi        = GetDpiForWindow(Wea.hWnd); 
 hFont=FindFont(Wea, iDpi); 
 hCtl=CreateWindowEx(0,L"static",L"User Name",WS_CHILD|WS_VISIBLE|SS_RIGHT,0,0,0,0,Wea.hWnd,(HMENU)IDC_lblUserName,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(WS_EX_CLIENTEDGE,L"edit",L"",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_txtUserName,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(0,L"static",L"Password",WS_CHILD|WS_VISIBLE|SS_RIGHT,0,0,0,0,Wea.hWnd,(HMENU)IDC_lblPassWord,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(WS_EX_CLIENTEDGE,L"edit",L"",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_txtPassWord,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(0,L"button",L"Submit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_btnSubmit,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(0,L"button",L"Cancel",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_btnCancel,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 rc.left=Siz(200), rc.top=Siz(100), rc.right=Siz(500), rc.bottom=Siz(224);
 SizeWindows(Wea.hWnd, &rc, iDpi); 
 
 return 0;
}


LRESULT btnSubmit_Click(WndEventArgs& Wea)
{
 MessageBox(Wea.hWnd,L"You Clicked The Submit Button",L"Button Click Report",MB_OK);
 return 0;
}


LRESULT btnCancel_Click(WndEventArgs& Wea)
{
 DestroyWindow(Wea.hWnd);
 return 0;
} 


LRESULT fnWndProc_OnCommand(WndEventArgs& Wea)
{
 switch(LOWORD(Wea.wParam))
 {
   case IDC_btnSubmit:
     return btnSubmit_Click(Wea);
   case IDC_btnCancel:
     return btnCancel_Click(Wea);
 } 
 
 return DefWindowProc(Wea.hWnd, WM_CTLCOLOREDIT, Wea.wParam, Wea.lParam); 
}	


LRESULT fnWndProc_OnDpiChanged(WndEventArgs& Wea)
{
 int    iDpi    = 0;
 RECT*  pRect   = NULL;
  
 iDpi=LOWORD(Wea.wParam);
 pRect=(RECT*)Wea.lParam;
 FindFont(Wea, iDpi); 
 SizeWindows(Wea.hWnd,pRect,iDpi);
 
 return 0;
}


LRESULT fnWndProc_OnDestroy(WndEventArgs& Wea)
{
 HFONT hFont = NULL;
 
 hFont=(HFONT)GetWindowLongPtr(Wea.hWnd,GWLP_USERDATA);
 DeleteObject(hFont);
 PostQuitMessage(0);
  
 return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(size_t i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI wWinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPTSTR lpszArgument, int iShow)
{
 wchar_t szClassName[]=L"NewDpi6";
 WNDCLASS wc;
 HWND hWnd;
 MSG Msg;
  
 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
 memset(&wc,0,sizeof(WNDCLASS));
 wc.lpszClassName = szClassName,                     wc.lpfnWndProc   = fnWndProc;
 wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION),  wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 
 wc.hInstance     = hIns,                            wc.hCursor       = LoadCursor(NULL,IDC_ARROW),          
 RegisterClass(&wc);
 hWnd=CreateWindow(szClassName,L"DpiAware V2",WS_OVERLAPPEDWINDOW,0,0,0,0,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&Msg,NULL,0,0))
 {
    if(!IsDialogMessage(hWnd,&Msg))
    { 
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }   
 }

 return (int)Msg.wParam;
}

...and NewDpi6.h include file....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//NewDpi6.h
#ifndef NewDpi6_h
#define NewDpi6_h

#define dim(x)                    (sizeof(x) / sizeof(x[0]))
#define Siz(z)                    (int)(z * iDpi/96.0)

#define IDC_lblUserName           2000
#define IDC_lblPassWord           2005
#define IDC_txtUserName           2010
#define IDC_txtPassWord           2015
#define IDC_btnSubmit             2020
#define IDC_btnCancel             2025
#define IDC_TEST                  9999

#ifdef TCLib
   extern "C" int                 _fltused=1;
#endif
   
struct WndEventArgs
{
 HWND                             hWnd;
 WPARAM                           wParam;
 LPARAM                           lParam;
 HINSTANCE                        hIns;
};

HFONT   __cdecl                   FindFont(WndEventArgs& Wea, int& iDpi);
void    __cdecl                   SizeWindows(HWND hWnd, RECT* pRect, int& iDpi);
LRESULT __cdecl                   fnWndProc_OnCreate(WndEventArgs& Wea);
LRESULT __cdecl                   btnSubmit_Click(WndEventArgs& Wea);
LRESULT __cdecl                   btnCancel_Click(WndEventArgs& Wea);
LRESULT __cdecl                   fnWndProc_OnCommand(WndEventArgs& Wea);
LRESULT __cdecl                   fnWndProc_OnDpiChanged(WndEventArgs& Wea);
LRESULT __cdecl                   fnWndProc_OnDestroy(WndEventArgs& Wea);
int     __stdcall                 wWinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPTSTR lpszArgument, int iShow);

struct EVENTHANDLER
{
 unsigned int                     iMsg;
 LRESULT                          (*fnPtr)(WndEventArgs&);
};

const EVENTHANDLER                EventHandler[]=
{
 {WM_CREATE,                      fnWndProc_OnCreate},
 {WM_COMMAND,                     fnWndProc_OnCommand},
 {WM_DPICHANGED,                  fnWndProc_OnDpiChanged},
 {WM_DESTROY,                     fnWndProc_OnDestroy}
};
#endif 
And here's the debug version (need three posts)....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// cl NewDpi5.cpp /O1 /Os /W4 kernel32.lib user32.lib gdi32.lib                 133,120 Bytes; Debug; x64; VC19; LIBCMT Static Linkage /MT
// cl NewDpi5.cpp /O1 /Os /GS- /W4 TCLib.lib kernel32.lib user32.lib gdi32.lib   12,288 Bytes; Debug; x64; VC19; TCLib  Static Linkage
#ifndef UNICODE
   #define UNICODE            
#endif                        
#ifndef _UNICODE              
   #define _UNICODE           
#endif 
#include <Windows.h>
//#define TCLib                        
#ifdef TCLib  
   #pragma warning(disable:4996 4565 4244 4100)         
   #include "stdlib.h"        
   #include "stdio.h"         
#else 
   #pragma warning(disable:4244 4100 4996)  
   #include <stdlib.h> 
   #include <stdio.h>
#endif   
#include "NewDpi5.h"          
#define Debug  
    
#ifdef Debug
   FILE* fp=NULL;
#endif 

                        
HFONT FindFont(WndEventArgs& Wea, int& iDpi)
{
 HWND       hCtl        = NULL;
 HFONT      hFont       = NULL;
 HFONT      hTmp        = NULL;
 HDC        hDC         = NULL;
 int        iFont       = 8; 
 TEXTMETRIC tm;
 RECT       rc;
 int        nHeight; 
 int        iDiff;
 
 #ifdef Debug
 fprintf(fp,"  Entering FindFont()\n");
 #endif
 hFont=(HFONT)GetWindowLongPtr(Wea.hWnd,GWLP_USERDATA);      // Font Being Used For Each DPI Is Persisted/StoredIn Window Structure
 if(hFont)
    DeleteObject(hFont);                                     // This Procedure Will Create A New One
 // Figure Out Closest Matching HFONT To Client Rectangle Of Edit Control.  Create Dummy/Temp Edit Control To Facilitate The Determination. 
 hCtl=CreateWindowEx(WS_EX_CLIENTEDGE,L"edit",L"",WS_CHILD,Siz(110),Siz(10),Siz(160),Siz(20),Wea.hWnd,(HMENU)IDC_TEST,Wea.hIns,0);
 GetClientRect(hCtl,&rc); // rc.bottom Will Hold Height Of Client Area Of Control
 #ifdef Debug
 fprintf(fp,"    rc.bottom     = %d\n",rc.bottom);  // See how big Client Rectangle of edit control is
 fprintf(fp,"    rc.right      = %d\n",rc.right);
 #endif
 DestroyWindow(hCtl); // Done With Control.  Destroy It.
 hDC = GetDC(NULL); 
 do // Put Font Creation In A Loop Where The Height Of The Font Is Continually Compared To The Client Rectangle 
 {  // Of A Control Until A Close Match Is Made, i.e., Somewhere Around Zero Pixels Difference Or So.
    #ifdef Debug                                             
    fprintf(fp,"\n    Next Iteration...\n");                       
    fprintf(fp,"    iFont           = %d\n",iFont);
    #endif
    nHeight=-MulDiv(iFont, iDpi, 72.0);  // Petzold's Formula I Believe, Also In MSDN Docs On CreateFont().
    #ifdef Debug
    fprintf(fp,"    nHeight           = %d\n",nHeight);
    #endif   
    hFont=CreateFont(nHeight,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,0,0,0,0,L"Tahoma");     
    hTmp=(HFONT)SelectObject(hDC,hFont);  // Select Into Device Context and....
    GetTextMetrics(hDC,&tm);              // ...Measure With TextMetrics().
    #ifdef Debug
    fprintf(fp,"    hTmp              = %p\n",hTmp);
    fprintf(fp,"    tm.tmHeight       = %d\n",tm.tmHeight);
    #endif
    iDiff=rc.bottom-tm.tmHeight;          // See How Big A Difference Between Size Of Edit Control And Returned Font Height
    #ifdef Debug                          // Close Enough - So We'' Use This Font.
    fprintf(fp,"    iDiff             = %d\n",iDiff);
    #endif
    if(iDiff<=1)
    {
       #ifdef Debug
       fprintf(fp,"    Got In Where iDiff <=0!!!\n");
       fprintf(fp,"    hFont             = %p\n",hFont);
       fprintf(fp,"    hTmp              = %p\n",hTmp);
       #endif
       SetWindowLongPtr(Wea.hWnd,GWLP_USERDATA,(LONG_PTR)hFont); // Store This HFONT For Use In Application
       SelectObject(hDC,hTmp);                                   // Restore Stock HFONT Back In Device Context
       #ifdef Debug                                                             
       fprintf(fp,"  Leaving FindFont()\n\n");                     
       #endif
       break;  // Exit Loop. We've Fonnd an HFONT That Closely Matches Client Rectangle Of Edit Control. 
    }                                                            
    else
    {  
       DeleteObject(SelectObject(hDC,hTmp));                     // Delete Created HFONT -- It Isn't Suitable   
       iFont=iFont+1;                                            // Increase Font Size A Little Bit
    }   
 }while(true);
 ReleaseDC(Wea.hWnd,hDC);
 
 return hFont;	
}

 
void SizeWindows(HWND hWnd, RECT* pRect, int& iDpi)
{
 HFONT hFont = NULL;
 HWND  hCtl  = 0;
  
 #ifdef Debug
 fprintf(fp,"  Entering SizeWindows()\n");
 fprintf(fp,"    iDpi          = %d\n",iDpi);
 fprintf(fp,"    Siz(10)       = %d\n",Siz(10));
 fprintf(fp,"    pRect->left   = %d\n",pRect->left);
 fprintf(fp,"    pRect->top    = %d\n",pRect->top);
 fprintf(fp,"    pRect->right  = %d\n",pRect->right);
 fprintf(fp,"    pRect->bottom = %d\n",pRect->bottom);
 int iWidth  = pRect->right  - pRect->left;
 int iHeight = pRect->bottom - pRect->top;
 fprintf(fp,"    iWidth        = %d\n",iWidth);
 fprintf(fp,"    iHeight       = %d\n",iHeight);
 #endif
 MoveWindow(hWnd,pRect->left,pRect->top,pRect->right-pRect->left,pRect->bottom-pRect->top,TRUE); // Use RECT* Sent In
 hFont=(HFONT)GetWindowLongPtr(hWnd,GWLP_USERDATA);       // Get Stored HFONT                    // From WM_DPICHANGED
 hCtl=GetDlgItem(hWnd,IDC_lblUserName);                   // Get HWND lblUserName                // Message, And Adjust
 MoveWindow(hCtl,Siz(10),Siz(12),Siz(90),Siz(16),TRUE);   // Move lblUserName                    // Main Window Position
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);            // Set Corrected Font                  // And Size, If Needed.
 SetWindowText(hCtl,L"User Name");                        // Reset Text
 hCtl=GetDlgItem(hWnd,IDC_txtUserName);                   // Get HWND txtUserName
 MoveWindow(hCtl,Siz(110),Siz(10),Siz(160),Siz(20),TRUE); // Move txtUserName
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);            // Set Corrected Font
 hCtl=GetDlgItem(hWnd,IDC_lblPassWord);                   // Get HWND lblPassWord
 MoveWindow(hCtl,Siz(10),Siz(36),Siz(90),Siz(16),TRUE);   // Move lblPassWord
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);            // Set Corrected Font
 SetWindowText(hCtl,L"Password");                         // Reset Text
 hCtl=GetDlgItem(hWnd,IDC_txtPassWord);                   // Get HWND txtPassWord
 MoveWindow(hCtl,Siz(110),Siz(34),Siz(160),Siz(20),TRUE); // Move txtPassWord
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);            // Set Corrected Font
 hCtl=GetDlgItem(hWnd,IDC_btnSubmit);                     // Get HWND btnSubmit
 MoveWindow(hCtl,Siz(120),Siz(60),Siz(60),Siz(20),TRUE);  // Move btnSubmit
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);            // Set Corrected Font
 SetWindowText(hCtl,L"Submit");                           // Reset Text
 hCtl=GetDlgItem(hWnd,IDC_btnCancel);                     // Get HWND btnCancel
 MoveWindow(hCtl,Siz(200),Siz(60),Siz(60),Siz(20),TRUE);  // Move btnCancel
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);            // Set Corrected Font
 SetWindowText(hCtl,L"Cancel");                           // Reset Text
 #ifdef Debug
 fprintf(fp,"  Leaving SizeWindows()\n");
 #endif
 
 return;
}


continued....
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
LRESULT fnWndProc_OnCreate(WndEventArgs& Wea)
{
 int        iDpi        = 0;
 BOOL       blnDpiAware = FALSE;          
 HWND       hCtl        = NULL;
 HFONT      hFont       = NULL;
 RECT       rc;
 
 #ifdef Debug
 fp=fopen("Output.txt","w");
 fprintf(fp,"Entering fnWndProc_OnCreate()\n");
 fprintf(fp,"  Wea.hWnd      = %p\n",Wea.hWnd);
 #endif 
 Wea.hIns    = ((LPCREATESTRUCT)Wea.lParam)->hInstance;
 blnDpiAware = IsProcessDPIAware();
 #ifdef Debug
 fprintf(fp,"  blnDpiAware   = %d\n",blnDpiAware);
 #endif
 iDpi        = GetDpiForWindow(Wea.hWnd); 
 #ifdef Debug
 fprintf(fp,"  iDpi          = %d\n",iDpi);  
 fprintf(fp,"  Siz(10)       = %d\n\n",Siz(10));
 #endif
 hFont=FindFont(Wea, iDpi); // Find Font That Works For This DPI (FindFont() 1st Proc Above)
 #ifdef Debug
 fprintf(fp,"  hFont         = %p\n",hFont);
 #endif
 // Create Child Window Controls And Set Font
 hCtl=CreateWindowEx(0,L"static",L"User Name",WS_CHILD|WS_VISIBLE|SS_RIGHT,0,0,0,0,Wea.hWnd,(HMENU)IDC_lblUserName,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(WS_EX_CLIENTEDGE,L"edit",L"",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_txtUserName,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(0,L"static",L"Password",WS_CHILD|WS_VISIBLE|SS_RIGHT,0,0,0,0,Wea.hWnd,(HMENU)IDC_lblPassWord,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(WS_EX_CLIENTEDGE,L"edit",L"",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_txtPassWord,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(0,L"button",L"Submit",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_btnSubmit,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 hCtl=CreateWindowEx(0,L"button",L"Cancel",WS_CHILD|WS_VISIBLE|WS_TABSTOP,0,0,0,0,Wea.hWnd,(HMENU)IDC_btnCancel,Wea.hIns,0);
 SendMessage(hCtl,WM_SETFONT,(WPARAM)hFont,0);
 rc.left=Siz(200), rc.top=Siz(100), rc.right=Siz(500), rc.bottom=Siz(224); // Have To Set Size Of Main Window Somewhere!
 #ifdef Debug
 int iWidth  = rc.right  - rc.left;
 int iHeight = rc.bottom - rc.top;
 fprintf(fp,"  iWidth        = %d\n",iWidth);
 fprintf(fp,"  iHeight       = %d\n\n",iHeight);
 #endif 
 SizeWindows(Wea.hWnd, &rc, iDpi); 
 #ifdef Debug
 fprintf(fp,"Leaving fnWndProc_OnCreate()\n\n");
 #endif 
 
 return 0;
}


LRESULT btnSubmit_Click(WndEventArgs& Wea)
{
 int    iDpi    = 0;
 int    iWidth  = 0;
 int    iHeight = 0;
 bool   bRet    = false;
 RECT   rc;
 
 #ifdef Debug
 fprintf(fp,"Entering btnSubmit_Click()\n");
 fprintf(fp,"  Wea.hWnd      = %p\n",Wea.hWnd);
 #endif
 bRet=GetWindowRect(Wea.hWnd,&rc);
 iWidth  = rc.right  - rc.left;
 iHeight = rc.bottom - rc.top;
 iDpi  = GetDpiForWindow(Wea.hWnd); 
 #ifdef Debug
 fprintf(fp,"  bRet          = %d\n",bRet);
 fprintf(fp,"  iDpi          = %d\n",iDpi);
 fprintf(fp,"  Siz(10)       = %d\n",Siz(1.0));
 fprintf(fp,"  iWidth        = %d\n",iWidth);
 fprintf(fp,"  iHeight       = %d\n",iHeight);
 #endif 
 MessageBox(Wea.hWnd,L"You Clicked The Submit Button",L"Button Click Report",MB_OK);
 #ifdef Debug
 fprintf(fp,"Leaving btnSubmit_Click()\n\n");
 #endif 
 
 return 0;
}


LRESULT btnCancel_Click(WndEventArgs& Wea)
{
 DestroyWindow(Wea.hWnd);
 return 0;
} 


LRESULT fnWndProc_OnCommand(WndEventArgs& Wea)
{
 switch(LOWORD(Wea.wParam))
 {
   case IDC_btnSubmit:
     return btnSubmit_Click(Wea);
   case IDC_btnCancel:
     return btnCancel_Click(Wea);
 } 
 
 return DefWindowProc(Wea.hWnd, WM_CTLCOLOREDIT, Wea.wParam, Wea.lParam); 
}	


LRESULT fnWndProc_OnDpiChanged(WndEventArgs& Wea)
{
 int    iDpi    = 0;
 int    iWidth  = 0;
 int    iHeight = 0;
 RECT*  pRect   = NULL;
  
 #ifdef Debug
 fprintf(fp,"Entering fnWndProc_OnDpiChanged()\n");
 fprintf(fp,"  Wea.hWnd      = %p\n",Wea.hWnd);
 #endif 
 iDpi=LOWORD(Wea.wParam);  // Suggested Sizes For Things Windows Sends In Via
 pRect=(RECT*)Wea.lParam;  // WPARAM and LPARAM.
 iWidth  = pRect->right  - pRect->left;
 iHeight = pRect->bottom - pRect->top;
 #ifdef Debug
 fprintf(fp,"  iDpi          = %d\n",iDpi);
 fprintf(fp,"  Siz(10)       = %d\n",Siz(10));
 fprintf(fp,"  pRect->left   = %d\n",pRect->left);
 fprintf(fp,"  pRect->top    = %d\n",pRect->top);
 fprintf(fp,"  pRect->right  = %d\n",pRect->right);
 fprintf(fp,"  pRect->bottom = %d\n",pRect->bottom);
 fprintf(fp,"  iWidth        = %d\n",iWidth);
 fprintf(fp,"  iHeight       = %d\n",iHeight);
 #endif
 FindFont(Wea, iDpi);              // See FindFont() And SizeWindows()
 SizeWindows(Wea.hWnd,pRect,iDpi); // In This App.
 #ifdef Debug
 fprintf(fp,"Leaving fnWndProc_OnDpiChanged()\n\n");
 #endif
 
 return 0;
}

LRESULT fnWndProc_OnDestroy(WndEventArgs& Wea)
{
 HFONT hFont = NULL;
 
 #ifdef Debug
 fprintf(fp,"Entering fnWndProc_OnDestroy()\n");
 fprintf(fp,"  Wea.hWnd      = %p\n",Wea.hWnd);
 #endif 
 hFont = (HFONT)GetWindowLongPtr(Wea.hWnd,GWLP_USERDATA);
 DeleteObject(hFont);
 PostQuitMessage(0);
 #ifdef Debug
 fprintf(fp,"  hFont         = %p\n",hFont);
 fprintf(fp,"Leaving fnWndProc_OnDestroy()\n");
 fclose(fp);
 #endif
 
 return 0;
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(size_t i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI wWinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPTSTR lpszArgument, int iShow)
{
 wchar_t szClassName[]=L"NewDpi5";
 MSG messages;
 WNDCLASS wc;
 HWND hWnd;
 
 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); // Needs To Be Called Before
 memset(&wc,0,sizeof(WNDCLASS));                                            // Any Window Creation!
 wc.lpszClassName = szClassName,                     wc.lpfnWndProc   = fnWndProc;
 wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION),  wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 
 wc.hInstance     = hIns,                            wc.hCursor       = LoadCursor(NULL,IDC_ARROW),          
 RegisterClass(&wc);
 hWnd=CreateWindow(szClassName,L"DpiAware V2",WS_OVERLAPPEDWINDOW,0,0,0,0,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    if(!IsDialogMessage(hWnd,&messages))
    { 
       TranslateMessage(&messages);
       DispatchMessage(&messages);
    }   
 }

 return (int)messages.wParam;
}


continued....
...and NewDpi5.h....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//NewDpi5.h
#ifndef NewDpi5_h
#define NewDpi5_h

#define dim(x)                    (sizeof(x) / sizeof(x[0]))
#define Siz(z)                    (int)(z * iDpi/96.0)

#define IDC_lblUserName           2000
#define IDC_lblPassWord           2005
#define IDC_txtUserName           2010
#define IDC_txtPassWord           2015
#define IDC_btnSubmit             2020
#define IDC_btnCancel             2025
#define IDC_TEST                  9999

#ifdef TCLib
   extern "C" int                 _fltused=1;
#endif
   
struct WndEventArgs
{
 HWND                             hWnd;
 WPARAM                           wParam;
 LPARAM                           lParam;
 HINSTANCE                        hIns;
};

HFONT   __cdecl                   FindFont(WndEventArgs& Wea, int& iDpi);
void    __cdecl                   SizeWindows(HWND hWnd, RECT* pRect, int& iDpi);
LRESULT __cdecl                   fnWndProc_OnCreate(WndEventArgs& Wea);
LRESULT __cdecl                   btnSubmit_Click(WndEventArgs& Wea);
LRESULT __cdecl                   btnCancel_Click(WndEventArgs& Wea);
LRESULT __cdecl                   fnWndProc_OnCommand(WndEventArgs& Wea);
LRESULT __cdecl                   fnWndProc_OnDpiChanged(WndEventArgs& Wea);
LRESULT __cdecl                   fnWndProc_OnDestroy(WndEventArgs& Wea);
int     __stdcall                 wWinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPTSTR lpszArgument, int iShow);

struct EVENTHANDLER
{
 unsigned int                     iMsg;
 LRESULT                          (*fnPtr)(WndEventArgs&);
};

const EVENTHANDLER                EventHandler[]=
{
 {WM_CREATE,                      fnWndProc_OnCreate},
 {WM_COMMAND,                     fnWndProc_OnCommand},
 {WM_DPICHANGED,                  fnWndProc_OnDpiChanged},
 {WM_DESTROY,                     fnWndProc_OnDestroy}
};
#endif 


I tested your code with mvs 2019, with the 32 bit version it works well. but with the 64 bit we have this warning



Severity Code Description Project File Line Suppression State
Warning C26451 Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2). DpiAware2 D:\Users\WinMain.cpp 42




I changed your code as follows
1
2
3
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)

int     __stdcall                 WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow);


and : maby this is not correct
1
2
3
    do
    {
        nHeight = -MulDiv(iFont, iDpi, 72);


and :
 
#define Siz(z)                    (int)(z * iDpi/96.0) 


i removed all the includes and error stuff from the main file, 2 includes leftover
1
2
#include <Windows.h>
#include "NewDpi6.h" 
Last edited on
Thanks for taking the time to test it John. But I'm not sure which program you are talking about. The two above I named NewDpi5 and NewDpi6. Or are you referring to that 2015 post I linked to above?????
I used NewDpi6.cpp and NewDpi6.h
Just worked on it this morning John and I'm not able to duplicate that warning. I will say that a fault I have is I often post code that has successfully built but with all warnings off. Reason for that is I only do command line compiling and I mostly forget to add the command line switch that turns on warnings, which is /W1, /W2, /W3, or /W4. Geeez, I just looked at the command line compilation strings I posted, and I do see I had /W4 included with NewDpi5 but not NewDpi6. About all I can think to do is build it with the Visual Studio IDE and see if it comes up there.

One thing I did check on though was my use of 96.0 and 72.0 in MulDiv() and Siz(). For some reason I thought I had to do that to overcome a problem I was having with floating point truncations while I was developing the programs. But I just double checked on it and I see I don't need to do that. In fact, the docs on MulDiv show all int parameters and returns.

In terms of the prototype for WinMain(), I believe WINAPI and CALLBACK are both synonyms for __stdcall, which has force in x86 builds, but is defined as nothing in x64 because Windows and the x64 chips it runs on only have one calling convention, and so those stack protocols become superflouis.

The only thing that bothers me about my code and for which I have no explanation is that if I start out in the standard resolution for my laptops and click the submit button after filling in a user name and password, a MessageBox pops up and everything looks fine and crisp - no virtualization, pixel stretching, fuzzy text, or anything. Then, if, while the program is running and still on the screen, if I go into Setting >> Control Panel >> Display and change the fonts to something larger, then reclick the submit button, the MessageBox() comes up, but the text is fuzzy. At least that's how it looks to me. My understanding is that shouldn't be. I thought my code did everything right to prevent that. Are you seeing that?
Pages: 12