Hello guys, even though this is about windows programing, my problem is actually math in relation to DPI aware program, so I'm posting here rather than in windows programming sub forum.
Currently my window class stores a variable with DIP dimensions which is updated each time the window resizes, moves or when it is initially created ex:
1 2
|
// Holds window dimensions in DIP's (device independent pixels)
RECT DipRect;
|
In addition my class also stores a variable which is a scale representing system setting in windows settings:
1 2
|
// Holds scale (1.0, 1.25, 1.5 or 1.75)
float DpiScale;
|
DpiScale variable is computed on the fly and it thus either, 1, 1.25, 1.50 or 1.75, which depends on setting in windows.
When I get
WM_DPICHANGED
message I use these variables to compute new size and position of a window by multiplying
DipRect
and
DpiScale
, resulting in new size and position of a window.
While this works just fine, I'm not happy with this method because I need to update DIP dimension everywhere in code, but I want to be able to compute DIP size of a window without managing those variables by simply calling just one function to get original window size.
So here is a math problem to achieve this.
Let variable
dim
represents current arbitrary window DPI dimension:
int dim = 100;
And let variable scale represents current scale:
float scale = 1.0;
You get
WM_DPICHANGED
and compute new scale to be 1.25 which means window dimension needs to be increased by 25%, therefore:
1 2 3 4
|
auto new_scale = 1.25;
auto diff = new_scale - scale; // 0.25
dim += (dim * diff) // 100 + 100 * 0.25 = 125
scale += new_scale; // 1.0 + 0.25 = 1.25
|
And we get new dimension of 125 and new scale of 1.25 which is correct.
Now assume you get a new
WM_DPICHANGED
event and new scale is back to 1.0 therefore variable
dim
needs to be scaled down to original value of 100
However, multiplying this same variable by 0.75 will not get us the original dimension of 100:
dim *= 0.75 // 93.75 (but 100 is expected)
Which is incorrect because original value was 100.
1 2 3 4 5
|
auto new_scale = 1.00;
auto diff = new_scale - scale; // 1.0 - 1.25 = -0.25
dim = ? // how do we calculate new dimension here
dim -= (dim * diff) // 125 - 125 * -0.25 = 125 - 31.25 = 93.75 INCORRECT!
scale += new_scale; // 1.25 + (-0.25) = 1.0
|
Computing the
scale
goes fine, however computing
dim
variable to get a dimension at scale is an issue.
So the first question is how to mathematically get original dimension back again?
Note that the formula should be able to give always same result for given scale.
The Window might resize to what ever dimension and we should get a value for given scale regardless of current dimension.