The short answer is: yes.
The long answer, as Vince has already outlined, is that doing it on your own isn’t nearly as simple as it may sound.
if you want to try it on your own, there are two main ways:
- Hack the VCL as Vince has outlined
Because Vince has already talked about hacking the VCL, I will talk about cheating (which is the way I chose when doing this and that was quite successful).
There are two main problems to address with cheating: boilerplate and images.
The boilerplate can be addressed by ensuring you have a base form with all the relevant code and every other form inherits from it. This means you could wind up having to do bulk substitutions, but hey, if you don’t want to upgrade, something has to give…
Images are another story entirely: the big problem is that you have to have a way to encode/decode images for your resolution or you will end up with horrible images that are completely unfit for use in your app.
The only reasonable way forward with this is to use SVG and SVG image lists. There are some components out there that do this, including at least one that is free.
Sorry but there is really no other way unless you’re willing to detect the right size and switch image list which I totally advise against. Bite the bullet and go with SVG, I promise you it’s just that much easier.
So… how does cheating work?
Basically, you have to handle the right windows messages and use a unit called Winapi.Multimon: in there you can find all the good stuff that you need.(GetMonitorInfo etc.) and that you need to use to make your base form right.
The best way to go about this is to create a sample project which includes tons of controls and that you can use as experimental grounds. Every time you make some progress, commit your code.
When you’re done you will have a base form which will scale correctly (you can use the ScaleBy method for that) and where all controls and images display correctly too.
If you’re careful and thoughtful, this will take you around a month-ish to get the vast majority of things right.
Occasionally, you will find that not everything behaves the way it should: time to go back to the playground and fix it that way. Eventually, you will find that all issues have been sorted.
To be sure, you also need a custom manifest telling Windows that your application is DPI-aware otherwise all is for naught.
You must also make sure that you intercept WM_DPICHANGE alongside other messages, please refer to MSDN for the bulk of 'em.
Finally, the first thing you need to do is detect the monitor information and the right proportions, that’s what you will be using for ScaleBy. There are two main ways to go about it:
- Use DPI density and match it against 96: this would be the most common way I think, because it’s also the easiest. 4K monitors and the likes have a much higher DPI density (say like 146) so once you have that you can scale.
- Check against monitor’s X and Y: when using the manifest you can also get the real dimensions and use those. I think that is a much more work-intensive way to do things but it is an option, especially for edge cases which you WILL find, make no mistake.
Please keep in mind that while the whole process may sound easy, it’s a lot of work and depending on your situation could wind up taking weeks or even months. Also, you need to confront the fact that a lot of component suites will already be DPI aware, so you also need to take that into account otherwise you will end up with blown out screens, which is something you definitely don’t want.