Como configurar um aplicativo para funcionar corretamente em uma máquina com uma configuração de alta DPI (por exemplo, 150%)?
101
Eu criei um aplicativo Winforms simples em C #. Quando executo o aplicativo em uma máquina com altas configurações de DPI (por exemplo, 150%), o aplicativo é ampliado. Por enquanto, tudo bem! Mas, em vez de renderizar as fontes com um tamanho de fonte maior, todos os textos também são ampliados. Isso, claro, leva a um texto muito borrado (em todos os controles, como botões, etc.).
O Windows não deveria se preocupar em renderizar os textos corretamente? Por exemplo, a barra de título do meu aplicativo é renderizada nítida e clara.
Depois de passar de 100% (ou 125% com a caixa de seleção "Escala de DPI no estilo XP" marcada), o Windows assume por padrão o escalonamento de sua IU. Ele faz isso fazendo com que seu aplicativo renderize sua saída em um bitmap e desenhe esse bitmap na tela. O redimensionamento desse bitmap torna o texto inevitavelmente confuso. Um recurso chamado "virtualização de DPI", ele mantém programas antigos utilizáveis em monitores de alta resolução.
Você deve informar explicitamente que você pode lidar com configurações de DPI mais altas adicionando o <dpiAware>elemento ao seu manifesto. A página do MSDN está aqui, mas não está completa, pois está omitindo as configurações do UAC. Projeto + Adicionar Novo Item, escolha "Arquivo de Manifesto do Aplicativo". Edite o texto do manifesto ou copie / cole:
Você também pode selecionar SetProcessDPIAware () em seu método Main (), necessário, por exemplo, se você implantar com ClickOnce:
[STAThread]staticvoidMain(){if(Environment.OSVersion.Version.Major>=6)SetProcessDPIAware();Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Application.Run(newForm1());// Edit as needed}[System.Runtime.InteropServices.DllImport("user32.dll")]privatestaticexternboolSetProcessDPIAware();
ATUALIZAÇÃO, esta necessidade comum é finalmente um pouco mais fácil se você usar o VS2015 Atualização 1 ou superior. O manifesto adicionado já possui a diretiva relevante, basta remover os comentários.
Palavra-chave para pesquisa para que eu possa encontrar este post de volta: dpiAware
Obrigado, sua solução funciona bem. O único problema que resta é que todas as imagens estão em seus tamanhos originais. Acho que terei que encontrar uma maneira de adicionar ícones de "retina" adicionais à minha GUI ...
Boris
@HansPassant Tenho o mesmo problema com fontes borradas e, depois de aplicar esta solução, meus controles não são redimensionados e não cabem. Como fazer os dois funcionarem?
gajo357
2
Para qualquer um que esteja investigando esta loucura do Win8, SetProcessDPIAwareestá obsoleto e também não funciona corretamente (pelo menos não no Win8.1), causando dimensionamento imprevisível em diferentes controles. Eu recomendo fortemente usar a abordagem de manifesto.
Jason Williams
5
Hmya, Windows 8.1 adquiriu DPI por monitor. Eu não sabia que precisava disso.
Hans Passant
1
Se você for usar ClickOnce para implantação, não poderá usar a opção dpiAware no manifesto, use SetProcessDPIAware ().
Matías
17
Os aplicativos podem ser desenvolvidos em dois modos diferentes.
A primeira é declarar que nosso aplicativo não reconhece DPI (não declarar nada será o padrão para isso). Nesse caso, o sistema operacional renderizará nosso aplicativo com os 96 DPI esperados e, em seguida, fará a escala de bitmap que discutimos antes. O resultado será um aplicativo embaçado, mas com um layout correto.
A segunda opção é declarar o aplicativo com reconhecimento de DPI. Nesse caso, o sistema operacional não fará nenhuma escala e permitirá que seu aplicativo seja renderizado de acordo com o DPI original da tela. No caso de um ambiente de DPI por monitor, seu aplicativo será renderizado com o DPI mais alto de todas as telas, então este bitmap será reduzido para o tamanho adequado para cada monitor. O downscaling resulta em uma experiência de visualização melhor do que o upscaling, mas você ainda pode notar alguma imprecisão.
Se quiser evitar isso, você deve declarar sua aplicação como compatível com o DPI do monitor. Em seguida, você deve detectar quando seu aplicativo é arrastado por monitores diferentes e renderizar de acordo com o DPI do atual.
A declaração do reconhecimento de DPI é feita em um arquivo de manifesto.
e se os usuários tiverem uma janela no tamanho restaurado e movê-la de forma que partes dela fiquem em monitores diferentes? precisamos renderizar tudo duas vezes e usar os limites do monitor como caixas delimitadoras? quanto disso é coberto pelas bibliotecas winforms?
Cee McSharpface,
4
Usando o .NET Framework 4.7 e o Windows 10 Creators Update (1703) ou mais recente, você deve fazer o seguinte para configurar o suporte a alto DPI para seu aplicativo Windows Form:
Declare compatibilidade com o Windows 10.
Para fazer isso, adicione o seguinte ao seu manifestarquivo:
Habilite o reconhecimento de DPI por monitor no app.configarquivo.
O Windows Forms apresenta um novo elemento System.Windows.Forms.ApplicationConfigurationSection para oferecer suporte a novos recursos e personalizações adicionados a partir do .NET Framework 4.7. Para aproveitar as vantagens dos novos recursos que oferecem suporte a alta DPI, adicione o seguinte ao arquivo de configuração do seu aplicativo.
Nas versões anteriores do .NET Framework, você usava o manifesto para adicionar suporte a alto DPI. Essa abordagem não é mais recomendada, pois substitui as configurações definidas no arquivo app.config.
Chame o método estático EnableVisualStyles.
Esta deve ser a primeira chamada de método em seu ponto de entrada do aplicativo. Por exemplo:
A vantagem disso é o suporte para cenários de DPI dinâmicos nos quais o usuário altera o DPI ou o fator de escala depois que um aplicativo Windows Forms foi iniciado.
Nenhuma dessas sugestões funcionou para mim, mas, algo aconteceu depois que eu removi o Form.Font = new... do Form.Design.cs, o formulário começou a ser redimensionado corretamente, funciona se a fonte está definida no construtor ou não. Por quê? outra pessoa pode explicar, só posso falar sobre a alteração que fiz e levei alguns minutos para descobrir que era a causa raiz do formulário em que estava trabalhando. Espero que ajude.
SetProcessDPIAware
está obsoleto e também não funciona corretamente (pelo menos não no Win8.1), causando dimensionamento imprevisível em diferentes controles. Eu recomendo fortemente usar a abordagem de manifesto.Os aplicativos podem ser desenvolvidos em dois modos diferentes.
A primeira é declarar que nosso aplicativo não reconhece DPI (não declarar nada será o padrão para isso). Nesse caso, o sistema operacional renderizará nosso aplicativo com os 96 DPI esperados e, em seguida, fará a escala de bitmap que discutimos antes. O resultado será um aplicativo embaçado, mas com um layout correto.
A segunda opção é declarar o aplicativo com reconhecimento de DPI. Nesse caso, o sistema operacional não fará nenhuma escala e permitirá que seu aplicativo seja renderizado de acordo com o DPI original da tela. No caso de um ambiente de DPI por monitor, seu aplicativo será renderizado com o DPI mais alto de todas as telas, então este bitmap será reduzido para o tamanho adequado para cada monitor. O downscaling resulta em uma experiência de visualização melhor do que o upscaling, mas você ainda pode notar alguma imprecisão.
Se quiser evitar isso, você deve declarar sua aplicação como compatível com o DPI do monitor. Em seguida, você deve detectar quando seu aplicativo é arrastado por monitores diferentes e renderizar de acordo com o DPI do atual.
A declaração do reconhecimento de DPI é feita em um arquivo de manifesto.
consulte o seguinte link stackoverflow
fonte
Usando o .NET Framework 4.7 e o Windows 10 Creators Update (1703) ou mais recente, você deve fazer o seguinte para configurar o suporte a alto DPI para seu aplicativo Windows Form:
Declare compatibilidade com o Windows 10.
Para fazer isso, adicione o seguinte ao seu
manifest
arquivo:Habilite o reconhecimento de DPI por monitor no
app.config
arquivo.O Windows Forms apresenta um novo elemento System.Windows.Forms.ApplicationConfigurationSection para oferecer suporte a novos recursos e personalizações adicionados a partir do .NET Framework 4.7. Para aproveitar as vantagens dos novos recursos que oferecem suporte a alta DPI, adicione o seguinte ao arquivo de configuração do seu aplicativo.
Importante
Nas versões anteriores do .NET Framework, você usava o manifesto para adicionar suporte a alto DPI. Essa abordagem não é mais recomendada, pois substitui as configurações definidas no arquivo app.config.
Chame o método estático EnableVisualStyles.
Esta deve ser a primeira chamada de método em seu ponto de entrada do aplicativo. Por exemplo:
A vantagem disso é o suporte para cenários de DPI dinâmicos nos quais o usuário altera o DPI ou o fator de escala depois que um aplicativo Windows Forms foi iniciado.
Fonte: Suporte a alta DPI em Windows Forms
fonte
Nenhuma dessas sugestões funcionou para mim, mas, algo aconteceu depois que eu removi o
Form.Font = new
... doForm.Design.cs
, o formulário começou a ser redimensionado corretamente, funciona se a fonte está definida no construtor ou não. Por quê? outra pessoa pode explicar, só posso falar sobre a alteração que fiz e levei alguns minutos para descobrir que era a causa raiz do formulário em que estava trabalhando. Espero que ajude.fonte
Desde pelo menos o Visual Studio 2017, você só precisa adicionar um arquivo de manifesto e descomentar esta seção:
fonte