Delphi -- exploration des compétences :
{N° 1}
Phrases pour créer des formulaires modaux :
classe PRocedure TMyForm.RunForm(AObj1, AObj2: TObject);
var
vForm : TMonFormulaire ;
commencer
vForm := TMyForm.Create(application);
avec vForm faire
Essayer
InitForm(AObj1, AObj2);
AfficherModal ;
Enfin
Gratuit;
fin;
fin;
//*illustrer:
Les fonctions déclarées via la classe sont similaires aux fonctions statiques dans VC ; utilisez l'instruction : TMyForm.RunForm(vObj1, vObj2);
Pour d'autres informations spécifiques, veuillez vous référer à : description de la classe dans l'aide de Delphi.
Le but de mettre l’accent sur cet idiome est de :
1. Si ce formulaire est utilisé à plusieurs endroits, vous pouvez vous assurer que ce code est appelé de manière uniforme ;
2. Si la fonction est modifiée, par exemple : traitement basé sur la valeur de retour de ShowModal, alors modifiez uniquement cette fonction.
3. Le programme a une bonne encapsulation et est facile à maintenir et à transférer. *//
{N° 2}//Utilisation de la balise
Réponse aux événements des boutons de la barre d'outils du formulaire
procédure TMyForm.RunOperate(ATag: Integer);
commencer
Cas ATag de
1 : MonBouton.Color := clRed ;
2 : MonBouton.Color := clGreen ;
3 : MonBouton.Color := clBlack ;
fin;
fin;
procédure TMyForm.ToolBtnClick(Expéditeur : TObject);
commencer
RunOperate(TControl(Expéditeur).Tag);
fin;
Si vous êtes dans un menu déroulant et devez exécuter des fonctions similaires,
procédure TMyForm.MenuItemClick(Sender: TObject);
commencer
RunOperate(TMenuItem(Expéditeur).Tag);
fin;
//*illustrer:
1. Structure claire
2. Les informations pertinentes sont concentrées, ce qui facilite leur vérification, leur modification et leur maintenance.
3. Améliorer l'adaptabilité et l'évolutivité du programme ; par exemple, si l'exigence n'est pas implémentée dans le bouton de la barre d'outils, mais implémentée dans différents boutons, elle sera facile à modifier.
Suggestion : Chaque catégorie est suivie d'une seule ou de quelques lignes de code. S'il y a beaucoup de code, utilisez plutôt une fonction de processus.
Ce qui est plus intéressant, c’est que j’écris souvent ceci :
Cas btnMyButton.Visible de
{afficher} Vrai : ...
{Ne pas afficher} Faux : ...
fin; *//
{ N°3 }//Pointeur d'événement en paramètre
//Utilisez le pointeur d'événement pour lire les listes, etc.
taper
TDataSetEvent = procédure (DataSet : TDataSet ; AIndex, ACount : Integer) d'Objet ;
//Classes dérivées de TADOQuery
procédure TMyADOQuery.EnumRecord(AWhereStr: String; APro: TDataSetEvent);
commencer
Fermer;
SQL.Effacer ;
SQL.Add('Sélectionner * De la Table1');
si AWhereStr <> '' alors
SQL.Add('Où ' + AWhereStr);
Ouvrir;
Bien que ce ne soit pas Eof Do
commencer
si assigné (APro) alors APro (Self, RecNo, RecordCount);
Suivant;
fin;
Fermer;
fin;
//*illustrer:
Cette méthode provient de la fonction API de Window pour énumérer toutes les fenêtres enfants actuelles, EnumChildWindow
1. Principe : essayez de séparer la lecture des données de l'affichage des données, du traitement des données, etc., tels que : MVC, etc. sont tous destinés à cet effet ;
2. L'évolutivité du programme a été améliorée. Si vous souhaitiez initialement afficher ou traiter une certaine colonne d'informations dans une liste, mais que vous avez ensuite opté pour l'utilisation de ComboBox, lors de la modification du programme, vous n'avez pas besoin de lire la partie lecture des données. , il vous suffit de modifier l'affichage des informations, etc. Pour un autre exemple, vous devez désormais utiliser une barre de progression pour afficher la progression de la lecture lors de la lecture des enregistrements.
*//
{ N° 4 } //Tableau constant
{Dans le n°2, le contenu suivant est implémenté
procédure TMyForm.RunOperate(ATag: Integer);
commencer
Cas ATag de
1 : MonBouton.Color := clRed ;
2 : MonBouton.Color := clGreen ;
3 : MonBouton.Color := clBlack ;
fin;
fin;
}
//Alors il serait idéal de l'implémenter en utilisant un tableau.
procédure TMyForm.RunOperate(ATag: Integer);
const
MonBoutonColorMax := 3;
MyButtonColor : tableau [1..MyButtonColorMax] de TColor = (clRed, clGreen, clBlack) ;
commencer
Cas ATag de
1..MyButtonColorMax : MyButton.Color := MyButtonColor[ATag];
101 : ....
fin;
fin;
//*illustrer:
Pour une utilisation en mode tableau, notez simplement que la limite supérieure ou inférieure du tableau est implémentée à l'aide de constantes, puis essayez d'utiliser cette constante pour la lecture de boucle de tableau lors d'utilisations futures.
*//
{No. 5}Le mécanisme de message réduit les fonctions publiques de classe
//Comment minimiser la définition des fonctions publiques dans un formulaire ;
{Par exemple : si vous souhaitez implémenter un formulaire de liste de propriétés du contrôle de formulaire actuel, lorsque vous devez actualiser le formulaire de propriété ; modifier la valeur d'une certaine propriété ; ajouter de nouvelles propriétés, etc. ; avec lequel il faut interagir. Si nous utilisons des fonctions publiques de classe, nous devons définir de nombreuses fonctions publiques. Dans le même temps, si une conversion du type de formulaire est requise, les fonctions publiques ne peuvent être utilisées qu'après la conversion vers le type de formulaire cible. Par conséquent, il y aura des situations où deux unités devront s'inclure}
//Solution:
TfrmMyForm = classe (TForm)
FfrmProperty : TForm ;
fin;
...
FfrmProperty := TfrmProperty.MyCreate(Application, Self);
...
//Quand la fenêtre des propriétés doit être actualisée
FfrmProperty.Perform(WD_REFRESHPROPERTYLIST, 0, 0);
TfrmProperty = classe (TForm)
privé
FMyFormulaire : TForm ;
procédure WDREFRESHPROPERTYLIST(var Message : TMessage); message WD_REFRESHPROPERTYLIST ;
publique
constructeur MyCreate (Propriétaire : TComponent ; AForm : TForm) ;
fin;
constructeur TfrmProperty.MyCreate (Propriétaire : TComponent ; AForm : TForm) ;
commencer
hérité Create(Propriétaire);
FMyForm := AForm;
fin;
//* Pour la manière d'utiliser les messages, la définition des fonctions publiques du formulaire peut être réduite. En même temps, cela améliore l’évolutivité du programme. Si vous utilisez son formulaire à la place, il peut être converti facilement, car tout au plus c'est votre formulaire et ne traite pas le message en cours*)//
{No. 6}Utiliser la liste d'enregistrement pour gérer les modules d'extension possibles
//Projet : vous devez prendre en charge plusieurs méthodes d'affichage de sortie pour un ensemble de données
...Des exemples seront donnés plus tard
//* illustre :
1. « Méthodes de sortie multiples » signifie que les méthodes de sortie peuvent être fréquemment étendues dans les applications futures, de sorte que la facilité d'évolutivité des méthodes de sortie doit être prise en compte lors de la conception du programme.
2. En vous référant au mécanisme d'enregistrement de contrôle (RegisterComponents) dans VCL, vous pouvez constater qu'un grand nombre de mécanismes d'enregistrement sont utilisés dans VCL ; le plus classique est l'enregistrement de l'éditeur de propriétés de contrôle.
*//
{No.7} Utiliser la version prédéfinie du programme de contrôle
//Si vous réalisez un programme de plate-forme de développement secondaire, vous devez impliquer les problèmes de contrôle de version du produit et de contrôle de version du projet
//Généralement contrôlé à l'aide de méthodes prédéfinies
//L'instruction est relativement simple :
{$DÉFINIR JOYYUAN97}
{$IFDEF JOYYUAN97} {ELSE} {ENDIF}
{$UNDEF JOYYUAN97}
*illustrer:
1. Divisez la prédéfinition en plusieurs fichiers distincts.
2. Au début de chaque unité mais après Unit, utilisez {$I ...} pour inclure le fichier dans l'unité actuelle.
3. Contrôlez les fichiers d'unité que l'unité actuelle peut contenir en fonction de conditions prédéfinies
4. Essayez de séparer un fichier prédéfini pour le projet. Après avoir inclus tous les fichiers prédéfinis, incluez ce fichier dans ce fichier, certains fichiers prédéfinis peuvent être annulés en fonction des besoins du projet.
*//
{No. 8} Utilisez des pointeurs de fonction pour réduire les inclusions de projets d'unités
//Je pense souvent que réduire l'inclusion des unités est la première étape pour rendre les unités publiques, alors comment réduire au maximum l'inclusion des unités
//C'est-à-dire que davantage d'efforts devraient être faits sur la manière de réduire le couplage des unités de programme.
{Description du scénario :
TMyFormManager : classe de gestion de formulaires
TMyForm : classe de base de formulaire de données
TMyFormaccess : classe de sauvegarde et de lecture des informations du formulaire. Enregistrez les informations du formulaire dans une base de données ou dans un autre type de structure
analyser:
1. La classe de base de formulaire (TMyForm) et la classe de gestion de formulaire (TMyFormManager) doivent être implémentées dans une unité uManagers.
2. L'unité fMyImange de classe d'implémentation spécifique au formulaire (TMyImageForm) doit inclure l'unité uManagers pour l'héritage et la gestion des formulaires.
3. L'unité de classe de lecture de données de formulaire (TMyFormAccess) uMyAccess doit inclure l'unité uManagers et l'unité fMyImange.
question:
Si je souhaite enregistrer le formulaire, cela doit être fait dans un événement bouton du formulaire. En ce qui concerne l'unité de formulaire, elle doit contenir l'unité de classe d'accès aux données du formulaire, et si elle est placée dans la classe de base du formulaire, l'unité uManager doit contenir l'unité uMyAccess.
L'inclusion de cellules constitue un danger lorsque l'accès aux données, c'est-à-dire les formats de stockage des données, change en fonction des exigences et nécessite une évolutivité.
Solution : utilisez des variables de pointeur de fonction.
1. Définissez une variable de pointeur de fonction dans les uManagers de l'unité pour enregistrer les informations sur les données.
2. Attribuez une valeur à cette variable de pointeur de fonction lors de l'initialisation de l'application.
3. Lorsqu'il est nécessaire d'enregistrer les informations du formulaire, déterminez si le pointeur n'est pas vide, puis exécutez la fonction pour enregistrer les informations du formulaire.
{Non. 9}Constantes, comprenez les constantes, utilisez les constantes
Il existe de nombreux livres qui présentent l'importance de la définition des constantes, et j'y pense souvent, mais quand je regarde le code source de la VCL, je me rends compte que j'ai ignoré l'utilisation des constantes par d'autres.
1. La définition d’un message que nous utilisons souvent est : déclarer une constante puis l’utiliser au moment opportun.
Couramment défini et utilisé :
const
WD_MonMessage = WM_Utilisateur + 101 ;
taper
TMyForm = classe (TForm)
...
procédure WDMyMessage(var message : TMessage); message WD_MyMessage ; {position du message de réponse}
fin;
Cependant, si vous réécrivez l'instruction {response message position} comme :
procédure WDMyMessage(var message : TMessage); message WM_User + 101;
De même, la compilation peut réussir et l’utilisation est normale. Par conséquent, les définitions constantes sont très couramment utilisées dans le traitement et les interfaces du système Windows.
2. Dans Delphi, nous avons défini des variables de couleur, clRed, clGreen, etc., qui sont également des constantes définies pour faciliter une utilisation future. Grâce à cette observation, j'ai découvert que la définition des constantes devait être partiellement réutilisable dans le projet. Par conséquent, une unité constante standard peut être définie afin que les constantes définies puissent être réutilisées dans chaque projet.
{No. 10}Un tableau couramment utilisé dans Delphi
Il existe une implémentation relativement complète dans Delphi pour la définition et l'utilisation de tableaux de type TIdentMapEntryd.
TIdentMapEntry = enregistrement
Valeur : Entier ;
Nom : chaîne ;
fin;
1. Définition du tableau : array[0..ArrMax] de TIdentMapEntry
Veuillez vous référer à : Unité de commande :
Curseurs : array[0..21] de TIdentMapEntry = (
...
);
2. Deux fonctions qui s'évaluent mutuellement : IntToIdent (trouver le nom à partir de la valeur) et IdentToInt (trouver la valeur à partir du nom) ;
Pour des applications spécifiques, veuillez vous référer à : IdentToCursor et CursorToIdent.
3. Application : a. Appliquer directement cette méthode de définition de groupe d'arbres et cette fonction de manipulation de tableaux. b. c. Apprenez la définition standard de la fonction d'accès aux informations : function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean; Les informations spécifiques renvoyées sont renvoyées par les paramètres. est transmis via la fonction. La valeur de retour booléenne est jugée.
{N°11}Des cas particuliers aux découvertes communes
J'ai découvert en traçant les fonctions de définition et de fonctionnement des curseurs :
1. Comme introduit dans {No. 10}, généralisez la définition et les opérations générales des curseurs.
2. Fournissez des fonctions de conversion entre Int et Ident.
3. Fournit une fonction pour lire cycliquement les informations de la liste de tableaux : GetCursorValues ; parmi elles, la méthode du « pointeur d'événement en tant que paramètre » introduite dans {No.
Supplément au {N° 6} :
exemple:
procédure RegisterComponents(const Page: string;
ComponentClasses : tableau de TComponentClass);
commencer
si assigné (RegisterComponentsProc) alors
RegisterComponentsProc (Page, ComponentClasses)
autre
augmenter EComponentError.CreateRes (@SRegisterError);
fin;
Interprétation:
1. Utilisez la méthode d'enregistrement pour enregistrer les types de contrôles pouvant être utilisés, etc.
3. Pour RegisterComponentsProc, la méthode « d'utilisation de pointeurs de fonction pour réduire l'inclusion de projets unitaires » dans {No. 8} est utilisée pour faciliter l'expansion future du programme, les mises à niveau de version, etc.
{Non 11} Définissez une seule fonction publique
//Description du projet : Nous devons maintenant mettre en œuvre un système de dessin CAO ou Visio, qui nécessite une bonne évolutivité et une maintenance facile ;
//Et cela nécessite un faible couplage, afin que des parties du système ou du système étendu puissent être empaquetées et utilisées directement dans des projets futurs.
conception:
1. Concevez une classe abstraite d'objet graphique. Dans cette classe, définissez une fonction abstraite CadPerform. Les paramètres de la fonction font référence à la fonction TControl.Perform(Msg: Cardinal; WParam: Longint): Longint;
2. Dans la classe de gestion graphique, implémentez la gestion d'une liste d'objets graphiques. Ce qui est stocké dans la liste est le pointeur de l'objet abstrait.
3. Lorsque vous souhaitez contrôler des objets de classe spécifiques, il vous suffit d'utiliser la fonction CanPerform, puis de transmettre Msg en fonction de la catégorie de l'opération en cours, et de transmettre les informations de paramètre correspondantes.
Implémentation : TCad est la classe de contrôle de premier niveau héritée de la classe abstraite
function TCad.CadPerform(Msg : Cardinal ; WParam, LParam : Longint) : Longint ;
commencer
Message de cas de
Mon_Message1 : Résultat := MonMessage1(WParam, LParam);
Mon_Message2 : Résultat := MonMessage2(WParam, LParam);
fin;
fin;
Car TPoint hérite de TCad, la fonction CadPerform est implémentée comme suit.
function TPoint.CadPerform(Msg : Cardinal ; WParam, LParam : Longint) : Longint ;
commencer
Message de cas de
My_Message1: Result := MyMessage1(WParam, LParam); //Le traitement de ce type d'opération dans TCad est bloqué
Mon_Message3 : Résultat := MonMessage3(WParam, LParam);
sinon Résultat := hérité de CadPerform(Msg, WParam, LParam);
fin;
fin;
*illustrer:
Parce que nous utilisons très fréquemment des objets graphiques, nous définissons une fonction d'interface publique et ouverte pour obtenir une encapsulation élevée de la classe et une maintenance et une extension faciles du programme.
*//
{N° 12}
Voici mes exigences de programmation : (Certaines informations n'ont aucune restriction de langue)
//Presque toutes les solutions suivantes peuvent être trouvées dans les méthodes ci-dessus.
1. Réduisez la complexité du programme. a. Réduisez le nombre de fonctions, utilisez les méthodes Case et Tag et apprenez à définir Perform b. Réduisez les relations d'imbrication des unités, utilisez les méthodes de transmission de messages et réduisez l'inclusion mutuelle des unités de formulaire.
2. Réduire
{N° 13} Utilisez la diffusion pour implémenter les notifications des classes de gestion vers les objets de la liste de gestion
//Pour la description du projet {N° 12}, lorsque les propriétés ou l'état du contrôle du formulaire de dessin changent, il est souvent nécessaire de notifier tous les objets graphiques et d'apporter les modifications correspondantes.
//Si une seule fonction de diffusion est définie, une notification parent-enfant peut être réalisée, ce qui améliorera également la réutilisabilité, l'évolutivité, la facilité de maintenance, etc. du programme et clarifiera la structure des classes.
//Par exemple : 1. Dans Visio et MapInfo, si l'échelle (taux de zoom) du formulaire actuel change, tous les objets graphiques actuellement affichés doivent être redessinés avec la nouvelle échelle. 2. Lorsque la police par défaut du formulaire actuel est modifiée, les polices de texte des objets graphiques qui utilisent la police du formulaire par défaut pour afficher les informations textuelles doivent également être modifiées en conséquence.
//Solution, reportez-vous au mécanisme de traitement dans TWinControl qui notifie tous les sous-contrôles lorsque les attributs ou le statut changent :
procédure TWinControl.NotifyControls (Msg : Word);
var
Message : TMessage ;
commencer
Message.Msg := Msg;
Message.WParam := 0;
Message.LParam := 0;
Message.Résultat := 0;
Broadcast(Message);//Diffuser le message de modification en cours
fin;
dans:
procédure TWinControl.Broadcast(var Message);
var
I : Entier ;
commencer
pour I := 0 à ControlCount - 1 faire
commencer
Contrôles[I].WindowProc(TMessage(Message));
// Remplacez par : avec TMessage(Message) do Cads[I].CadPerform(msg, WParam, LParam);
si TMessage(Message).Result <> 0 alors Quittez ;
fin;
fin;
Cependant, lorsque l'on a affaire à des objets graphiques, on peut appeler directement la fonction publique CanPerform de Cads.
{N° 14} Créez vos objets de manière dynamique en cas de besoin
Par exemple : http://www.delphibbs.com/keylife/iblog_show.asp?xid=824
//************Option 2 : Créer un formulaire de propriété si nécessaire
utilise
...
fPropriété ;
taper
TfrmMyMap = classe
...
procédure OnfrmMyMapDestroy(Expéditeur : TObject);
procédure OnMapGeoSelected(AGeo : TGeometry) ;
privé
FfrmProperty : TfrmProperty ;
procédure ShowPropertyForm(aVisible : Booléen);
publique
fin;
procédure TfrmMyMap.ShowPropertyForm(aVisible: Boolean);
commencer
si non attribué (FfrmProperty) alors FfrmProperty := TfrmProperty.Create (Application);
FfrmProperty.Visible := aVisible;
fin;
procédure TfrmMyMap.OnfrmMyMapDestroy(Expéditeur : TObject);
commencer
si attribué (FfrmProperty) alors FfrmProperty.Free ;
fin;
procédure TfrmMyMap.OnMapGeoSelected(AGeo: TGeometry);
commencer
si attribué (FfrmProperty) alors FfrmProperty.MyRefresh (AGeo);
fin;
Ici c'est expliqué :
1. Créez dynamiquement votre objet FfrmProperty en cas de besoin
2. Lorsque l'objet actuel est publié, déterminez la légalité de votre objet, puis libérez l'objet créé dynamiquement.
{Non. 15}Créer une interface ou créer une structure
//Description du projet : Lorsque je développe un contrôle table, si je mets la cellule sur Com, s'il y a trop d'informations dans la table, la vitesse de chargement ne peut pas être garantie, et il y a même une possibilité de crash. La raison pour laquelle j'utilise Com est que le traitement et les informations de chaque cellule puissent être étendus hors de tout contrôle à l'avenir.
Ma solution est la suivante : créer une instance pour chaque contrôle dérivé de Cell et créer dynamiquement plusieurs objets de structure. Enregistrez pour enregistrer les informations de chaque cellule. Si vous devez utiliser la cellule, attribuez le pointeur d'objet de structure au composant Cell, les résultats du test sont. très satisfaisant.
Par conséquent, si vous devez utiliser un grand nombre d'instances d'un Com, essayez de gérer et de maintenir une seule instance, et les données qu'elle contient peuvent être créées et gérées dynamiquement, ce qui aura un bon effet en termes de vitesse.
De plus, essayez de déclarer un pointeur d'interface pMyInterface = ^IMyInterface lors du passage ou de l'utilisation de paramètres, utilisez directement le pointeur d'interface. Cela peut réduire le nombre d'appels à la fonction de comptage _AddInft, etc., et peut également augmenter la vitesse si le. le fonctionnement est ordinaire.