1. Introdução
Depois de postar o primeiro artigo sobre meu aplicativo
FAQ.Net (programa de anotações do Windows) , apareceram os primeiros usuários que gostariam de continuar desenvolvendo seu programa de anotações.
Para aumentar o interesse dos usuários, surgiu uma idéia para aumentar sua atratividade, ajustando a cor e a fonte.
Requisitos para personalizar a aparência do aplicativo
- armazenar e carregar propriedades de componentes individuais em um arquivo XML
- o usuário deve ter uma ferramenta simples para personalizar a aparência
- a lista de componentes personalizados deve se expandir de maneira muito simples (em uma linha de código)
- ao alterar o valor de uma propriedade, o usuário deve ver imediatamente as alterações no formulário
- deve haver um botão de cancelamento que permita reverter todas as alterações
Resultado do trabalho
Janela de aparência:

Antes e depois das configurações de aparência:

Para resolver o problema é necessário
- use o componente PropertyGridEx para exibir e alterar as propriedades do componente
- crie uma classe CustomDesignControl para a conveniência de armazenar propriedades em XML
- crie um formulário MainForm, no qual mudaremos a aparência
- crie um formulário AppSettingsForm, no qual personalizaremos a aparência do MainForm
- crie a classe SettingsXml para conveniência de XML
A função de desfazer alterações na aparência
Para implementar a abolição das alterações na aparência (parágrafo 5 dos requisitos), decidi encontrar uma maneira universal de clonar as propriedades dos componentes que serão criados na memória e substituir os componentes exibidos.
Clonando objetos:
public static class ControlExtensions { public static T Clone<T>(T controlToClone) where T : Control { PropertyInfo[] controlProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); T instance = Activator.CreateInstance<T>(); RichTextBox rtb = new RichTextBox(); foreach (PropertyInfo propInfo in controlProperties) { if (propInfo.Name == "Parent") continue; if (propInfo.CanWrite) { if (propInfo.Name != "WindowTarget") { propInfo.SetValue(instance, propInfo.GetValue(controlToClone, null), null); } } } return instance; }
Copiei o código, removi propriedades desnecessárias que não precisam ser salvas, deixando as cores e a fonte.
Após a verificação do código, as deficiências desse método foram imediatamente reveladas:
- a conversão de qualquer controle para a classe Control é usada, o que significa que metade das propriedades pode ser perdida (por exemplo, o componente DataGridView é herdado da classe Control, mas possui seu próprio conjunto adicional de propriedades)
- ao clonar um componente, algumas propriedades (por exemplo: a cor da fonte na célula DataGridView) não são clonadas, mas criam links para o componente clonado (talvez seja porque a propriedade é usada com suas propriedades internas e precisa ser tratada de maneira diferente).
Ele começou a experimentar no segundo parágrafo, a fim de obter com precisão a clonagem da propriedade.
Para fazer isso, crie um objeto do tipo desejado com o novo operador.
DataGridView dgvClone = new DataGridView();
Sem sucesso, o componente não pôde reverter as alterações.
Tentei criar a propriedade em si com o novo operador e definir o valor usando o método SetValue:
propInfo.SetValue(_controls[i], propInfo.GetValue(_controlsBeforeChange[i], null), null);
E este método não deu resultado. Quando um valor de propriedade é alterado em um componente, ele é atualizado automaticamente no componente clonado.
Não procurei mais outros métodos e retornei a alteração simplesmente reiniciando o aplicativo com a capacidade de salvar o documento de trabalho ou cancelar a reinicialização. Isso permitiu economizar significativamente a memória do aplicativo, pois não é necessário criar clones de objetos.
Exemplo de aplicativo com customização de aparência
Por precaução, preparei um
código pronto para que todos possam verificar e possivelmente modificar a função de cancelar alterações na aparência sem reiniciar o aplicativo e nos informar sobre o problema nos comentários.
É necessário garantir que, ao clicar no botão "Autoteste", o componente DataGridView tenha um plano de fundo cinza e a fonte das células seja pequena.

Faça o download do aplicativo para Windows FAQ.Net (gratuito):
(x64)
yadi.sk/d/sq3g4NOD3Zt7ZY(x86)
yadi.sk/d/NKXeyUWH3Zt8PQGrupo VKCódigo fonte FAQ.NetConclusão
Espero que em muitos aplicativos WinForms, graças a este artigo, o usuário final tenha a oportunidade de personalizar a interface de acordo com seu gosto e cor.