I have an MFC MDI application written in C and C++. A C DLL creates a 24-bit DIB image that contains graphics and text. The size of the text matters a lot so the text fits in tight spaces in the image.
I cannot change the application from using MFC or change the image format.
Everything works fine in most situations, however, my 17-inch workstation laptop screen is 3840 pixels by 2160 pixels, and is set to use 250% scaling, which is recommended by the computer manufacturer. Because of that, the DrawText method creates text that is way too large.
If I right click on the executable, I can change the application DPI scaling, however, then it looks terrible. It looks much worse than when I set my screen resolution to be 1920 by 1080. I don't want to do either of those things.
I don't want to use Windows controls or APIs to change the monitor scaling for the application, because that makes the application look terrible, and the nature of the application requires as much screen precision as possible. Mouse movements can track image locations closely, and anything that hurts the precision makes the application worse. It will work at relatively low screen resolutions, but the higher the screen resolution, the better.
In my application, I create a memory device context for a DIB image.
CClientDC dc(this);
m_memory_device_context.CreateCompatibleDC(&dc);
I create a DIB section that is selected into the memory device context, and I copy the image bits into the DIB before using BitBlt to send the image to the screen. I use the MFC CDC class BitBlt method for that using the client windows device context obtained by using.
CClientDC dc(this);
All of that works. I don't expect to have to change any of that. That just copies the 24-bit DIB image that is created. The problem is that the text is too large in the DIB image.
If I use CreateFontIndirect to create the font I select, the font is always 2.5 (250%) larger than I want. I understand why it's too large. I want to make it smaller. I also can't just choose a smaller font point size either. That would be too small to work.
Oddly, if I use GetStockObject(SYSTEM_FONT) to create the font, then the font is still too large, unless I change the size of the window, which causes an OnSize method, which uses MoveWindow to resize my contained image instance. Then the font becomes the size I want, as if the device context was rendering at the normal 96 DPI. However, if anything refreshes the client area of my view that doesn't resize it, then the text is always too large.
I've tried to change the device context scaling using some Windows APIs, but that didn't change the text size. I really don't want to change the resolution of my application, and I must use the 24-bit DIB, for other reasons I can't go into here.
Essentially I want to get a device context to that renders text to the image at 96 DPI. After that, I'm all set.
I've tried creating my own window using GetModuleName, GetModuleHandle, RegisterClassEx, and CreateWindowEx to create a window the size of the image, and used GetDC with the window handle to create a device context, and I can selected the bitmap handle created by CreateDIBSection into that, but DrawText fails when using that device context. The error is zero, and the error code indicated a bad argument, which I suspect means a bad device context.
So, how do I get a device context that render to the image at 96 DPI.
The code is extremely large, even the pared-down example, and that example runs as a console application in a command window, and that always creates small text, i.e. unscaled text that's the size I want. I haven't yet tried to make my Window class name by "ConsoleWindowClass", although I'm not sure if that's a reserved Microsoft class or not, or whether the will work.
I've worked on this issue for about two weeks. I'm sure there's a way to solve this, particularly since it's solved temporarily when I use a stock font and resize the window. I haven't yet tried calling MoveWindow twice to resize the window before rendering the image, however, that seems like a wrong solution even if it works. Something in the OnSize method is causing this to work.
Thank you for reading this. The issue is driving me crazy as I'm so close to having this work, and this is stopping me. I really don't want the delay of having to obtain an open-source font and write a function to draw text for this special case. That would be a lot of work, and is probably the wrong thing to do.