Composante de l'écriture, de la partie 3
Cet article est le dernier de trois articles sur les composants. Cette dernière partie permettra de couvrir propriété / éditeurs de composants, comment écrire dédié éditeurs pour votre composant de la propriété, et comment écrire 'caché' des composants.
Cet article est paru initialement dans les Développeur Delphi |
Copyright Pinnacle Publishing, Inc. Tous droits réservés.
Personnalisé Éditeurs de Composants
dès Que nous commençons à écrire avancé types de propriété pour nos composants, la vie devient un peu plus compliqué. Bien que l'inspecteur d'objet intégré à Delphi est capable de reconnaître la plupart des types de propriété, il est impossible pour elle d'être en mesure de faire face avec tout type personnalisé nous pouvons écrire dans nos composants. Parfois, l'inspecteur d'objet est en mesure de faire face à nos types personnalisés, mais l'édition d'un tel arrangement complexe de propriétés dans l'inspecteur d'objet n'est tout simplement pas assez intuitif. C'est à ce point nous pouvons être amenés à écrire propriété / éditeurs de composants. Delphi a de nombreux prédéfinis éditeurs déjà, ces éditeurs sont dans le DsgnIntf.pas de fichier dans le $(Delphi)\Source\ToolsAPI répertoire. Vous aurez besoin de la liste de cette unité dans la clause uses de tout composant de l'éditeur / éditeur de propriétés, vous pouvez écrire, c'est aussi une bonne idée de garder ce fichier ouvert pour référence lors de l'écriture de vos propres éditeurs.
les normes de Codage
Pour commencer, je vais couvrir certaines normes de codage qui sont utilisés lors de l'écriture ou de la propriété des éditeurs. Il y a seulement quelques-uns, mais ce serait une bonne idée de garder à ces normes lors de l'écriture de vos propres éditeurs comme il est plus facile pour d'autres personnes à comprendre votre travail.
- Lors de la création d'un éditeur de propriété, à la fin le nom de votre éditeur de texte avec le mot 'Propriété' par exemple TAngleProperty
- Lors de la création d'un éditeur de composant, fin le nom de votre éditeur de texte avec le mot 'Éditeur' par exemple TPieChartEditor
- Lors de l'écriture des éditeurs, toujours écrire une lettre à l'éditeur dans une unité séparée de votre composante réelle. Il est bon de séparer la conception et de l'exécution du code et, en dehors de cela, il rend votre EXE résultant de taille plus petite (sur certaines versions de Delphi votre composant peut arrêter des applications à partir de la compilation si vous n'avez pas les séparer). Aussi, séparer les paquets de sorte que vos utilisateurs peuvent construire avec les packages d'exécution si ils le veulent bien !
- le Nom de votre rédacteur en chef de l'unité avec le même nom que votre composant de l'unité, mais ajouter le mot 'reg' à la fin par exemple, un composant avec le nom de l'unité 'Moncomposant.pas' dans l'éditeur de nom de fichier étant 'MyComponentreg.pas'
- Enfin, lors de l'écriture d'un éditeur de composant ou de la propriété de l'éditeur pour votre composant, déplacez votre RegisterComponents déclaration de votre composant de l'unité, et dans votre éditeur de composant de l'unité. De cette façon, votre composant ne sera pas enregistrée sans que l'éditeur a également enregistré.
La propriété de l'éditeur
les éditeurs de propriétés sont utilisées par l'IDE pour permettre l'édition spéciale de propriétés individuelles au sein d'un composant. Certains éditeurs sont très simples, d'autres sont beaucoup plus compliqué. Delphi a déjà un certain nombre de normes de propriété des éditeurs, certains de ces facteurs sont:
TIntegerProperty. Utilisée pour la saisie des nombres entiers.
TCharProperty. Utilisée pour la saisie d'un seul caractère.
TEnumProperty. Utilisé pour la sélection d'un élément individuel d'un type énuméré (alTop, alClient etc). TBoolProperty. Utilisé pour la sélection de 'Vrai' ou 'Faux' pour les propriétés Booléennes.
TFloatProperty. Utilisée pour la saisie des nombres à virgule flottante (Variable de type Float / etc. Le type 'Réel' ne doit pas être utilisé pour les propriétés du composant).
TStringProperty. Utilisée pour la saisie des chaînes jusqu'à un maximum de 255 caractères.
TSetProperty. Utilisés pour inclure / exclure des éléments d'un Ensemble de biens. Chaque élément est affiché comme une valeur Booléenne sous-propriété. Réglage de la valeur 'True' comprend l'élément, la valeur 'False' l'exclut.
TClassProperty. C'est la classe de base à descendre à partir de quand vous voulez créer un éditeur personnalisé à être invoquée pour les propriétés d'une certaine classe (quand vous avez une classe en tant que propriété, tels que TImage.Image).
Tous ces éditeurs de propriétés descendre directement ou indirectement de TPropertyEditor. TPropertyEditor a beaucoup de propriétés et de méthodes, les plus importants sont.
fonction AllEqual: Boolean virtual fonction GetAttributes: TPropertyAttributes virtual procédure Edit virtual fonction GetValue: string virtual procédure GetValues(Proc: TGetStrProc) virtual |
AllEqual
Lorsque plusieurs composants sont sélectionnés à l'inspecteur d'objet, les filtres de la liste de ses propriétés à seulement celles que tous les composants sélectionnés ont en commun. Si la valeur de chaque composant pour toute propriété (par exemple, la Largeur est la même, la valeur sera affichée, sinon pas de valeur sera affichée. AllEqual est la routine qui détermine si chaque valeur est identique.
fonction TStringProperty.AllEqual: Boolean var I: Integer V string commencer Result := False si PropCount > 1 puis commencer V := GetStrValue pour I := 1 PropCount - 1 ne si GetStrValueAt(I) <> V puis Quitter fin Résultat := True fin |
Dans l'exemple ci-dessus TStringProperty compare chaque valeur (à l'aide de GetStrValueAt) avec la valeur de la première composante de la liste (à l'aide de GetStrValue, GetStrValueAt(0) en auraient fait de même). La taille de la liste est déterminée en utilisant des PropCount, il renvoie le montant total des composants sélectionnés.
GetAttributes
GetAttributes est appelé par l'IDE quand il a besoin de recueillir des informations sur la propriété de l'éditeur. L'inspecteur d'objets affiche un éditeur approprié sur la base des informations fournies. Le résultat de GetAttributes (TPropertyAttributes) est un ensemble, de sorte qu'il peut contenir une combinaison des valeurs suivantes (cette liste n'est pas exhaustive)
paDialog
Dit l'inspecteur d'objet pour afficher un bouton [...] après le nom de la propriété, lorsque l'utilisateur clique sur ce bouton, la méthode Edit est déclenché.
paSubProperties
Dit l'inspecteur d'objet pour montrer un [ ] bouton développer avant le nom de la propriété, cliquez sur ce bouton pour afficher une liste élargie de sous-propriétés (généralement les propriétés publiées d'une propriété de la classe).
paValueList
L'inspecteur d'objet affichera une liste déroulante avec une liste de valeurs, cette liste est déterminée par l'IDE en appelant la méthode GetValues.
NOTE: La méthode GetValues, pas la méthode GetValue qui est complètement différent
paSortList
Si elle est combinée avec paValueList, les valeurs affichées sont triés par ordre alphabétique.
paMultiSelect
Ceci indique à l'IDE que la propriété est autorisé à afficher lorsque plusieurs composants sont sélectionnés. Cet élément n'est pas présent pour les éditeurs, par exemple un TClassProperty.
paAutoUpdate
les Causes de la méthode SetValue être appelée à chaque fois que la valeur est modifiée dans l'inspecteur d'objet, plutôt que d'attendre que l'utilisateur appuie sur la ou de modifier d'une autre propriété. Il est utilisé pour les 'sous-titre' et 'Texte' propriétés', pour donner un live de la représentation de la valeur de l'utilisateur est d'entrer.
paReadOnly
Si cet élément est inclus dans la valeur dans l'inspecteur d'objet est en lecture seule. Il est généralement utilisé en conjonction avec paDialog. GetValue serait substituée pour renvoyer un descriptif de la représentation de la propriété.
Edit
Cette méthode est appelée lorsque le bouton [...] pour la propriété est cliqué. Ce bouton s'affiche si le paDialog élément est inclus dans le résultat de GetAttributes.
GetValue
Cette méthode est appelée lorsque l'objet de l'inspecteur a besoin de savoir comment faire pour afficher la propriété comme une chaîne de caractères. Ceci est généralement utilisé lorsque [paDialog, paReadOnly] sont précisées dans la suite de GetAttributes.
GetValues
Cette méthode est appelée lorsque l'objet de l'inspecteur des besoins pour récupérer une liste de valeurs à afficher lorsque paValueList est spécifiée dans le résultat de GetAttributes. GetValues passe un paramètre appelé 'Proc' qui est de type TGetStrProc. GetStrProc est déclarée comme TGetStrProc = procédure(const S: string) de l'objet
L'IDE s'attend à 'Proc' pour être appelée une fois pour chaque valeur qui doit être affiché dans l'inspecteur d'objet pour cette propriété.
procédure THintProperty.GetValues(Proc: TGetStrProc) commencer Proc('Premier élément à afficher') Proc('Deuxième élément à afficher') fin |
L'exemple suivant montre comment fournir une liste de valeurs par défaut pour le 'Soupçon' de la propriété de tous les composants, tout en permettant à l'utilisateur d'entrer une valeur dans la liste.
type THintProperty = class(TStringProperty) public fonction GetAttributes: TPropertyAttributes remplacer procédure GetValues(Proc: TGetStrProc) remplacer fin procédure s'Inscrire application procédure Inscrivez-vous commencer RegisterPropertyEditor(TypeInfo(String), nul, 'Astuce' , THintProperty) fin { THintProperty } fonction THintProperty.GetAttributes: TPropertyAttributes commencer Result := hérité GetAttributes [paValueList, paSortList] fin procédure THintProperty.GetValues(Proc: TGetStrProc) commencer Proc('Cette entrée est nécessaire') Proc( 'Appuyez sur F1 pour plus d'informations') Proc('Cette valeur est en lecture seule') fin |
Premier GetAttributes est substituée, et [paValueList, paSortList] sont inclus dans le résultat. Prochaine GetValues est remplacée et trois valeurs sont ajoutées à la liste déroulante en appelant le 'Proc' de la procédure.
Enregistrement de la propriété des éditeurs de
Enfin, l'éditeur de propriété est enregistrée à l'aide RegisterPropertyEditor. RegisterPropertyEditor prend quatre paramètres:
PropertyType: PTypeInfo
Nécessite un pointeur vers une TTypeInfo enregistrement. Cela semble beaucoup plus compliqué qu'il ne l'est vraiment, tout ce que nous devons faire est d'ajouter TypInfo à nos usages de la clause, et l'utilisation de la TypeInfo fonction pour récupérer le pointeur pour nous. TypeInfo(SomeVariableType)
ComponentClass: TClass
C'est la classe de base que cet éditeur doit s'appliquer. L'éditeur de cette classe et des classes qui en descendre. Si nul n'est spécifié, cet éditeur s'appliquent à toute la classe.
const PropertyName: string
Si cet éditeur ne devrait s'appliquer qu'à une propriété spécifique, puis le nom de la propriété doit être spécifié ici. Si l'éditeur doit s'appliquer à tout bien du type spécifié dans PropertyType cette valeur doit être '.
EditorClass: TPropertyEditorClass
C'est la classe qui a été créé pour s'occuper de la propriété. Dans l'exemple ci-dessus, la classe est THintProperty.
à l'Aide de RegisterPropertyEditor incorrectement
Il est important lors de l'utilisation de RegisterPropertyEditor que vous fournir la bonne information. La fourniture de renseignements inexacts qui pourrait vouloir dire que votre éditeur touche incorrecte propriétés (par exemple, Toutes les propriétés de chaîne) ou incorrecte des composants.
À l'autre extrême, le réglage des paramètres de manière incorrecte pourrait signifier que seule une propriété spécifique à un élément spécifique (et descendants) est associée avec votre éditeur de texte. Cela ne semble pas un problème au début, mais descendant composants peuvent souhaiter mettre en œuvre d'autres propriétés du même type. Comme ces propriétés seront, évidemment, ont un nom différent, ils n'auront pas le bon éditeur de propriétés affectées à eux.
Un exemple de mauvaise enregistrés l'éditeur existe déjà au sein de la VCL. L'éditeur standard pour TCollection a été enregistrée pour toutes les classes descendu de TComponent. Le problème est que la plus basse classe capable d'être affichées dans l'inspecteur d'objet est TPersistent (la classe qui TComponent descend d').
Si un composant a une propriété de type TPersistent (qui, par défaut, expose ses sous-propriétés dans la liste extensible), et l'une de ses propriétés est de type TCollection, le résultat est un bouton [...] dans l'inspecteur d'objet qui ne fait rien quand on clique dessus (comme nous l'avons vu dans la partie deux de cette série d'article).
La solution à ce problème semble assez simple. Plutôt que de sous-propriété d'être descendu de TPersistent nous avons pu le descendre de TComponent à la place. Cependant, le comportement par défaut d'une propriété de type TComponent (tel Que déterminé par la propriété de l'éditeur TComponentProperty éditeur) est d'afficher une liste des autres composants, plutôt que de les sous-propriétés d'un composant embarqué.
La solution réelle est vraiment simple, mais seulement si vous savez comment écrire une propriété de l'éditeur.
Etape 1:
type TExpandingRecord = class(TPersistent) |
Devrait être modifié pour se lire
type TExpandingRecord = class(TComponent) |
Etape 2: Créer un éditeur de propriété comme
type TExpandingRecordProperty = class(TClassProperty) public fonction GetAttributes : TPropertyAttributes remplacer fin |
procédure s'Inscrire
application
procédure s'Inscrire
commencer
RegisterComponents('Article', [TExpandingComponent])
RegisterPropertyEditor(TypeInfo(TExpandingRecord), nul, ', TExpandingRecordProperty)
fin
{ TExpandingRecordProperty }
fonction TExpandingRecordProperty.GetAttributes: TPropertyAttributes
commencer
Result := [paReadOnly, paSubProperties]
fin
Étape 3: Supprimer le RegisterComponents appel de la composante de l'unité, et de l'inscrire dans l'éditeur de l'unité. De cette façon, nous pouvons assurer que le composant ne sera pas enregistrée sans le composant.
Maintenant, dans notre propriété de type TExpandingRecord s'affiche comme une expansion de la propriété (à cause de nous retourner paSubProperties de GetAttributes), et l'éditeur par défaut pour TCollection va travailler en tant que propriétaire de la TCollection propriété est un TComponent.
boîte de Dialogue propriété des éditeurs de
la Plupart du temps, lors de la création d'un éditeur de propriétés personnalisées, l'objectif est de fournir une représentation graphique des moyens d'interaction avec la propriété.
Ce premier exemple est un moyen très simple de permettre à l'utilisateur de saisir plusieurs lignes dans la 'Légende' la propriété d'un TLabel. Bien que cet exemple n'est pas très compliqué, il montre comment intégrer un formulaire dans votre éditeur de texte.
Etape 1:
Sélectionnez Fichier, la Nouvelle Application à partir du menu principal. Cela va créer un formulaire, nom de la forme 'fmLabelEdit', ajouter un TMemo à la forme nommée memCaption. Ajoutez deux boutons 'OK' et 'Annuler' avec la ModalResult définir les propriétés de mrOK et mrCancel respectivement.
Etape 2:
Ajouter DsgnIntf et TypInfo à votre clause uses.
Etape 3:
pour Ajouter la propriété suivante de l'éditeur de code de votre appareil.
TCaptionProperty = class(TStringProperty) public fonction GetAttributes: TPropertyAttributes remplacer procédure Edit remplacer fin |
Et registre de la propriété éditeur
procédure s'Inscrire application {$R *.DFM} procédure Inscrivez-vous commencer RegisterPropertyEditor(TypeInfo(TCaption), TLabel, 'Caption', TCaptionProperty) fin |
Étape 4:
Ajoutez le code suivant dans l'ordre de l'inspecteur d'objet pour afficher [...] bouton modifier après le nom de la propriété.
fonction TCaptionProperty.GetAttributes: TPropertyAttributes commencer Result := hérité GetAttributes [paDialog] fin |
Etape 5:
Enfin, nous créons une instance de notre forme de l'éditeur, définir le contenu du mémo pour le courant de la légende, et de montrer ensuite le formulaire modal.
procédure TCaptionProperty.Edit var I: Integer commencer avec TfmLabelEdit.Créer(Application) ne essayer memCaption.Les lignes.Texte := GetStrValue ShowModal {Si la ModalResult de la forme est mrOK, nous devons définir la 'Légende' de la propriété de chaque TLabel.} si ModalResult = mrOK puis pour I:=0 PropCount-1 ne TLabel(GetComponent(I)).Légende := memCaption.Les lignes.Texte enfin fin fin |
Étape 6:
Installer l'unité dans le package, puis essayer le nouvel éditeur !
Avancé de la propriété des éditeurs de
quelqu'un qui n'a jamais utilisé TActionList ou TDataSet (TTable / TQuery) devra posséder de l'expérience de l'exemple suivant, peut-être sans même s'en rendre compte.
Le ActionList éditeur est évidemment un éditeur personnalisé, car il permet de regroupement des actions, tandis que le FieldsEditor de TDataSet peut paraître à première vue comme un standard de l'éditeur, mais sur une inspection plus minutieuse a un menu déroulant avec des articles comme 'Ajouter des champs'. Cependant, la caractéristique la plus remarquable de ces deux éditeurs n'est pas qu'ils sont de dialogue personnalisée éditeurs (semblable à celui que nous avons abordés précédemment), mais le fait que les objets qu'ils créent sont inclus dans la classe principale de la déclaration de l'unité actuelle.
type TForm1 = class(TForm) ActionList1: TActionList Action1: TAction Action2: TAction privé { Private declarations } public { déclarations Publiques } fin |
L'avantage de ceci est que l'IDE est mis au courant de ces éléments, par conséquent, leur permettant d'être sélectionné à partir d'une liste d'objets chaque fois que la propriété d'un composant exige d'eux.
Dans l'illustration ci-dessus, deux actions sont ajoutés à une TActionList, en cliquant sur le bouton 'Action' de la propriété de Button1 montre d'une liste comprenant les actions ajoutées. Les deux actions sont également ajoutés au Formulaire de déclaration de classe, et peut donc être désigné par le nom (Action1, Action2).
Le truc c'est là que réside entièrement dans la propriété de l'éditeur et non pas au sein de la composante. Lorsqu'un éditeur de propriété est déclenchée (c'est à dire le Modifier méthode est appelée), le Concepteur de la propriété contient une référence valide pour une IFormDesigner (TFormDesigner en Delphi 4). De nombreuses fonctions de cette interface ne sont pas dans le champ d'application de cet article, si vous souhaitez en savoir plus sur les fonctionnalités de cette interface, je vous recommande un livre qui s'appelle Delphi Manuel du Développeur par Marco Cantu.
Certaines de ces méthodes incluent
fonction MethodExists(const Nom: string): Boolean procédure RenameMethod(const CurName, NewName: string) procédure SelectComponent(Exemple: TPersistent) procédure ShowMethod(const Nom: string) fonction GetComponent(const Nom: string): TComponent fonction CreateComponent(ComponentClass: TComponentClass Parent: TComponent Gauche, Haut, Largeur, Hauteur: Integer): TComponent |
Certains de ces appels sont assez élémentaires, MethodExists par exemple renvoie True ou False selon si oui ou non une méthode de même nom existe déjà dans la forme de l'unité actuelle (FormCreate, Button1Click etc). ShowMethod de déplacer le curseur sur le nom de la méthode, et RenameMethod va changer le nom d'une méthode.
Les deux méthodes qui sont de l'intérêt à utiliser à ce stade sont les suivantes:
CreateComponent
étant Donné une classe de composant, un parent, pour maintenir le composant, et la position / dimensions, le concepteur va créer une instance de la classe comme si le réalisateur avait choisi à partir de la palette de composants et de l'ajouter à la forme elle-même.
Modifié
Informe le concepteur que quelque chose a été changé (une propriété, etc). Cela modifie l'état de l'appareil de sorte que l'IDE sait, il doit être enregistré avant la fermeture (il permet également le bouton enregistrer dans l'IDE).
Lors de l'ajout d'éléments à notre tableau de tout ce que nous devons faire est d'obtenir TMyProperty.Designer pour créer un composant en notre nom. Cette composante sera ensuite ajouté à la forme et aux biens qui se réfère à une classe de ce type sera automatiquement informé. Dans le cas de TActionList et TDataSet les composants qui sont ajoutés à l'écran ne sont pas visibles au moment de la conception, le propriétaire composant agit comme une sorte de 'manager' pour les composants.
Cours au moment de la conception, vous ne verrez pas un TAction ou un TField composant dans la palette de composants qui seraient éventuellement vous faire penser qu'ils ne sont pas enregistrés, mais l'IDE est encore capable de créer des instances de ces composants (et ils ne sont pas visibles). La réponse n'est pas qu'ils ne sont pas inscrits, ce comportement est un résultat du 'comment' le composant est enregistré.
alors que RegisterComponents permet d'ajouter les composants de la palette de composants, la RegisterNoIcon méthode inscrire votre composant sans l'ajouter à la palette de composants, en vous inscrivant dans cette voie, elle aussi raconte l'IDE que le composant ne doit pas être affiché pendant le moment de la conception.
Dans l'exemple suivant, nous allons créer un composant appelé TWavSound (un composant supplémentaire appelé TWavButton est inclus dans le code source qui accompagne cet article comme un exemple). TWavSound tiendront simplement des données à partir d'un fichier WAV, et de jouer le son à la demande. Bien qu'il serait facile pour nous de déposer un TWavSound sur notre formulaire pour chaque son WAV nous avons besoin de notre formulaire pourrait bientôt commencer à devenir ingérable, donc nous allons également créer un gestionnaire de classe appelé TWavList.
Chaque technique utilisée dans le code source de ces composants a été couverts en partie deux de cette série d'articles, de sorte que le code source ne sera pas traité dans un grand niveau de détail. Cependant, je vais vous montrer les déclarations de classe de ces composants juste pour vous donner une idée de la façon dont ils sont structurés.
Note: En bas de l'unité, dans la section initialisation de l'appareil, vous remarquerez peut-être le code suivant:
initialisation
RegisterClass(TWavSound)
La raison en est que RegisterNoIcon ne semble pas faire un travail complet. Bien qu'il nous permet de créer des instances de composant enregistré à partir de notre propriété de l'éditeur, quelque chose semble aller mal quand un projet est re-loaded contenant ces composants. Une 'Classe non enregistrée' boîte de message s'affiche et le projet est endommagé. En outre, l'enregistrement de la classe dans cette voie semble résoudre le problème
TWavSound
type PWavData = ^TWavData TWavData = paniers record Taille: Longint Données: array[0..0] byte fin TWavSound = class(TComponent) privé FWavData: PWavData FWav: TWav procédure ReadWavData(Stream: TStream) procédure WriteWavData(Stream: TStream) protected procédure DefineProperties(Déclarant: TFiler) remplacer public destructeur Détruire remplacer procédure Clear procédure LoadFromFile(const nom du fichier: TFilename) procédure LoadFromStream(Stream: TStream) procédure Jouer publié fin |
FWavData
Sera utilisé pour stocker le contenu du fichier WAV une fois chargé à partir d'un flux ou d'un fichier.
Clear
Permettra de libérer de la mémoire contenant FWavData.
Jeu
utiliser la sndPlaySound les appels de l'API dans MMSystem.pas t
Composante de l'ecriture, de la partie 3
Composante de l'ecriture, de la partie 3 : Plusieurs milliers de conseils pour vous faciliter la vie.
Cet article est le dernier de trois articles sur les composants. Cette derniere partie permettra de couvrir propriete / editeurs de composants, comment ecrire dedie editeurs pour votre composant de la propriete, et comment ecrire 'cache' des composants.
Cet article est paru initialement dans les Developpeur Delphi |
Copyright Pinnacle Publishing, Inc. Tous droits reserves.
Personnalise Editeurs de Composants
des Que nous commençons a ecrire avance types de propriete pour nos composants, la vie devient un peu plus complique. Bien que l'inspecteur d'objet integre a Delphi est capable de reconnaître la plupart des types de propriete, il est impossible pour elle d'etre en mesure de faire face avec tout type personnalise nous pouvons ecrire dans nos composants. Parfois, l'inspecteur d'objet est en mesure de faire face a nos types personnalises, mais l'edition d'un tel arrangement complexe de proprietes dans l'inspecteur d'objet n'est tout simplement pas assez intuitif. C'est a ce point nous pouvons etre amenes a ecrire propriete / editeurs de composants. Delphi a de nombreux predefinis editeurs deja, ces editeurs sont dans le DsgnIntf.pas de fichier dans le $(Delphi)\Source\ToolsAPI repertoire. Vous aurez besoin de la liste de cette unite dans la clause uses de tout composant de l'editeur / editeur de proprietes, vous pouvez ecrire, c'est aussi une bonne idee de garder ce fichier ouvert pour reference lors de l'ecriture de vos propres editeurs.
les normes de Codage
Pour commencer, je vais couvrir certaines normes de codage qui sont utilises lors de l'ecriture ou de la propriete des editeurs. Il y a seulement quelques-uns, mais ce serait une bonne idee de garder a ces normes lors de l'ecriture de vos propres editeurs comme il est plus facile pour d'autres personnes a comprendre votre travail.
- Lors de la creation d'un editeur de propriete, a la fin le nom de votre editeur de texte avec le mot 'Propriete' par exemple TAngleProperty
- Lors de la creation d'un editeur de composant, fin le nom de votre editeur de texte avec le mot 'Editeur' par exemple TPieChartEditor
- Lors de l'ecriture des editeurs, toujours ecrire une lettre a l'editeur dans une unite separee de votre composante reelle. Il est bon de separer la conception et de l'execution du code et, en dehors de cela, il rend votre EXE resultant de taille plus petite (sur certaines versions de Delphi votre composant peut arreter des applications a partir de la compilation si vous n'avez pas les separer). Aussi, separer les paquets de sorte que vos utilisateurs peuvent construire avec les packages d'execution si ils le veulent bien !
- le Nom de votre redacteur en chef de l'unite avec le meme nom que votre composant de l'unite, mais ajouter le mot 'reg' a la fin par exemple, un composant avec le nom de l'unite 'Moncomposant.pas' dans l'editeur de nom de fichier etant 'MyComponentreg.pas'
- Enfin, lors de l'ecriture d'un editeur de composant ou de la propriete de l'editeur pour votre composant, deplacez votre RegisterComponents declaration de votre composant de l'unite, et dans votre editeur de composant de l'unite. De cette façon, votre composant ne sera pas enregistree sans que l'editeur a egalement enregistre.
La propriete de l'editeur
les editeurs de proprietes sont utilisees par l'IDE pour permettre l'edition speciale de proprietes individuelles au sein d'un composant. Certains editeurs sont tres simples, d'autres sont beaucoup plus complique. Delphi a deja un certain nombre de normes de propriete des editeurs, certains de ces facteurs sont:
TIntegerProperty. Utilisee pour la saisie des nombres entiers.
TCharProperty. Utilisee pour la saisie d'un seul caractere.
TEnumProperty. Utilise pour la selection d'un element individuel d'un type enumere (alTop, alClient etc). TBoolProperty. Utilise pour la selection de 'Vrai' ou 'Faux' pour les proprietes Booleennes.
TFloatProperty. Utilisee pour la saisie des nombres a virgule flottante (Variable de type Float / etc. Le type 'Reel' ne doit pas etre utilise pour les proprietes du composant).
TStringProperty. Utilisee pour la saisie des chaînes jusqu'a un maximum de 255 caracteres.
TSetProperty. Utilises pour inclure / exclure des elements d'un Ensemble de biens. Chaque element est affiche comme une valeur Booleenne sous-propriete. Reglage de la valeur 'True' comprend l'element, la valeur 'False' l'exclut.
TClassProperty. C'est la classe de base a descendre a partir de quand vous voulez creer un editeur personnalise a etre invoquee pour les proprietes d'une certaine classe (quand vous avez une classe en tant que propriete, tels que TImage.Image).
Tous ces editeurs de proprietes descendre directement ou indirectement de TPropertyEditor. TPropertyEditor a beaucoup de proprietes et de methodes, les plus importants sont.
fonction AllEqual: Boolean virtual fonction GetAttributes: TPropertyAttributes virtual procedure Edit virtual fonction GetValue: string virtual procedure GetValues(Proc: TGetStrProc) virtual |
AllEqual
Lorsque plusieurs composants sont selectionnes a l'inspecteur d'objet, les filtres de la liste de ses proprietes a seulement celles que tous les composants selectionnes ont en commun. Si la valeur de chaque composant pour toute propriete (par exemple, la Largeur est la meme, la valeur sera affichee, sinon pas de valeur sera affichee. AllEqual est la routine qui determine si chaque valeur est identique.
fonction TStringProperty.AllEqual: Boolean var I: Integer V string commencer Result := False si PropCount > 1 puis commencer V := GetStrValue pour I := 1 PropCount - 1 ne si GetStrValueAt(I) <> V puis Quitter fin Resultat := True fin |
Dans l'exemple ci-dessus TStringProperty compare chaque valeur (a l'aide de GetStrValueAt) avec la valeur de la premiere composante de la liste (a l'aide de GetStrValue, GetStrValueAt(0) en auraient fait de meme). La taille de la liste est determinee en utilisant des PropCount, il renvoie le montant total des composants selectionnes.
GetAttributes
GetAttributes est appele par l'IDE quand il a besoin de recueillir des informations sur la propriete de l'editeur. L'inspecteur d'objets affiche un editeur approprie sur la base des informations fournies. Le resultat de GetAttributes (TPropertyAttributes) est un ensemble, de sorte qu'il peut contenir une combinaison des valeurs suivantes (cette liste n'est pas exhaustive)
paDialog
Dit l'inspecteur d'objet pour afficher un bouton [...] apres le nom de la propriete, lorsque l'utilisateur clique sur ce bouton, la methode Edit est declenche.
paSubProperties
Dit l'inspecteur d'objet pour montrer un [ ] bouton developper avant le nom de la propriete, cliquez sur ce bouton pour afficher une liste elargie de sous-proprietes (generalement les proprietes publiees d'une propriete de la classe).
paValueList
L'inspecteur d'objet affichera une liste deroulante avec une liste de valeurs, cette liste est determinee par l'IDE en appelant la methode GetValues.
NOTE: La methode GetValues, pas la methode GetValue qui est completement different
paSortList
Si elle est combinee avec paValueList, les valeurs affichees sont tries par ordre alphabetique.
paMultiSelect
Ceci indique a l'IDE que la propriete est autorise a afficher lorsque plusieurs composants sont selectionnes. Cet element n'est pas present pour les editeurs, par exemple un TClassProperty.
paAutoUpdate
les Causes de la methode SetValue etre appelee a chaque fois que la valeur est modifiee dans l'inspecteur d'objet, plutot que d'attendre que l'utilisateur appuie sur la ou de modifier d'une autre propriete. Il est utilise pour les 'sous-titre' et 'Texte' proprietes', pour donner un live de la representation de la valeur de l'utilisateur est d'entrer.
paReadOnly
Si cet element est inclus dans la valeur dans l'inspecteur d'objet est en lecture seule. Il est generalement utilise en conjonction avec paDialog. GetValue serait substituee pour renvoyer un descriptif de la representation de la propriete.
Edit
Cette methode est appelee lorsque le bouton [...] pour la propriete est clique. Ce bouton s'affiche si le paDialog element est inclus dans le resultat de GetAttributes.
GetValue
Cette methode est appelee lorsque l'objet de l'inspecteur a besoin de savoir comment faire pour afficher la propriete comme une chaîne de caracteres. Ceci est generalement utilise lorsque [paDialog, paReadOnly] sont precisees dans la suite de GetAttributes.
GetValues
Cette methode est appelee lorsque l'objet de l'inspecteur des besoins pour recuperer une liste de valeurs a afficher lorsque paValueList est specifiee dans le resultat de GetAttributes. GetValues passe un parametre appele 'Proc' qui est de type TGetStrProc. GetStrProc est declaree comme TGetStrProc = procedure(const S: string) de l'objet
L'IDE s'attend a 'Proc' pour etre appelee une fois pour chaque valeur qui doit etre affiche dans l'inspecteur d'objet pour cette propriete.
procedure THintProperty.GetValues(Proc: TGetStrProc) commencer Proc('Premier element a afficher') Proc('Deuxieme element a afficher') fin |
L'exemple suivant montre comment fournir une liste de valeurs par defaut pour le 'Soupçon' de la propriete de tous les composants, tout en permettant a l'utilisateur d'entrer une valeur dans la liste.
type THintProperty = class(TStringProperty) public fonction GetAttributes: TPropertyAttributes remplacer procedure GetValues(Proc: TGetStrProc) remplacer fin procedure s'Inscrire application procedure Inscrivez-vous commencer RegisterPropertyEditor(TypeInfo(String), nul, 'Astuce' , THintProperty) fin { THintProperty } fonction THintProperty.GetAttributes: TPropertyAttributes commencer Result := herite GetAttributes [paValueList, paSortList] fin procedure THintProperty.GetValues(Proc: TGetStrProc) commencer Proc('Cette entree est necessaire') Proc( 'Appuyez sur F1 pour plus d'informations') Proc('Cette valeur est en lecture seule') fin |
Premier GetAttributes est substituee, et [paValueList, paSortList] sont inclus dans le resultat. Prochaine GetValues est remplacee et trois valeurs sont ajoutees a la liste deroulante en appelant le 'Proc' de la procedure.
Enregistrement de la propriete des editeurs de
Enfin, l'editeur de propriete est enregistree a l'aide RegisterPropertyEditor. RegisterPropertyEditor prend quatre parametres:
PropertyType: PTypeInfo
Necessite un pointeur vers une TTypeInfo enregistrement. Cela semble beaucoup plus complique qu'il ne l'est vraiment, tout ce que nous devons faire est d'ajouter TypInfo a nos usages de la clause, et l'utilisation de la TypeInfo fonction pour recuperer le pointeur pour nous. TypeInfo(SomeVariableType)
ComponentClass: TClass
C'est la classe de base que cet editeur doit s'appliquer. L'editeur de cette classe et des classes qui en descendre. Si nul n'est specifie, cet editeur s'appliquent a toute la classe.
const PropertyName: string
Si cet editeur ne devrait s'appliquer qu'a une propriete specifique, puis le nom de la propriete doit etre specifie ici. Si l'editeur doit s'appliquer a tout bien du type specifie dans PropertyType cette valeur doit etre '.
EditorClass: TPropertyEditorClass
C'est la classe qui a ete cree pour s'occuper de la propriete. Dans l'exemple ci-dessus, la classe est THintProperty.
a l'Aide de RegisterPropertyEditor incorrectement
Il est important lors de l'utilisation de RegisterPropertyEditor que vous fournir la bonne information. La fourniture de renseignements inexacts qui pourrait vouloir dire que votre editeur touche incorrecte proprietes (par exemple, Toutes les proprietes de chaîne) ou incorrecte des composants.
A l'autre extreme, le reglage des parametres de maniere incorrecte pourrait signifier que seule une propriete specifique a un element specifique (et descendants) est associee avec votre editeur de texte. Cela ne semble pas un probleme au debut, mais descendant composants peuvent souhaiter mettre en œuvre d'autres proprietes du meme type. Comme ces proprietes seront, evidemment, ont un nom different, ils n'auront pas le bon editeur de proprietes affectees a eux.
Un exemple de mauvaise enregistres l'editeur existe deja au sein de la VCL. L'editeur standard pour TCollection a ete enregistree pour toutes les classes descendu de TComponent. Le probleme est que la plus basse classe capable d'etre affichees dans l'inspecteur d'objet est TPersistent (la classe qui TComponent descend d').
Si un composant a une propriete de type TPersistent (qui, par defaut, expose ses sous-proprietes dans la liste extensible), et l'une de ses proprietes est de type TCollection, le resultat est un bouton [...] dans l'inspecteur d'objet qui ne fait rien quand on clique dessus (comme nous l'avons vu dans la partie deux de cette serie d'article).
La solution a ce probleme semble assez simple. Plutot que de sous-propriete d'etre descendu de TPersistent nous avons pu le descendre de TComponent a la place. Cependant, le comportement par defaut d'une propriete de type TComponent (tel Que determine par la propriete de l'editeur TComponentProperty editeur) est d'afficher une liste des autres composants, plutot que de les sous-proprietes d'un composant embarque.
La solution reelle est vraiment simple, mais seulement si vous savez comment ecrire une propriete de l'editeur.
Etape 1:
type TExpandingRecord = class(TPersistent) |
Devrait etre modifie pour se lire
type TExpandingRecord = class(TComponent) |
Etape 2: Creer un editeur de propriete comme
type TExpandingRecordProperty = class(TClassProperty) public fonction GetAttributes : TPropertyAttributes remplacer fin |
procedure s'Inscrire
application
procedure s'Inscrire
commencer
RegisterComponents('Article', [TExpandingComponent])
RegisterPropertyEditor(TypeInfo(TExpandingRecord), nul, ', TExpandingRecordProperty)
fin
{ TExpandingRecordProperty }
fonction TExpandingRecordProperty.GetAttributes: TPropertyAttributes
commencer
Result := [paReadOnly, paSubProperties]
fin
Etape 3: Supprimer le RegisterComponents appel de la composante de l'unite, et de l'inscrire dans l'editeur de l'unite. De cette façon, nous pouvons assurer que le composant ne sera pas enregistree sans le composant.
Maintenant, dans notre propriete de type TExpandingRecord s'affiche comme une expansion de la propriete (a cause de nous retourner paSubProperties de GetAttributes), et l'editeur par defaut pour TCollection va travailler en tant que proprietaire de la TCollection propriete est un TComponent.
boîte de Dialogue propriete des editeurs de
la Plupart du temps, lors de la creation d'un editeur de proprietes personnalisees, l'objectif est de fournir une representation graphique des moyens d'interaction avec la propriete.
Ce premier exemple est un moyen tres simple de permettre a l'utilisateur de saisir plusieurs lignes dans la 'Legende' la propriete d'un TLabel. Bien que cet exemple n'est pas tres complique, il montre comment integrer un formulaire dans votre editeur de texte.
Etape 1:
Selectionnez Fichier, la Nouvelle Application a partir du menu principal. Cela va creer un formulaire, nom de la forme 'fmLabelEdit', ajouter un TMemo a la forme nommee memCaption. Ajoutez deux boutons 'OK' et 'Annuler' avec la ModalResult definir les proprietes de mrOK et mrCancel respectivement.
Etape 2:
Ajouter DsgnIntf et TypInfo a votre clause uses.
Etape 3:
pour Ajouter la propriete suivante de l'editeur de code de votre appareil.
TCaptionProperty = class(TStringProperty) public fonction GetAttributes: TPropertyAttributes remplacer procedure Edit remplacer fin |
Et registre de la propriete editeur
procedure s'Inscrire application {$R *.DFM} procedure Inscrivez-vous commencer RegisterPropertyEditor(TypeInfo(TCaption), TLabel, 'Caption', TCaptionProperty) fin |
Etape 4:
Ajoutez le code suivant dans l'ordre de l'inspecteur d'objet pour afficher [...] bouton modifier apres le nom de la propriete.
fonction TCaptionProperty.GetAttributes: TPropertyAttributes commencer Result := herite GetAttributes [paDialog] fin |
Etape 5:
Enfin, nous creons une instance de notre forme de l'editeur, definir le contenu du memo pour le courant de la legende, et de montrer ensuite le formulaire modal.
procedure TCaptionProperty.Edit var I: Integer commencer avec TfmLabelEdit.Creer(Application) ne essayer memCaption.Les lignes.Texte := GetStrValue ShowModal {Si la ModalResult de la forme est mrOK, nous devons definir la 'Legende' de la propriete de chaque TLabel.} si ModalResult = mrOK puis pour I:=0 PropCount-1 ne TLabel(GetComponent(I)).Legende := memCaption.Les lignes.Texte enfin fin fin |
Etape 6:
Installer l'unite dans le package, puis essayer le nouvel editeur !
Avance de la propriete des editeurs de
quelqu'un qui n'a jamais utilise TActionList ou TDataSet (TTable / TQuery) devra posseder de l'experience de l'exemple suivant, peut-etre sans meme s'en rendre compte.
Le ActionList editeur est evidemment un editeur personnalise, car il permet de regroupement des actions, tandis que le FieldsEditor de TDataSet peut paraître a premiere vue comme un standard de l'editeur, mais sur une inspection plus minutieuse a un menu deroulant avec des articles comme 'Ajouter des champs'. Cependant, la caracteristique la plus remarquable de ces deux editeurs n'est pas qu'ils sont de dialogue personnalisee editeurs (semblable a celui que nous avons abordes precedemment), mais le fait que les objets qu'ils creent sont inclus dans la classe principale de la declaration de l'unite actuelle.
type TForm1 = class(TForm) ActionList1: TActionList Action1: TAction Action2: TAction prive { Private declarations } public { declarations Publiques } fin |
L'avantage de ceci est que l'IDE est mis au courant de ces elements, par consequent, leur permettant d'etre selectionne a partir d'une liste d'objets chaque fois que la propriete d'un composant exige d'eux.
Dans l'illustration ci-dessus, deux actions sont ajoutes a une TActionList, en cliquant sur le bouton 'Action' de la propriete de Button1 montre d'une liste comprenant les actions ajoutees. Les deux actions sont egalement ajoutes au Formulaire de declaration de classe, et peut donc etre designe par le nom (Action1, Action2).
Le truc c'est la que reside entierement dans la propriete de l'editeur et non pas au sein de la composante. Lorsqu'un editeur de propriete est declenchee (c'est a dire le Modifier methode est appelee), le Concepteur de la propriete contient une reference valide pour une IFormDesigner (TFormDesigner en Delphi 4). De nombreuses fonctions de cette interface ne sont pas dans le champ d'application de cet article, si vous souhaitez en savoir plus sur les fonctionnalites de cette interface, je vous recommande un livre qui s'appelle Delphi Manuel du Developpeur par Marco Cantu.
Certaines de ces methodes incluent
fonction MethodExists(const Nom: string): Boolean procedure RenameMethod(const CurName, NewName: string) procedure SelectComponent(Exemple: TPersistent) procedure ShowMethod(const Nom: string) fonction GetComponent(const Nom: string): TComponent fonction CreateComponent(ComponentClass: TComponentClass Parent: TComponent Gauche, Haut, Largeur, Hauteur: Integer): TComponent |
Certains de ces appels sont assez elementaires, MethodExists par exemple renvoie True ou False selon si oui ou non une methode de meme nom existe deja dans la forme de l'unite actuelle (FormCreate, Button1Click etc). ShowMethod de deplacer le curseur sur le nom de la methode, et RenameMethod va changer le nom d'une methode.
Les deux methodes qui sont de l'interet a utiliser a ce stade sont les suivantes:
CreateComponent
etant Donne une classe de composant, un parent, pour maintenir le composant, et la position / dimensions, le concepteur va creer une instance de la classe comme si le realisateur avait choisi a partir de la palette de composants et de l'ajouter a la forme elle-meme.
Modifie
Informe le concepteur que quelque chose a ete change (une propriete, etc). Cela modifie l'etat de l'appareil de sorte que l'IDE sait, il doit etre enregistre avant la fermeture (il permet egalement le bouton enregistrer dans l'IDE).
Lors de l'ajout d'elements a notre tableau de tout ce que nous devons faire est d'obtenir TMyProperty.Designer pour creer un composant en notre nom. Cette composante sera ensuite ajoute a la forme et aux biens qui se refere a une classe de ce type sera automatiquement informe. Dans le cas de TActionList et TDataSet les composants qui sont ajoutes a l'ecran ne sont pas visibles au moment de la conception, le proprietaire composant agit comme une sorte de 'manager' pour les composants.
Cours au moment de la conception, vous ne verrez pas un TAction ou un TField composant dans la palette de composants qui seraient eventuellement vous faire penser qu'ils ne sont pas enregistres, mais l'IDE est encore capable de creer des instances de ces composants (et ils ne sont pas visibles). La reponse n'est pas qu'ils ne sont pas inscrits, ce comportement est un resultat du 'comment' le composant est enregistre.
alors que RegisterComponents permet d'ajouter les composants de la palette de composants, la RegisterNoIcon methode inscrire votre composant sans l'ajouter a la palette de composants, en vous inscrivant dans cette voie, elle aussi raconte l'IDE que le composant ne doit pas etre affiche pendant le moment de la conception.
Dans l'exemple suivant, nous allons creer un composant appele TWavSound (un composant supplementaire appele TWavButton est inclus dans le code source qui accompagne cet article comme un exemple). TWavSound tiendront simplement des donnees a partir d'un fichier WAV, et de jouer le son a la demande. Bien qu'il serait facile pour nous de deposer un TWavSound sur notre formulaire pour chaque son WAV nous avons besoin de notre formulaire pourrait bientot commencer a devenir ingerable, donc nous allons egalement creer un gestionnaire de classe appele TWavList.
Chaque technique utilisee dans le code source de ces composants a ete couverts en partie deux de cette serie d'articles, de sorte que le code source ne sera pas traite dans un grand niveau de detail. Cependant, je vais vous montrer les declarations de classe de ces composants juste pour vous donner une idee de la façon dont ils sont structures.
Note: En bas de l'unite, dans la section initialisation de l'appareil, vous remarquerez peut-etre le code suivant:
initialisation
RegisterClass(TWavSound)
La raison en est que RegisterNoIcon ne semble pas faire un travail complet. Bien qu'il nous permet de creer des instances de composant enregistre a partir de notre propriete de l'editeur, quelque chose semble aller mal quand un projet est re-loaded contenant ces composants. Une 'Classe non enregistree' boîte de message s'affiche et le projet est endommage. En outre, l'enregistrement de la classe dans cette voie semble resoudre le probleme
TWavSound
type PWavData = ^TWavData TWavData = paniers record Taille: Longint Donnees: array[0..0] byte fin TWavSound = class(TComponent) prive FWavData: PWavData FWav: TWav procedure ReadWavData(Stream: TStream) procedure WriteWavData(Stream: TStream) protected procedure DefineProperties(Declarant: TFiler) remplacer public destructeur Detruire remplacer procedure Clear procedure LoadFromFile(const nom du fichier: TFilename) procedure LoadFromStream(Stream: TStream) procedure Jouer publie fin |
FWavData
Sera utilise pour stocker le contenu du fichier WAV une fois charge a partir d'un flux ou d'un fichier.
Clear
Permettra de liberer de la memoire contenant FWavData.
Jeu
utiliser la sndPlaySound les appels de l'API dans MMSystem.pas t
Composante de l'écriture, de la partie 3
By commentfaire
Composante de l'écriture, de la partie 3 : Plusieurs milliers de conseils pour vous faciliter la vie.