Un moyen universel de personnaliser l'apparence d'une application WinForms (en utilisant l'exemple de FAQ.Net)

Présentation


Après avoir publié le premier article sur mon application FAQ.Net (programme de notes Windows) , les premiers utilisateurs sont apparus qui souhaitent développer davantage leur programme de notes.

Pour augmenter l'intérêt des utilisateurs, une idée est venue d'augmenter son attractivité en ajustant la couleur et la police.

Conditions requises pour personnaliser l'apparence de l'application


  1. stocker et charger les propriétés de composants individuels dans un fichier XML
  2. l'utilisateur doit disposer d'un outil simple pour personnaliser l'apparence
  3. la liste des composants personnalisés doit se développer très simplement (en une seule ligne de code)
  4. lors de la modification de la valeur d'une propriété, l'utilisateur doit immédiatement voir les modifications sur le formulaire
  5. il devrait y avoir un bouton d'annulation qui vous permettra d'annuler toutes les modifications

Résultat du travail


Fenêtre d'apparence:



Avant et après les paramètres d'apparence:



Pour résoudre le problème, il est nécessaire


  1. utiliser le composant PropertyGridEx pour afficher et modifier les propriétés du composant
  2. créer une classe CustomDesignControl pour la commodité de stocker des propriétés en XML
  3. créer un formulaire MainForm, sur lequel nous allons changer l'apparence
  4. créer un formulaire AppSettingsForm, sur lequel nous allons personnaliser l'apparence de MainForm
  5. créer la classe SettingsXml pour faciliter le travail avec XML

La fonction d'annuler les changements d'apparence


Pour mettre en œuvre la suppression des changements d'apparence (article 5 des exigences), j'ai décidé de trouver un moyen universel de cloner les propriétés des composants qui seront créés en mémoire et de remplacer les composants affichés.

Clonage d'objets:

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; } 

J'ai copié le code, supprimé les propriétés inutiles qui n'ont pas besoin d'être enregistrées, laissant les couleurs et la police.
Après vérification du code, les lacunes de cette méthode ont été immédiatement révélées:

  1. la conversion de n'importe quel contrôle dans la classe Control est utilisée, ce qui signifie que la moitié des propriétés peuvent être perdues (par exemple, le composant DataGridView est hérité de la classe Control, mais possède son propre ensemble supplémentaire de propriétés)
  2. lors du clonage d'un composant, certaines propriétés (par exemple: la couleur de police à l'intérieur de la cellule DataGridView) ne sont pas clonées, mais créent des liens vers le composant cloné (peut-être parce que la propriété est utilisée avec ses propriétés internes et doit être gérée différemment).

Il a commencé à expérimenter sur le deuxième paragraphe, afin de réaliser précisément le clonage de la propriété.
Pour ce faire, créez un objet du type souhaité avec le nouvel opérateur.

 DataGridView dgvClone = new DataGridView(); 

En vain, le composant n'a pas pu annuler les modifications.

J'ai ensuite essayé de créer la propriété elle-même avec le nouvel opérateur et de lui attribuer la valeur à l'aide de la méthode SetValue:

 propInfo.SetValue(_controls[i], propInfo.GetValue(_controlsBeforeChange[i], null), null); 

Et cette méthode n'a pas donné de résultat. Lorsqu'une valeur de propriété change dans un composant, elle est automatiquement mise à jour dans le composant cloné.

Je n'ai plus recherché d'autres méthodes et j'ai effectué le changement en redémarrant simplement l'application avec la possibilité d'enregistrer le document de travail ou d'annuler le redémarrage. Cela a permis d'économiser considérablement la mémoire de l'application, car il n'est pas nécessaire de créer des clones d'objets.

Exemple d'application avec personnalisation de l'apparence


Au cas où, j'ai préparé un code prêt à l'emploi sur lequel tout le monde peut vérifier et éventuellement affiner la fonction d'annulation des changements d'apparence sans redémarrer l'application et nous faire part du problème dans les commentaires.
Il est nécessaire de s'assurer que lorsque vous cliquez sur le bouton "AutoTest", le composant DataGridView a un arrière-plan gris et la police des cellules est petite.



Téléchargez l'application Windows FAQ.Net (gratuite):

(x64) yadi.sk/d/sq3g4NOD3Zt7ZY
(x86) yadi.sk/d/NKXeyUWH3Zt8PQ

Groupe VK
Code source FAQ.Net

Conclusion


J'espère que dans de nombreuses applications WinForms, grâce à cet article, l'utilisateur final aura la possibilité de personnaliser l'interface à son goût et sa couleur.

Source: https://habr.com/ru/post/fr474104/


All Articles