O suporte a múltiplos monitores com diferentes resoluções nas aplicações Windows, incluindo aquelas feitas com a VCL, costuma ser muito complexo. Um dos problemas enfrentados no passado foi o de obter o tamanho dos elementos da plataforma usando APIs de Windows tal como a GetSystemMetrics, a qual só retorna informações a respeito do monitor principal. Por isso era difícil, por exemplo, ter uma barra de rolagem personalizada com um tamanho específico em um monitor secundário executando uma resolução diferente da do monitor principal.
A Microsoft introduziu novas APIs no Windows 10 para simplificar este trabalho, como a nova GetSystemMetricsForDPI no Windows 10 Creator's Update (build 1703). A VCL faz uso extensivo desta API, entretanto não é possível apenas usar a nova chamada pois se corre o risco de quebrar a compatibilidade com o Windows 7 e até mesmo versões mais antigas do Windows 10. A solução, portanto, precisou de algumas manobras adicionais.
Primeiramente foi adicionada uma nova função global na unit VCL.Classes chamada GetSystemMetricsForWindow. Ela empacota a chamada a nova GetSystemMetricsForDPI se disponível, ou a tradicional GetSystemMetrics caso contrário. A nova função tem um parâmetro adicional onde se informa um handle, o qual é passado para a API e que serve para indicar o handle da janela na qual se está interessado (e indiretamente a informação sobre o monitor no qual ela está sendo exibida).
Em segundo lugar, a fim de simplificar o trabalho necessário para atualizar o código VCL existente (a biblioteca VCL propriamente dita e seus componentes ou códigos de aplicação personalizados), foi adicionado um novo método em TControl chamado GetSystemMetrics. Ele é compatível em termos de parâmetros com a nova API do Windows de mesmo nome, por isso chamadas existentes para a API em seus componentes será redirecionada para o método, que por sua vez chama GetSystemMetricsForWindow passando o handle do pai do controle como parâmetro. Desta forma, boa parte do código existente será "migrado" sem qualquer esforço! Por fim, foi adicionada a propriedade somente leitura CurrentPPI à classe TControl, que tem por objetivo obter o DPI do controle, dependendo do monitor onde ele está sendo exibido.
Como um exemplo de uso, eu criei uma aplicação VCL simples com o seguinte código no evento OnClick de um botão:
Note que este código é correto mesmo em versões anteriores do Delphi, pois ele invocava a função de API do Windows diretamente. Agora a chamada a GetSystemMetrics é redirecionada, incrementada com o handle do form e retorna o seu resultado de acordo com um monitor específico, porque no fim das contas ela usa a nova função de API do Windows (GetSystemMetricsForDPI). Eu incluí o mesmo código no evento OnCreate do form, atualizando outro label com o padrão para meu monitor principal, que tem resolução mais alta (barra de rolagem com 34 pixels de largura). Após mover o form para meu monitor secundário, que tem resolução mais baixa (no qual as barras de rolagem tem 17 pixels de largura), você verá que o resultado da mesma chamada muda:
Além desta mudança principal, foram feitas atualizações significativas à VCL e seu suporte a temas e estilos, adotando o novo modelo Per Monitor v2 e recomendamos que os desenvolvedores de componentes façam o mesmo a fim de dar suporte a este novo modelo de DPI da Microsoft. Em muitos casos, tudo que precisa ser feito é deixar o código como está. Algumas das métricas são independentes de monitor ou dependentes exclusivamente do monitor principal e, neste caso, talvez você queira forçar uma chamada direta a API do Windows, bastando para isso prefixar a chamada com a unit Windows, por exemplo, Windows.GetSystemMetrics(SM_xxx). Além disso, caso você utilize esta função a partir de um TDataModule, função global ou qualquer classe que não herde de TControl, talvez seja necessário reescrever seu código.
Nós também facilitamos a ativação deste recurso no manifesto da aplicação ao adicioná-lo as opções de projeto na IDE, como pode ser visto a seguir. Para novos projetos VCL, este é o padrão:
Para finalizar, existe uma ressalva: O modelo Per Monitor v2 (tal como muitos outros recursos "High-DPI" do Windows) não dá suporte a janelas MDI Child. A Microsoft parou de considerar erros relatados para o moedlo MDI e nós recomendamos uma migração para um modelo multi-janelas diferente (múltiplas janelas flutuantes, painéis de encaixe, janelas com guias, etc.)
1
O texto não é uma tradução "um para um". Palavras foram substituídas, removidas ou adicionadas a fim de garantir o pleno entendimento do texto por leitores lusófonos