Donnez à vos clients le contrôle de l'interface graphique


Cet article montre comment les utilisateurs peuvent modifier leur interface graphique lors de l'exécution.

Développeur Delphi février 1999
droit d'Auteur Pinnacle Publishing, Inc. Tous droits réservés.Donnez à Vos Clients le Contrôle de l'interface graphique
Steve Zimmelman

Combien de fois avez-vous livrer ce que vous avez pensé était une demande dûment remplie, que d'entendre votre client de dire, 'Gee, c'est gentil, mais j'aimerais vraiment le Nom de la gauche, et le champ d'État doivent être de couleur rouge, n'est pas noir, et . . .' Ne serait-il pas agréable si tous vos utilisateurs avaient à faire était de clic droit de la souris sur le contrôle, et vient jusqu'à un menu permettant de modifier le contrôle d'attributs? Ou si elles appuyez sur Ctrl-ArrowKey ou Maj-ArrowKey pour modifier la position ou la taille de la commande?

Donner aux utilisateurs le contrôle de l'interface graphique est un processus en deux étapes. Vous devez d'abord créer des commandes avec des propriétés les utilisateurs peuvent modifier au moment de l'exécution, puis vous devez avoir un moyen de sauvegarder et de restaurer les modifications. Généralement, le contrôle qui obtient le plus utilisé est le DBEdit. Donc, cet exemple sera axé sur la création d'un DBEdit qui utilise une mesure PopupMenu qui est activé sur le clic droit de la souris. Le menu permet à l'utilisateur de changer la Couleur, la Police, l'Ordre de Tabulation, et la casse du Texte. En outre, la combinaison de touches Ctrl-Flèche et Maj-Flèche pour modifier la position et la taille de la commande, respectivement.
Avant de commencer, je tiens à vous présenter un nouveau texte-cas de la propriété: ProperCase. La plupart correcte des cas de conversions généralement de capitaliser la première lettre, puis toute lettre qui suit un espace. Mais cela laisse une foule de noms et de titres abrégés à la recherche d'un peu maladroit, comme Mcdonald's, O'Hara, M. D., et ainsi de suite. Donc, dans ma tentative de créer une meilleure souris-trap, j'ai inclus un cas de conversion qui a l'intelligence de poignée de ces noms spéciaux. J'ai placé les fonctions utilisées pour le bon cas de conversion en un appareil appelé StrFunc.pas et puis inclus l'unité StrFunc dans le Utilise l'instruction du composant.
la Création de la variable DBEdit
La première chose que j'ai faite a été de créer un nouveau composant à l'aide de TDBEdit que la classe parent. J'ai appelé la nouvelle classe TPSIDBEdit parce que le nom de la société pour laquelle je travaille est en PSI, et c'était un moyen simple de distinguer la composante. Ensuite, j'ai créé un nouveau CharCase type qui comprend ProperCase. Il sera utilisé pour remplacer le DBEdit de TCharCase. J'ai aussi changé la CharCase propriété à un nouveau type, TPSICharCase. En outre, à la redéfinition de la CharCase bien, j'ai introduit deux nouvelles propriétés: AllowUserChange et PopupChangeMenu. La propriété AllowUserChange est un simple commutateur Booléen qui s'engage ou se désactive la capacité de l'utilisateur à modifier les propriétés du composant au moment de l'exécution, et PopupChangeMenu est un pointeur vers le PopupMenu c'est en effet lors de l'AllowUserChange est définie sur True. Une grande partie de la composante du changement est effectué par le PopupChangeMenu, mais je vais discuter un peu plus tard. Le Listing 1 présente les PSIDBEdit unité.

Listing 1. Le PSIDBEdit unité.
unité de PSIDBEdit
interface

& nbsp & nbsp Windows, SysUtils, Classes, des Contrôles, des Formes, des Dialogues, des
& nbsp & nbsp DBCtrls, les Menus, db, StrFunc
type
& nbsp & nbsp TPSICharCase = (ecNormal, ecUpperCase,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecLowerCase, ecProperCase)
& nbsp & nbsp TPSIDBEdit = classe(TDBEdit)
& nbsp & nbsp privé
& ! & ! & ! & nbsp fCharCase : TPSICharCase
& ! & ! & ! & nbsp fIsChanging : Boolean
& ! & ! & ! & nbsp fAllowUserChange : Boolean
& ! & ! & ! & nbsp fStartMove : Boolean
& ! & ! & ! & nbsp fhaut : Integer
& ! & ! & ! & nbsp fLeft : Integer
& ! & ! & ! & nbsp fChangeMenu : TpopupMenu
& ! & ! & ! & nbsp fPopupSave : TPopupMenu
& ! & ! & ! & nbsp Procédure SetAllowUserChange(Value:Boolean)
& ! & ! & ! & nbsp Procédure SetChangeMenu(Valeur:TpopupMenu)
& ! & ! & ! & nbsp Procédure SetPopUpMenu
& ! & ! & ! & nbsp Procédure SetCharCase(Valeur:TPSICharCase)
& ! & ! & ! & nbsp Procédure SetTextCase(Const bCheckState:Boolean)
& nbsp & nbsp protégé
& nbsp & nbsp public
& ! & ! & ! & nbsp Procédure Chargé de Remplacer
& ! & ! & ! & nbsp Procédure de Changement de Remplacer
& ! & ! & ! & nbsp procédure KeyDown(var Key: Mot
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Shift: TShiftState) remplacer
& ! & ! & ! & nbsp Procédure MouseDown(Button: TMouseButton Maj:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp TShiftState X, Y: Integer)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Remplacer
& ! & ! & ! & nbsp procédure MouseMove(Maj: TShiftState
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp X, Y: Integer) Remplacer
& ! & ! & ! & nbsp procédure MouseUp(Button: TMouseButton Maj:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp TShiftState X, Y: Integer)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Remplacer
& nbsp & nbsp publié
& ! & ! & ! & nbsp Propriété AllowUserChange : Boolean
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fAllowUserChange
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Écrire SetAllowUserChange
& ! & ! & ! & nbsp Propriété CharCase : TPSICharCase
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fCharCase
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Écrire SetCharCase
& ! & ! & ! & nbsp Propriété PopupChangeMenu : TPopupMenu
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fChangeMenu
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Écrire SetChangeMenu
& nbsp & nbsp fin

je voulais le composant pour avoir deux états: un état par défaut qui se comporte comme son ancêtre, et une conception de l'état, qui permettrait à l'utilisateur de modifier ses propriétés au moment de l'exécution. La propriété Booléenne AllowUserChange distingue ces deux états. Lorsque AllowUserChange est Vrai, la PopupMenu est modifié pour pointer vers la valeur stockée dans la PopupChangeMenu de la propriété. Si c'est Faux, alors le PopupMenu propriété revient à ses précédentes moment de la conception d'affectation. Il permet également le composant à être déplacé ou redimensionné. J'ai pensé qu'il serait agréable pour l'utilisateur d'être en mesure de voir une différence entre les deux états, alors j'ai changé le curseur à crHandPoint (-21) dans le SetAllowUserChange méthode.
Le PopupMenu affectation est modifiée via la SetPopupMenu méthode lorsque le AllowUserChange propriété est modifiée.
En vue d'un échange le PopupMenu pointeurs, la valeur par défaut PopupMenu est stocké dans fPopupSave dans le Chargé de la méthode (voir Listing 2). Puis le SetPopupMenu méthode est appelée à s'assurer que le bon menu contextuel est attribué sur la base de la valeur de AllowUserChange.

Liste 2. Le Chargé de la méthode.
Procédure TPSIDBEdit.Chargé
Begin
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp Si (csDesigning dans ComponentState) Puis la Sortie
& ! & ! & ! & ! & ! & nbsp // Capture PopupMenu Affectation
& ! & ! & ! & ! & ! & nbsp fPopupSave := PopupMenu
& ! & ! & ! & ! & ! & nbsp SetPopupMenu
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp hérité Chargé
& nbsp & nbsp & nbsp Fin
Fin

Avec l'avènement du nouveau texte cas ProperCase et le nouveau type TPSICharCase, J'ai dû complètement remplacer et de mettre tous les autres types de texte en cas de conversions dans le Changement de la méthode de la pièce (voir le Listing 3).

le Listing 3. Le Changement de méthode.
Procédure TPSIDBEdit.Changement
Var
& nbsp & nbsp & nbsp iSelStart : Integer
Begin
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp Si (csDesigning dans ComponentState)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ou fIsChanging Puis la Sortie
& ! & ! & ! & ! & ! & nbsp // Capture de la Position du Curseur
& ! & ! & ! & ! & ! & nbsp iSelStart := SelStart
& ! & ! & ! & ! & ! & nbsp SetTextCase(False)
& ! & ! & ! & ! & ! & nbsp // Restaurer la Position du Curseur
& ! & ! & ! & ! & ! & nbsp SelStart := iSelStart
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp Hérité
& nbsp & nbsp & nbsp Fin
Fin

La réelle modification du Texte était un peu difficile. Si vous modifiez le texte par programmation lorsque l'objet qui a le focus, et le jeu de données n'est pas en Modifier ou en mode Insertion, alors que l'exception 'Dataset de ne pas en Modifier ou en mode Insertion' est généré. Donc avant de changer le texte du composant DataSet.L'état doit être interrogé et modifié si nécessaire. Nous devons également gérer tout le potentiel multi-utilisateur conflits qui pourraient survenir. Le paramètre bCheckState est utilisé pour déterminer si l'ensemble de données.L'état doit être placé dans Modifier ou Insérer mode avant de changer le texte. Si c'est le cas, la méthode doit également afficher les modifications. La méthode Post est appelée que si la variable de mémoire bPost est définie sur True. Liste 4 montre ce qui se passe dans le SetTextCase méthode.

Liste 4. Le SetTextCase méthode.
Procédure TPSIDBEdit.SetTextCase(Const bCheckState:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Boolean)
Var
& nbsp & nbsp & nbsp bPost : Boolean
& nbsp & nbsp & nbsp Fonction CanChange : Boolean
& nbsp & nbsp & nbsp Commencer
& ! & ! & ! & ! & ! & nbsp Essayer
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si Pas bCheckState Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Résultat := True
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Sortie
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si (source de données <> Nil) Ensuite, Commencez
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si ce N' (source de données.Jeu de données.État
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Dans [dsEdit, dsInsert]), Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si la source de données.Jeu de données.Actif, Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp source de données.Jeu de données.Edit
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp bPost := True
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & nbsp & ! & ! & ! & ! & nbsp Result := True
& ! & ! & ! & ! & ! & nbsp à l'Exception de
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Résultat := False
& ! & ! & ! & ! & ! & nbsp Fin
& nbsp & nbsp & nbsp Fin
Begin
& nbsp & nbsp & nbsp // Si la modification du Texte et le jeu de données
& nbsp & nbsp & nbsp // n'est pas dans EditState, une Exception
& nbsp & nbsp & nbsp // est généré. Assurez-vous que l'ensemble de données est
& nbsp & nbsp & nbsp // en EditState avant de changer de Texte.
& nbsp & nbsp & nbsp fIsChanging := True
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp bPost := False
& ! & ! & ! & ! & ! & nbsp Si CanChange Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Cas CharCase De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecNormal : {Ne Rien faire}
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecUpperCase : Texte := Majuscule(Texte)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecLowerCase : Texte := Minuscule(Texte)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecProperCase: Texte := ToProper(Texte)
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si bPost Puis
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp source de données.Jeu de données.Post
& ! & ! & ! & ! & ! & nbsp Fin Else
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp MessageDlg('un Autre utilisateur à l'aide de cette'
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! 'enregistrement.' #13 #13
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! 'TextCase les modifications ne peuvent pas être'
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! 'visible pour cet enregistrement.' ,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp mtWarning,[bakang],0)
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp fIsChanging := False
& nbsp & nbsp & nbsp Fin
Fin

le Changement de la CharCase propriété exécute la SetCharCase méthode (voir le Listing 5), qui, à son tour, exécute la SetTextCase méthode.

Listing 5. Le SetCharCase méthode.
Procédure TPSIDBEdit.SetCharCase(Valeur:TPSICharCase)
Begin
& nbsp & nbsp & nbsp Si fCharCase < Valeur> Ensuite Commencer
& ! & ! & ! & ! & ! & nbsp fCharCase := Valeur
& ! & ! & ! & ! & ! & nbsp SetTextCase(Vrai)
& nbsp & nbsp & nbsp Fin
Fin

pour le contrôle d'avoir les capacités de mouvement, j'ai remplacé le KeyDown méthode (voir le Listing 6). L'emprunt Delphi IDE séquences de touches pour la composante de déplacement et de dimensionnement, j'ai utilisé la combinaison de touches Ctrl-ArrowKeys pour le mouvement et le Changement-ArrowKeys pour le dimensionnement. En appuyant sur ces touches, le contrôle de modifier sa taille ou la position d'un pixel.

Listing 6. Le KeyDown méthode.
Procédure TPSIDBEdit.KeyDown(var Key: Mot
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Shift: TShiftState)
Begin
& nbsp & nbsp & nbsp If (Key [vk_up,vk_down,vk_left,vk_right])
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Et AllowUserChange Puis Commencer
& ! & ! & ! & ! & ! & nbsp Si (Maj = [ssCtrl]) Ensuite, Commencez
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp // Modification de la position
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Clé de Cas De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Up : Top := Top - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Down : en Haut := 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Left : à Gauche := Gauche - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Right: à Gauche := Gauche, 1
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & nbsp Fin Else if (Tour = [ssShift]) Ensuite, Commencez
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp // Modification de la Taille
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Clé de Cas De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Up : Hauteur := Hauteur - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Down : Hauteur := Hauteur 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Left : Largeur := Largeur - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Right: Largeur= Largeur 1
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & nbsp Clé := 0
& nbsp & nbsp & nbsp End Else Begin
& ! & ! & ! & ! & ! & nbsp hérité KeyDown(Clé,Maj)
& nbsp & nbsp & nbsp Fin
Fin

je tenais également à l'utilisateur d'être en mesure de déplacer le composant avec la souris, donc j'ai changé les méthodes MouseDown, MouseUp, et MouseMove.
jusqu'à présent, ce que vous avez est un DBEdit qui permet à un utilisateur de modifier sa position et sa taille, mais à peu de chose. La Police, la Couleur, l'Ordre de Tabulation, l'effet 3D, et de la Frontière sera fait avec l'ajout de la composante ChangeMenu.
La base de ce composant se trouve dans l'unité TypInfo.pas, qui vous permet d'avoir accès à un objet RTTI (runtime type d'information). TypInfo.pas contient des fonctions et des procédures qui peuvent Obtenir ou de Définir une propriété de l'objet les valeurs lors de l'exécution de l'application. Quelques méthodes simples de définition ou de l'Obtention d'un objet, la valeur de la propriété au moment de l'exécution peut ressembler à quelque chose comme la Liste des 7.

Listing 7. Obtention et définition d'une propriété de l'objet au moment de l'exécution.
Fonction de GetProperty(Sender:TComponent
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName:String):Variant
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& ! & ! & ! & nbsp // De la classe d'informations, obtenir la propriété
& ! & ! & ! & nbsp PropInfo := GetPropInfo(Expéditeur.ClassInfo,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName)
& ! & ! & ! & nbsp // est-ce que la propriété existe?
& ! & ! & ! & nbsp Si (PropInfo <> Nil) Then Begin
& ! & ! & ! & ! & ! & ! & nbsp Cas propinfo^.PropType^.Type De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkEnumeration,tkInteger:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Résultat := GetOrdProp(Expéditeur,PropInfo)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkString,tkLString,tkWString:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Résultat := GetStrProp(Expéditeur,PropInfo)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & nbsp Fin Else
& ! & ! & ! & ! & ! & ! & nbsp Résultat := Null
Fin

Procédure SetProperty(Sender:TComponent
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName:String
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vValue:Variante)
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& ! & ! & ! & nbsp // à Partir de la classe de l'information, obtenir la propriété
& ! & ! & ! & nbsp PropInfo := GetPropInfo(Expéditeur.ClassInfo,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName)
& ! & ! & ! & nbsp // est-ce que la propriété existe?
& ! & ! & ! & nbsp Si (PropInfo <> Nil) Then Begin
& ! & ! & ! & ! & ! & ! & nbsp Cas propinfo^.PropType^.Type De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkEnumeration,tkInteger:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp SetOrdProp(Expéditeur,PropInfo,vValue)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkString,tkLString,tkWString:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp SetStrProp(Expéditeur,PropInfo,vValue)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & nbsp Fin
Fin

l'Utilisation de ces deux méthodes pourrait ressembler à ceci:

& nbsp & nbsp SetProperty(DBEdit1,'Ctl3D',False)
& nbsp & nbsp DBEdit2.Ctrl3D := GetProperty(DBEdit1.'Ctl3D')

Accordé, cet exemple est probablement trop simplifiée, mais les procédures comme celles-ci peuvent être très utiles si vous ne savez pas du nom du composant, ou même de sa catégorie.
Les trois principales méthodes utilisées dans ChangeMenu & GetProperty(), SetProperty(), et IsProperty() & sont trouvés dans l'unité PropFunc.pas qui fait partie de cette bibliothèque. IsProperty() est une fonction Booléenne qui vérifie l'existence d'une propriété spécifiée dans un objet et renvoie une valeur True si la propriété existe. Il peut être utilisé quelque chose comme ceci:

Si IsProperty(Form1.Composants[i],'Ctl3D'),
& nbsp & nbsp & nbsp Composants[i].Ctl3D := False

TChangeMenu est une sous-classe de TPopupMenu avec deux autres propriétés: FontDialog et ColorDialog, qui sont utilisés pour modifier la Police et la Couleur, et peut pointer vers n'importe quel correspondant de la classe des types qui sont dans le champ d'application de la composante. Les méthodes MenuClick et OnMenuPopup faire le gros du travail et sont affectés à la OnClick et OnPopup événements des éléments de menu lorsque le composant est créé. Tout cela se passe, bien sûr, dans le ChangeMenu de l'unité (voir le Listing 8).

Listing 8. Le ChangeMenu unité.
unité de ChangeMenu
interface

& nbsp & nbsp Windows, Messages, SysUtils, Classes, Graphics,
& nbsp & nbsp Contrôles, des Formulaires, des boîtes de dialogue, Menus,comctrls,
& nbsp & nbsp StdCtrls,dbctrls, db,extctrls
type
& nbsp & nbsp TChangeMenu = classe(TPopupMenu)
& nbsp & nbsp privé
& ! & ! & ! & nbsp { Private declarations }
& ! & ! & ! & nbsp pm_Font : TMenuItem
& ! & ! & ! & nbsp pm_bgColor : TMenuItem
& ! & ! & ! & nbsp pm_TabOrder : TMenuItem
& ! & ! & ! & nbsp pm_Ctrl3D : TMenuItem
& ! & ! & ! & nbsp pm_BorderStyle: TMenuItem
& ! & ! & ! & nbsp pm_Columns : TMenuItem
& ! & ! & ! & nbsp pm_Caption : TMenuItem
& ! & ! & ! & nbsp pm_Divider1 : TMenuItem
& ! & ! & ! & nbsp pm_UpperCase : TMenuItem
& ! & ! & ! & nbsp pm_LowerCase : TMenuItem
& ! & ! & ! & nbsp pm_MixedCase : TMenuItem
& ! & ! & ! & nbsp pm_ProperCase : TMenuItem
& ! & ! & ! & nbsp pm_Height : TMenuItem
& ! & ! & ! & nbsp pm_Width : TMenuItem
& ! & ! & ! & nbsp pm_Style : TMenuItem
& ! & ! & ! & nbsp fFontDialog :TFontDialog
& ! & ! & ! & nbsp fColorDialog :TColorDialog
& ! & ! & ! & nbsp Procédure SetColorDialog(Valeur:TColorDialog)
& ! & ! & ! & nbsp Procédure SetFontDialog(Valeur:TFontDialog)
& ! & ! & ! & nbsp Procédure MenuClick(Sender:TObject)
& ! & ! & ! & nbsp Procédure OnMenuPopup(Sender:TObject)
& nbsp & nbsp protégé
& ! & ! & ! & nbsp { déclarations Protégées }
& nbsp & nbsp public
& ! & ! & ! & nbsp { déclarations Publiques }
& ! & ! & ! & nbsp Procédure Chargé de Remplacer
& ! & ! & ! & nbsp Destructeur de détruire remplacer
& ! & ! & ! & nbsp Constructor Create(AOwner: TComponent) remplacer
& nbsp & nbsp publié
& ! & ! & ! & nbsp { Publié des déclarations }
& ! & ! & ! & nbsp Propriété FontDialog :TFontDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fFontDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Écrire SetFontDialog
& ! & ! & ! & nbsp Propriété ColorDialog : TColorDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fColorDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Écrire SetColorDialog
& nbsp & nbsp fin
procédure Register
application
utilise PropFunc, col_edit

en Raison de l'utilisation de ce menu, les éléments de menu sont créés uniquement au moment de l'exécution, et non pas au moment de la conception dans l'IDE. Après les éléments de menu sont créés, la méthode MenuClick() est attribuée à l'événement OnClick de chaque élément de menu. Le menu ressemble à la Figure 1.
Le Chargé de la méthode (voir la Liste des 9) permet de saisir le pointeur de la composante OnPopup méthode, puis affecte le OnPopup cas de la méthode OnMenuPoup(). Ceci est fait de sorte que le développeur OnPopup méthode permettra de s'exécuter après la OnMenuPopup méthode a terminé le traitement de ses propres éléments de menu.

Listing 9. Le Chargé de la méthode.
Procédure TChangeMenu.Chargé
Begin
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp // Enregistrer le pointeur de la Composante OnPopup Méthode
& ! & ! & ! & ! & ! & nbsp FOtherOnPopup := OnPopup
& ! & ! & ! & ! & ! & nbsp // affectation de OnPopup Méthode
& ! & ! & ! & ! & ! & nbsp OnPopup := OnMenuPopup
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp Hérité
& nbsp & nbsp & nbsp Fin
Fin

Lorsque l'utilisateur clique avec le bouton droit de la souris sur le composant, le OnMenuPopup méthode est exécutée (voir le Listing 10) et initialise les éléments de menu en fonction du menu du PopupComponent de la propriété. PopupComponent est un pointeur vers l'objet qui a été responsable de l'activation du menu et le type de TComponent. Notez l'utilisation de la méthode IsProperty de définir la propriété Visible des éléments de menu.

Listing 10. Le OnMenuPopup méthode.
Procédure TChangeMenu.OnMenuPopup(Sender:TObject)
// Initialisation des éléments de menu basé sur le
// concentré du composant, le type et les propriétés.
Var bSet : Boolean
Begin
& nbsp & nbsp & nbsp // Ne pas afficher de Police de l'élément si la Police
& nbsp & nbsp & nbsp // boîte de Dialogue propriété est Nul ou la Police de caractères
& nbsp & nbsp & nbsp // Propriété n'existe pas dans le
& nbsp & nbsp & nbsp // composant.
& nbsp & nbsp & nbsp pm_Font.Visible :=
& ! & ! & ! & ! & ! & nbsp (Pas (FontDialog = Nil))
& ! & ! & ! & ! & ! & nbsp Et IsProperty(PopupComponent,'Police')
& nbsp & nbsp & nbsp // Ne pas afficher l'élément en Couleur si le ColorDialog
&







Donnez a vos clients le controle de l'interface graphique


Donnez a vos clients le controle de l'interface graphique : Plusieurs milliers de conseils pour vous faciliter la vie.


Cet article montre comment les utilisateurs peuvent modifier leur interface graphique lors de l'execution.

Developpeur Delphi fevrier 1999
droit d'Auteur Pinnacle Publishing, Inc. Tous droits reserves.Donnez a Vos Clients le Controle de l'interface graphique
Steve Zimmelman

Combien de fois avez-vous livrer ce que vous avez pense etait une demande dûment remplie, que d'entendre votre client de dire, 'Gee, c'est gentil, mais j'aimerais vraiment le Nom de la gauche, et le champ d'Etat doivent etre de couleur rouge, n'est pas noir, et . . .' Ne serait-il pas agreable si tous vos utilisateurs avaient a faire etait de clic droit de la souris sur le controle, et vient jusqu'a un menu permettant de modifier le controle d'attributs? Ou si elles appuyez sur Ctrl-ArrowKey ou Maj-ArrowKey pour modifier la position ou la taille de la commande?

Donner aux utilisateurs le controle de l'interface graphique est un processus en deux etapes. Vous devez d'abord creer des commandes avec des proprietes les utilisateurs peuvent modifier au moment de l'execution, puis vous devez avoir un moyen de sauvegarder et de restaurer les modifications. Generalement, le controle qui obtient le plus utilise est le DBEdit. Donc, cet exemple sera axe sur la creation d'un DBEdit qui utilise une mesure PopupMenu qui est active sur le clic droit de la souris. Le menu permet a l'utilisateur de changer la Couleur, la Police, l'Ordre de Tabulation, et la casse du Texte. En outre, la combinaison de touches Ctrl-Fleche et Maj-Fleche pour modifier la position et la taille de la commande, respectivement.
Avant de commencer, je tiens a vous presenter un nouveau texte-cas de la propriete: ProperCase. La plupart correcte des cas de conversions generalement de capitaliser la premiere lettre, puis toute lettre qui suit un espace. Mais cela laisse une foule de noms et de titres abreges a la recherche d'un peu maladroit, comme Mcdonald's, O'Hara, M. D., et ainsi de suite. Donc, dans ma tentative de creer une meilleure souris-trap, j'ai inclus un cas de conversion qui a l'intelligence de poignee de ces noms speciaux. J'ai place les fonctions utilisees pour le bon cas de conversion en un appareil appele StrFunc.pas et puis inclus l'unite StrFunc dans le Utilise l'instruction du composant.
la Creation de la variable DBEdit
La premiere chose que j'ai faite a ete de creer un nouveau composant a l'aide de TDBEdit que la classe parent. J'ai appele la nouvelle classe TPSIDBEdit parce que le nom de la societe pour laquelle je travaille est en PSI, et c'etait un moyen simple de distinguer la composante. Ensuite, j'ai cree un nouveau CharCase type qui comprend ProperCase. Il sera utilise pour remplacer le DBEdit de TCharCase. J'ai aussi change la CharCase propriete a un nouveau type, TPSICharCase. En outre, a la redefinition de la CharCase bien, j'ai introduit deux nouvelles proprietes: AllowUserChange et PopupChangeMenu. La propriete AllowUserChange est un simple commutateur Booleen qui s'engage ou se desactive la capacite de l'utilisateur a modifier les proprietes du composant au moment de l'execution, et PopupChangeMenu est un pointeur vers le PopupMenu c'est en effet lors de l'AllowUserChange est definie sur True. Une grande partie de la composante du changement est effectue par le PopupChangeMenu, mais je vais discuter un peu plus tard. Le Listing 1 presente les PSIDBEdit unite.

Listing 1. Le PSIDBEdit unite.
unite de PSIDBEdit
interface

& nbsp & nbsp Windows, SysUtils, Classes, des Controles, des Formes, des Dialogues, des
& nbsp & nbsp DBCtrls, les Menus, db, StrFunc
type
& nbsp & nbsp TPSICharCase = (ecNormal, ecUpperCase,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecLowerCase, ecProperCase)
& nbsp & nbsp TPSIDBEdit = classe(TDBEdit)
& nbsp & nbsp prive
& ! & ! & ! & nbsp fCharCase : TPSICharCase
& ! & ! & ! & nbsp fIsChanging : Boolean
& ! & ! & ! & nbsp fAllowUserChange : Boolean
& ! & ! & ! & nbsp fStartMove : Boolean
& ! & ! & ! & nbsp fhaut : Integer
& ! & ! & ! & nbsp fLeft : Integer
& ! & ! & ! & nbsp fChangeMenu : TpopupMenu
& ! & ! & ! & nbsp fPopupSave : TPopupMenu
& ! & ! & ! & nbsp Procedure SetAllowUserChange(Value:Boolean)
& ! & ! & ! & nbsp Procedure SetChangeMenu(Valeur:TpopupMenu)
& ! & ! & ! & nbsp Procedure SetPopUpMenu
& ! & ! & ! & nbsp Procedure SetCharCase(Valeur:TPSICharCase)
& ! & ! & ! & nbsp Procedure SetTextCase(Const bCheckState:Boolean)
& nbsp & nbsp protege
& nbsp & nbsp public
& ! & ! & ! & nbsp Procedure Charge de Remplacer
& ! & ! & ! & nbsp Procedure de Changement de Remplacer
& ! & ! & ! & nbsp procedure KeyDown(var Key: Mot
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Shift: TShiftState) remplacer
& ! & ! & ! & nbsp Procedure MouseDown(Button: TMouseButton Maj:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp TShiftState X, Y: Integer)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Remplacer
& ! & ! & ! & nbsp procedure MouseMove(Maj: TShiftState
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp X, Y: Integer) Remplacer
& ! & ! & ! & nbsp procedure MouseUp(Button: TMouseButton Maj:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp TShiftState X, Y: Integer)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Remplacer
& nbsp & nbsp publie
& ! & ! & ! & nbsp Propriete AllowUserChange : Boolean
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fAllowUserChange
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ecrire SetAllowUserChange
& ! & ! & ! & nbsp Propriete CharCase : TPSICharCase
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fCharCase
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ecrire SetCharCase
& ! & ! & ! & nbsp Propriete PopupChangeMenu : TPopupMenu
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fChangeMenu
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ecrire SetChangeMenu
& nbsp & nbsp fin

je voulais le composant pour avoir deux etats: un etat par defaut qui se comporte comme son ancetre, et une conception de l'etat, qui permettrait a l'utilisateur de modifier ses proprietes au moment de l'execution. La propriete Booleenne AllowUserChange distingue ces deux etats. Lorsque AllowUserChange est Vrai, la PopupMenu est modifie pour pointer vers la valeur stockee dans la PopupChangeMenu de la propriete. Si c'est Faux, alors le PopupMenu propriete revient a ses precedentes moment de la conception d'affectation. Il permet egalement le composant a etre deplace ou redimensionne. J'ai pense qu'il serait agreable pour l'utilisateur d'etre en mesure de voir une difference entre les deux etats, alors j'ai change le curseur a crHandPoint (-21) dans le SetAllowUserChange methode.
Le PopupMenu affectation est modifiee via la SetPopupMenu methode lorsque le AllowUserChange propriete est modifiee.
En vue d'un echange le PopupMenu pointeurs, la valeur par defaut PopupMenu est stocke dans fPopupSave dans le Charge de la methode (voir Listing 2). Puis le SetPopupMenu methode est appelee a s'assurer que le bon menu contextuel est attribue sur la base de la valeur de AllowUserChange.

Liste 2. Le Charge de la methode.
Procedure TPSIDBEdit.Charge
Begin
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp Si (csDesigning dans ComponentState) Puis la Sortie
& ! & ! & ! & ! & ! & nbsp // Capture PopupMenu Affectation
& ! & ! & ! & ! & ! & nbsp fPopupSave := PopupMenu
& ! & ! & ! & ! & ! & nbsp SetPopupMenu
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp herite Charge
& nbsp & nbsp & nbsp Fin
Fin

Avec l'avenement du nouveau texte cas ProperCase et le nouveau type TPSICharCase, J'ai dû completement remplacer et de mettre tous les autres types de texte en cas de conversions dans le Changement de la methode de la piece (voir le Listing 3).

le Listing 3. Le Changement de methode.
Procedure TPSIDBEdit.Changement
Var
& nbsp & nbsp & nbsp iSelStart : Integer
Begin
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp Si (csDesigning dans ComponentState)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ou fIsChanging Puis la Sortie
& ! & ! & ! & ! & ! & nbsp // Capture de la Position du Curseur
& ! & ! & ! & ! & ! & nbsp iSelStart := SelStart
& ! & ! & ! & ! & ! & nbsp SetTextCase(False)
& ! & ! & ! & ! & ! & nbsp // Restaurer la Position du Curseur
& ! & ! & ! & ! & ! & nbsp SelStart := iSelStart
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp Herite
& nbsp & nbsp & nbsp Fin
Fin

La reelle modification du Texte etait un peu difficile. Si vous modifiez le texte par programmation lorsque l'objet qui a le focus, et le jeu de donnees n'est pas en Modifier ou en mode Insertion, alors que l'exception 'Dataset de ne pas en Modifier ou en mode Insertion' est genere. Donc avant de changer le texte du composant DataSet.L'etat doit etre interroge et modifie si necessaire. Nous devons egalement gerer tout le potentiel multi-utilisateur conflits qui pourraient survenir. Le parametre bCheckState est utilise pour determiner si l'ensemble de donnees.L'etat doit etre place dans Modifier ou Inserer mode avant de changer le texte. Si c'est le cas, la methode doit egalement afficher les modifications. La methode Post est appelee que si la variable de memoire bPost est definie sur True. Liste 4 montre ce qui se passe dans le SetTextCase methode.

Liste 4. Le SetTextCase methode.
Procedure TPSIDBEdit.SetTextCase(Const bCheckState:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Boolean)
Var
& nbsp & nbsp & nbsp bPost : Boolean
& nbsp & nbsp & nbsp Fonction CanChange : Boolean
& nbsp & nbsp & nbsp Commencer
& ! & ! & ! & ! & ! & nbsp Essayer
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si Pas bCheckState Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Resultat := True
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Sortie
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si (source de donnees <> Nil) Ensuite, Commencez
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si ce N' (source de donnees.Jeu de donnees.Etat
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Dans [dsEdit, dsInsert]), Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si la source de donnees.Jeu de donnees.Actif, Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp source de donnees.Jeu de donnees.Edit
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp bPost := True
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & nbsp & ! & ! & ! & ! & nbsp Result := True
& ! & ! & ! & ! & ! & nbsp a l'Exception de
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Resultat := False
& ! & ! & ! & ! & ! & nbsp Fin
& nbsp & nbsp & nbsp Fin
Begin
& nbsp & nbsp & nbsp // Si la modification du Texte et le jeu de donnees
& nbsp & nbsp & nbsp // n'est pas dans EditState, une Exception
& nbsp & nbsp & nbsp // est genere. Assurez-vous que l'ensemble de donnees est
& nbsp & nbsp & nbsp // en EditState avant de changer de Texte.
& nbsp & nbsp & nbsp fIsChanging := True
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp bPost := False
& ! & ! & ! & ! & ! & nbsp Si CanChange Puis Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Cas CharCase De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecNormal : {Ne Rien faire}
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecUpperCase : Texte := Majuscule(Texte)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecLowerCase : Texte := Minuscule(Texte)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp ecProperCase: Texte := ToProper(Texte)
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Si bPost Puis
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp source de donnees.Jeu de donnees.Post
& ! & ! & ! & ! & ! & nbsp Fin Else
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp MessageDlg('un Autre utilisateur a l'aide de cette'
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! 'enregistrement.' #13 #13
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! 'TextCase les modifications ne peuvent pas etre'
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! 'visible pour cet enregistrement.' ,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp mtWarning,[bakang],0)
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp fIsChanging := False
& nbsp & nbsp & nbsp Fin
Fin

le Changement de la CharCase propriete execute la SetCharCase methode (voir le Listing 5), qui, a son tour, execute la SetTextCase methode.

Listing 5. Le SetCharCase methode.
Procedure TPSIDBEdit.SetCharCase(Valeur:TPSICharCase)
Begin
& nbsp & nbsp & nbsp Si fCharCase < Valeur> Ensuite Commencer
& ! & ! & ! & ! & ! & nbsp fCharCase := Valeur
& ! & ! & ! & ! & ! & nbsp SetTextCase(Vrai)
& nbsp & nbsp & nbsp Fin
Fin

pour le controle d'avoir les capacites de mouvement, j'ai remplace le KeyDown methode (voir le Listing 6). L'emprunt Delphi IDE sequences de touches pour la composante de deplacement et de dimensionnement, j'ai utilise la combinaison de touches Ctrl-ArrowKeys pour le mouvement et le Changement-ArrowKeys pour le dimensionnement. En appuyant sur ces touches, le controle de modifier sa taille ou la position d'un pixel.

Listing 6. Le KeyDown methode.
Procedure TPSIDBEdit.KeyDown(var Key: Mot
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Shift: TShiftState)
Begin
& nbsp & nbsp & nbsp If (Key [vk_up,vk_down,vk_left,vk_right])
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Et AllowUserChange Puis Commencer
& ! & ! & ! & ! & ! & nbsp Si (Maj = [ssCtrl]) Ensuite, Commencez
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp // Modification de la position
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Cle de Cas De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Up : Top := Top - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Down : en Haut := 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Left : a Gauche := Gauche - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Right: a Gauche := Gauche, 1
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & nbsp Fin Else if (Tour = [ssShift]) Ensuite, Commencez
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp // Modification de la Taille
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Cle de Cas De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Up : Hauteur := Hauteur - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Down : Hauteur := Hauteur 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Left : Largeur := Largeur - 1
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vk_Right: Largeur= Largeur 1
& ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & nbsp Cle := 0
& nbsp & nbsp & nbsp End Else Begin
& ! & ! & ! & ! & ! & nbsp herite KeyDown(Cle,Maj)
& nbsp & nbsp & nbsp Fin
Fin

je tenais egalement a l'utilisateur d'etre en mesure de deplacer le composant avec la souris, donc j'ai change les methodes MouseDown, MouseUp, et MouseMove.
jusqu'a present, ce que vous avez est un DBEdit qui permet a un utilisateur de modifier sa position et sa taille, mais a peu de chose. La Police, la Couleur, l'Ordre de Tabulation, l'effet 3D, et de la Frontiere sera fait avec l'ajout de la composante ChangeMenu.
La base de ce composant se trouve dans l'unite TypInfo.pas, qui vous permet d'avoir acces a un objet RTTI (runtime type d'information). TypInfo.pas contient des fonctions et des procedures qui peuvent Obtenir ou de Definir une propriete de l'objet les valeurs lors de l'execution de l'application. Quelques methodes simples de definition ou de l'Obtention d'un objet, la valeur de la propriete au moment de l'execution peut ressembler a quelque chose comme la Liste des 7.

Listing 7. Obtention et definition d'une propriete de l'objet au moment de l'execution.
Fonction de GetProperty(Sender:TComponent
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName:String):Variant
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& ! & ! & ! & nbsp // De la classe d'informations, obtenir la propriete
& ! & ! & ! & nbsp PropInfo := GetPropInfo(Expediteur.ClassInfo,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName)
& ! & ! & ! & nbsp // est-ce que la propriete existe?
& ! & ! & ! & nbsp Si (PropInfo <> Nil) Then Begin
& ! & ! & ! & ! & ! & ! & nbsp Cas propinfo^.PropType^.Type De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkEnumeration,tkInteger:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Resultat := GetOrdProp(Expediteur,PropInfo)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkString,tkLString,tkWString:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Resultat := GetStrProp(Expediteur,PropInfo)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & nbsp Fin Else
& ! & ! & ! & ! & ! & ! & nbsp Resultat := Null
Fin

Procedure SetProperty(Sender:TComponent
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName:String
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp vValue:Variante)
Var
& nbsp & nbsp & nbsp PropInfo : PPropinfo
Begin
& ! & ! & ! & nbsp // a Partir de la classe de l'information, obtenir la propriete
& ! & ! & ! & nbsp PropInfo := GetPropInfo(Expediteur.ClassInfo,
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp sPropName)
& ! & ! & ! & nbsp // est-ce que la propriete existe?
& ! & ! & ! & nbsp Si (PropInfo <> Nil) Then Begin
& ! & ! & ! & ! & ! & ! & nbsp Cas propinfo^.PropType^.Type De
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkEnumeration,tkInteger:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp SetOrdProp(Expediteur,PropInfo,vValue)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp tkString,tkLString,tkWString:
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Commencer
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp SetStrProp(Expediteur,PropInfo,vValue)
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & ! & ! & ! & nbsp Fin
& ! & ! & ! & nbsp Fin
Fin

l'Utilisation de ces deux methodes pourrait ressembler a ceci:

& nbsp & nbsp SetProperty(DBEdit1,'Ctl3D',False)
& nbsp & nbsp DBEdit2.Ctrl3D := GetProperty(DBEdit1.'Ctl3D')

Accorde, cet exemple est probablement trop simplifiee, mais les procedures comme celles-ci peuvent etre tres utiles si vous ne savez pas du nom du composant, ou meme de sa categorie.
Les trois principales methodes utilisees dans ChangeMenu & GetProperty(), SetProperty(), et IsProperty() & sont trouves dans l'unite PropFunc.pas qui fait partie de cette bibliotheque. IsProperty() est une fonction Booleenne qui verifie l'existence d'une propriete specifiee dans un objet et renvoie une valeur True si la propriete existe. Il peut etre utilise quelque chose comme ceci:

Si IsProperty(Form1.Composants[i],'Ctl3D'),
& nbsp & nbsp & nbsp Composants[i].Ctl3D := False

TChangeMenu est une sous-classe de TPopupMenu avec deux autres proprietes: FontDialog et ColorDialog, qui sont utilises pour modifier la Police et la Couleur, et peut pointer vers n'importe quel correspondant de la classe des types qui sont dans le champ d'application de la composante. Les methodes MenuClick et OnMenuPopup faire le gros du travail et sont affectes a la OnClick et OnPopup evenements des elements de menu lorsque le composant est cree. Tout cela se passe, bien sûr, dans le ChangeMenu de l'unite (voir le Listing 8).

Listing 8. Le ChangeMenu unite.
unite de ChangeMenu
interface

& nbsp & nbsp Windows, Messages, SysUtils, Classes, Graphics,
& nbsp & nbsp Controles, des Formulaires, des boîtes de dialogue, Menus,comctrls,
& nbsp & nbsp StdCtrls,dbctrls, db,extctrls
type
& nbsp & nbsp TChangeMenu = classe(TPopupMenu)
& nbsp & nbsp prive
& ! & ! & ! & nbsp { Private declarations }
& ! & ! & ! & nbsp pm_Font : TMenuItem
& ! & ! & ! & nbsp pm_bgColor : TMenuItem
& ! & ! & ! & nbsp pm_TabOrder : TMenuItem
& ! & ! & ! & nbsp pm_Ctrl3D : TMenuItem
& ! & ! & ! & nbsp pm_BorderStyle: TMenuItem
& ! & ! & ! & nbsp pm_Columns : TMenuItem
& ! & ! & ! & nbsp pm_Caption : TMenuItem
& ! & ! & ! & nbsp pm_Divider1 : TMenuItem
& ! & ! & ! & nbsp pm_UpperCase : TMenuItem
& ! & ! & ! & nbsp pm_LowerCase : TMenuItem
& ! & ! & ! & nbsp pm_MixedCase : TMenuItem
& ! & ! & ! & nbsp pm_ProperCase : TMenuItem
& ! & ! & ! & nbsp pm_Height : TMenuItem
& ! & ! & ! & nbsp pm_Width : TMenuItem
& ! & ! & ! & nbsp pm_Style : TMenuItem
& ! & ! & ! & nbsp fFontDialog :TFontDialog
& ! & ! & ! & nbsp fColorDialog :TColorDialog
& ! & ! & ! & nbsp Procedure SetColorDialog(Valeur:TColorDialog)
& ! & ! & ! & nbsp Procedure SetFontDialog(Valeur:TFontDialog)
& ! & ! & ! & nbsp Procedure MenuClick(Sender:TObject)
& ! & ! & ! & nbsp Procedure OnMenuPopup(Sender:TObject)
& nbsp & nbsp protege
& ! & ! & ! & nbsp { declarations Protegees }
& nbsp & nbsp public
& ! & ! & ! & nbsp { declarations Publiques }
& ! & ! & ! & nbsp Procedure Charge de Remplacer
& ! & ! & ! & nbsp Destructeur de detruire remplacer
& ! & ! & ! & nbsp Constructor Create(AOwner: TComponent) remplacer
& nbsp & nbsp publie
& ! & ! & ! & nbsp { Publie des declarations }
& ! & ! & ! & nbsp Propriete FontDialog :TFontDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fFontDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ecrire SetFontDialog
& ! & ! & ! & nbsp Propriete ColorDialog : TColorDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Lire fColorDialog
& ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & ! & nbsp Ecrire SetColorDialog
& nbsp & nbsp fin
procedure Register
application
utilise PropFunc, col_edit

en Raison de l'utilisation de ce menu, les elements de menu sont crees uniquement au moment de l'execution, et non pas au moment de la conception dans l'IDE. Apres les elements de menu sont crees, la methode MenuClick() est attribuee a l'evenement OnClick de chaque element de menu. Le menu ressemble a la Figure 1.
Le Charge de la methode (voir la Liste des 9) permet de saisir le pointeur de la composante OnPopup methode, puis affecte le OnPopup cas de la methode OnMenuPoup(). Ceci est fait de sorte que le developpeur OnPopup methode permettra de s'executer apres la OnMenuPopup methode a termine le traitement de ses propres elements de menu.

Listing 9. Le Charge de la methode.
Procedure TChangeMenu.Charge
Begin
& nbsp & nbsp & nbsp Essayer
& ! & ! & ! & ! & ! & nbsp // Enregistrer le pointeur de la Composante OnPopup Methode
& ! & ! & ! & ! & ! & nbsp FOtherOnPopup := OnPopup
& ! & ! & ! & ! & ! & nbsp // affectation de OnPopup Methode
& ! & ! & ! & ! & ! & nbsp OnPopup := OnMenuPopup
& nbsp & nbsp & nbsp Enfin
& ! & ! & ! & ! & ! & nbsp Herite
& nbsp & nbsp & nbsp Fin
Fin

Lorsque l'utilisateur clique avec le bouton droit de la souris sur le composant, le OnMenuPopup methode est executee (voir le Listing 10) et initialise les elements de menu en fonction du menu du PopupComponent de la propriete. PopupComponent est un pointeur vers l'objet qui a ete responsable de l'activation du menu et le type de TComponent. Notez l'utilisation de la methode IsProperty de definir la propriete Visible des elements de menu.

Listing 10. Le OnMenuPopup methode.
Procedure TChangeMenu.OnMenuPopup(Sender:TObject)
// Initialisation des elements de menu base sur le
// concentre du composant, le type et les proprietes.
Var bSet : Boolean
Begin
& nbsp & nbsp & nbsp // Ne pas afficher de Police de l'element si la Police
& nbsp & nbsp & nbsp // boîte de Dialogue propriete est Nul ou la Police de caracteres
& nbsp & nbsp & nbsp // Propriete n'existe pas dans le
& nbsp & nbsp & nbsp // composant.
& nbsp & nbsp & nbsp pm_Font.Visible :=
& ! & ! & ! & ! & ! & nbsp (Pas (FontDialog = Nil))
& ! & ! & ! & ! & ! & nbsp Et IsProperty(PopupComponent,'Police')
& nbsp & nbsp & nbsp // Ne pas afficher l'element en Couleur si le ColorDialog
&

Donnez à vos clients le contrôle de l'interface graphique

Donnez à vos clients le contrôle de l'interface graphique : Plusieurs milliers de conseils pour vous faciliter la vie.
Recommander aux amis
  • gplus
  • pinterest

Messages récents

Commentaire

Laisser un commentaire

évaluation