Création du menu étrange de DELPHI
Traducteur : Li Junyu email : [email protected],[email protected]
Menus personnalisés, Texte, Lignes / Delphi 4, 5
Menu personnalisé, texte, ligne/Delphi 4, 5
Menus fantaisie, etc.
Menus bizarres, etc.
Menus personnalisés, texte pivoté et lignes spéciales
Menus personnalisés, texte pivoté et lignes spéciales
Avant Delphi 4, il était difficile de personnaliser un menu (ajouter un bitmap, changer une police, etc.), car le dessin du propriétaire (c'est-à-dire le dessin personnalisé) - bien qu'implémenté par Windows - n'était pas exposé par la classe TMainMenu. Depuis Delphi 4, Cependant, cette situation a été corrigée et nous pouvons nous débrouiller avec les menus.
Avant Delphi 4, il était difficile de personnaliser un menu (comme l'ajout d'une image BMP, la modification de la police, etc.) car l'événement de dessin du propriétaire (c'est-à-dire l'événement de dessin personnalisé) - bien qu'exécuté par Windows, n'apparaît pas dans Classe TMainMenu Depuis Delphi 4,
Cette situation a changé et nous avons désormais la possibilité de personnaliser les menus.
Cet article mettra en évidence certaines techniques que vous pouvez utiliser pour personnaliser l'apparence des menus dans vos applications Delphi. Nous aborderons le placement du texte, la taille des menus, l'affectation des polices et l'utilisation de bitmaps et de formes pour améliorer l'apparence d'un menu. Juste pour le plaisir, cet article. propose également des techniques pour créer du texte pivoté et des lignes personnalisées. Toutes les techniques abordées dans cet article sont démontrées dans les projets disponibles en téléchargement.
Cet article se concentrera sur certaines techniques que vous pouvez utiliser pour personnaliser l'apparence des menus dans vos applications DELPHI. Nous aborderons le placement du texte, la taille des menus, les paramètres de police et les améliorations avec les fichiers BMP et le contrôle SHAPE. . Juste à des fins amusantes, cet article présentera également un gros plan des techniques de rotation du texte et des lignes personnalisées. Toutes les techniques abordées dans cet article ont été déboguées dans les fichiers de projet et peuvent être téléchargées en ligne.
Polices et tailles personnalisées
Définir la police et la taille
Pour créer un menu personnalisé, définissez la propriété OwnerDraw du composant de menu -TMainMenu ou TPopupMenu - sur True et fournissez des gestionnaires d'événements pour ses événements OnDrawItem et OnMeasureItem. Par exemple, un gestionnaire d'événements OnMeasureItem est déclaré comme ceci :
Pour créer un menu personnalisé, définissez la propriété OwnerDraw du composant TmainMenu ou TpopupMenu sur TRUE et créez ses procédures événementielles OnDrawItem et OnMeasureItem. Par exemple, une procédure événementielle OnMeasureItem pourrait être déclarée comme suit :
procédure TForm1.Option1MeasureItem(Sender: TObject;
ACanvas : TCanvas ; var Largeur, Hauteur : Entier);
Définissez les variables Largeur et Hauteur pour ajuster la taille de l'élément de menu. Le gestionnaire d'événements OnDrawItem est l'endroit où tout le travail est effectué ; c'est là que vous dessinez votre menu et effectuez les paramètres spéciaux pour dessiner l'option de menu avec la police Times New Roman. , par exemple, vous devriez faire quelque chose comme ceci :
Définissez les variables Largeur et Hauteur de l'élément de menu dans la procédure événementielle ci-dessus sur les tailles appropriées. Toutes les choses principales sont déclenchées par l'événement OnDrawItem ; c'est ici que vous redessinerez le menu et effectuerez les paramètres spéciaux. Par exemple, pour redessiner un élément de menu dans la police Times New Roman, procédez comme suit :
procédure TForm1.Times1DrawItem(Sender: TObject;
ACanvas : TCanvas ; ARect : TRect ; Sélectionné : Booléen );
commencer
ACanvas.Font.Name := 'Times New Roman';
ACanvas.TextOut(ARect.Left+1, ARect.Top+1,
(Expéditeur en tant que TMenuItem).Caption);
fin;
Ce code est cependant défectueux. S'il est exécuté, la légende du menu sera alignée avec la bordure gauche du menu. Ce n'est généralement pas le comportement par défaut de Windows. Il y a donc un espace pour placer des bitmaps et des coches dans le menu. vous devez calculer l'espace nécessaire pour cette coche avec un code similaire à celui illustré dans la figure 1. La figure 2 montre le menu résultant.
Cependant ce code est défectueux. Si vous exécutez ce code, la légende de l'élément de menu sera alignée à gauche de l'élément de menu. Ce n'est pas le comportement par défaut de Windows. Normalement, il y a un espace sur le côté gauche du menu pour une image BMP et une sélection. marque. Par conséquent, vous devez utiliser du code pour calculer l’espace nécessaire pour placer l’indicateur de sélection, comme le montre la figure 1. La figure 2 montre le menu en action.
procédure TForm1.Times2DrawItem(Sender: TObject;
ACanvas : TCanvas ; ARect : TRect ; Sélectionné : Booléen );
var
dwCheck : Entier ;
Légende du menu : chaîne ;
commencer
// Récupère les dimensions de la coche.
Obtenez le nombre de pixels requis pour le logo de sélection
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// Ajuste la position gauche.
Ajuster la position gauche
ARect.Left := ARect.Left + LoWord(dwCheck) + 1;
MenuCaption := (Expéditeur en tant que TMenuItem).Caption;
// Le nom de la police est la légende du menu.
ACanvas.Font.Name := 'Times New Roman';
// Dessine le texte.
dessiner du texte
DrawText(ACanvas.Handle, PChar(MenuCaption),
Longueur(MenuCaption), ARect, 0);
fin;
Figure 1 : Ce gestionnaire d'événements OnDrawItem place correctement le texte des éléments de menu.
[Le traducteur a omis toutes les figures, les mêmes ci-dessous]
Figure 2 : Un menu dessiné avec des polices personnalisées.
Si le texte est trop grand pour être dessiné dans le menu, Windows le coupera pour l'adapter. Par conséquent, vous devez définir la taille de l'élément de menu afin que tout le texte puisse être dessiné. C'est le rôle du gestionnaire d'événements OnMeasureItem illustré dans la figure 3. .
Si le texte est trop long, Windows le recadrera automatiquement pour l'adapter. Par conséquent, vous devez dimensionner le menu de manière à ce que tout le texte puisse être affiché. La même chose devrait être vraie dans l'événement OnMeasureItem, comme le montre la figure 3.
procédure TForm1.Times2MeasureItem(Sender: TObject;
ACanvas : TCanvas ; var Largeur, Hauteur : Entier);
commencer
ACanvas.Font.Name := 'Times New Roman';
ACanvas.Font.Style := [];
// La largeur est l'espace du contrôle du menu
Cette longueur est la longueur de la marque de sélection du menu
// plus la largeur du texte de l'élément.
Plus la longueur de l'élément de menu
Largeur := GetSystemMetrics(SM_CXMENUCHECK) +
ACanvas.TextWidth((Expéditeur en tant que TMenuItem).Caption) + 2;
Hauteur := ACanvas.TextHeight(
(Expéditeur en tant que TMenuItem).Caption) + 2 ;
fin;
Figure 3 : Ce gestionnaire d'événements OnMeasureItem garantit qu'un élément tient dans son menu.
Formes et bitmaps personnalisés
Configurer des graphiques et des bitmaps
Il est également possible de personnaliser les éléments de menu en incluant des bitmaps ou d'autres formes. Pour ajouter un bitmap, attribuez simplement un fichier bitmap à la propriété TMenuItem.Bitmap - avec l'inspecteur d'objets au moment de la conception ou avec du code au moment de l'exécution pour dessiner des rectangles colorés. comme légende d'un élément de menu, vous pouvez utiliser le gestionnaire d'événements OnDrawItem illustré dans la figure 4. La figure 5 montre le résultat.
Il est possible de configurer des menus avec des bitmaps et d'autres graphiques. Pour ajouter un bitmap, attribuez simplement un fichier BMP à la propriété Bitmap de TmenuItem dans l'inspecteur d'objets au moment de la conception, ou utilisez du code au moment de l'exécution. Pour remplacer le titre du menu par un rectangle coloré, vous pouvez utiliser l'événement OnDrawItem, comme illustré dans la figure 4. Les résultats sont présentés à la figure 5.
procédure TForm1.ColorDrawItem(Sender: TObject;
ACanvas : TCanvas ; ARect : TRect ; Sélectionné : Booléen );
var
dwCheck : Entier ;
Couleur du menu : TCouleur ;
commencer
// Récupère les dimensions de la coche.
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
ARect.Left := ARect.Left + LoWord(dwCheck);
// Convertit la légende de l'élément de menu en couleur.
Convertir le titre de l'élément de menu en couleur
Couleur du menu :=
StringToColor((Expéditeur en tant que TMenuItem).Caption);
// Change la couleur du pinceau du canevas.
Changer la couleur du pinceau de la toile
ACanvas.Brush.Color := MenuColor;
// Dessine le rectangle Si l'élément est sélectionné,
Dessine un rectangle si l'élément de menu est sélectionné
// dessine une bordure.
tracer des frontières
si sélectionné alors
ACanvas.Pen.Style := psSolid
autre
ACanvas.Pen.Style := psClear;
ACanvas.Rectangle(ARect.Left, ARect.Top,
ARect.Droite, ARect.Bottom);
fin;
Figure 4 : Utilisation de l'événement OnDrawItem pour dessiner des rectangles colorés sur les éléments de menu.
Figure 5 : Un menu comportant des rectangles colorés comme éléments.
Il n'y a qu'un seul problème. Si vous utilisez Delphi 5, vous devez définir la propriété AutoHotkeys du menu sur maManual. Si vous la laissez par défaut, maAutomatic, Delphi ajoutera une esperluette (&) à la légende, ce qui brisera ce problème. Une autre solution consiste à supprimer l'esperluette avec la fonction StripHotKey.
L'approche la plus populaire consiste à définir la propriété AutoHotkeys du menu sur maManual si vous utilisez Delphi 5. Si vous ne le faites pas et laissez la valeur par défaut de maAutomatic, Delphi ajoutera automatiquement une esperluette au titre, ce qui cassera le code. Une autre solution consiste à utiliser la fonction StripHotKey pour supprimer l'esperluette.
Une autre façon d'utiliser les événements OnDrawItem et OnMeasureItem consiste à écrire du texte verticalement dans un menu (comme le montre la figure 7). Pour ce faire, vous devez créer une police pivotée. Ceci n'est possible qu'à l'aide de la fonction API Windows CreateFont ou CreateLogFont (voir). l'astuce "Texte pivoté" plus loin dans cet article). Ensuite, vous devez le dessiner dans le gestionnaire d'événement OnDrawItem. Cet événement est déclenché à chaque fois qu'un élément de menu est dessiné, donc si un menu a. 20 éléments, il sera dessiné 20 fois. Pour le rendre plus rapide, le texte vertical sera dessiné uniquement lorsque l'élément de menu est sélectionné (puisqu'il n'y a qu'un seul élément de menu sélectionné à la fois). La figure 6 montre comment cela est implémenté avec le code. , et la figure 7 montre le résultat d'exécution.
Une autre utilisation des événements OnDrawItem et OnMeasureItem consiste à écrire du texte vertical à côté du menu (comme illustré dans la figure 7). Pour ce faire, vous devez créer une police pivotée. La seule façon est d'utiliser la fonction CreateFont ou CreateLogFont de l'API Windows (voir la technique du « texte pivoté » plus loin dans cet article). Vous devez donc le redessiner dans l'événement OnDrawItem. Cet événement est exécuté lorsque l'élément de menu est retiré, donc si un menu contient 20 éléments, il sera exécuté 20 fois. Pour le rendre plus rapide, le texte vertical peut être redessiné à chaque fois qu'un élément de menu est sélectionné (bien qu'un seul élément de menu soit sélectionné à la fois). La figure 6 montre comment le code s'exécute, tandis que la figure 7 montre les résultats.
procédure TForm1.VerticalDrawItem(Sender: TObject;
ACanvas : TCanvas ; ARect : TRect ; Sélectionné : Booléen );
var
lf : TLogFont;
Ancienne police : HFont ;
clFore, clBack : LongInt ;
Rectangulaire : TRect ;
dwCheck : LongInt;
MenuHauteur : Entier ;
commencer
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// Cela sera fait une fois, lorsque l'élément est sélectionné.
Ceci sera exécuté lorsque l’élément de menu est sélectionné
si sélectionné, commencez
// Crée une police pivotée.
Créer une police pivotée
FillChar(lf, SizeOf(lf), 0);
lf.lfHauteur := -14;
lf.lfEscapement := 900;
lf.lfOrientation := 900;
lf.lfWeight := Fw_Bold;
StrPCopy(lf.lfFaceName, 'Arial');
// Sélectionnez cette police à dessiner.
Sélectionnez cette police pour dessiner
OldFont := SelectObject(ACanvas.Handle,
CreateFontIndirect(lf));
// Change les couleurs de premier plan et d'arrière-plan.
Changer les couleurs de premier plan et d'arrière-plan
clFore := SetTextColor(ACanvas.Handle, clSilver);
clBack := SetBkColor(ACanvas.Handle, clBlack);
// Récupère la hauteur du menu.
Obtenir la hauteur du menu
Hauteur du menu := (ARect.Bottom-ARect.Top) *
((Expéditeur en tant que TMenuItem).Parent en tant que TMenuItem).Count;
Rectang := Rect(-1, 0, dwCheck-1, MenuHeight);
// Dessine le texte.
dessiner du texte
ExtTextOut(ACanvas.Handle, -1, MenuHeight, Eto_Clipped,
@Rectang, 'Made in Borland', 15, zéro);
// Retourne à l'état d'origine.
Retour à l'état d'origine
SupprimerObject(SelectObject(ACanvas.Handle, OldFont));
SetTextColor(ACanvas.Handle, clFore);
SetBkColor(ACanvas.Handle, clBack);
fin;
// Dessine le vrai texte du menu.
Dessiner le vrai texte d'un élément de menu
ARect.Left := ARect.Left + LoWord(dwCheck) + 2;
DrawText(ACanvas.Handle,
PChar((Expéditeur en tant que TMenuItem).Caption),
Longueur((Expéditeur en tant que TMenuItem).Caption), ARect, 0);
fin;
Figure 6 : Utilisation d'OnDrawItem pour dessiner du texte vertical sur un menu.
Figure 7 : Menu avec texte vertical.
Un détail délicat est de savoir par où commencer à dessiner le texte. Il doit commencer au bas du dernier élément du menu. Pour obtenir sa position, nous obtenons la hauteur de l'élément de menu, en utilisant :
Vous devez savoir par où commencer à dessiner du texte. Cela devrait commencer au bas du dernier élément du menu. Afin d'obtenir cette position, nous obtenons la hauteur de l'élément de menu comme suit :
ARect.Haut - ARect.Bas
et multipliez-le par le nombre d'éléments dans le menu :
Et multiplié par le nombre d'éléments de menu :
(((Expéditeur en tant que TMenuItem).Parent en tant que TMenuItem).Count)
Texte pivoté
texte pivoté
L'API Windows vous permet de dessiner du texte sous n'importe quel angle. Pour ce faire dans Delphi, vous devez utiliser la fonction API CreateFont ou CreateFontIndirect est déclarée comme indiqué dans la figure 8.
L'API Windows vous permet de dessiner du texte sous n'importe quel angle. Pour ce faire dans Delphi, vous devez utiliser les deux fonctions API CreateFont ou CreateFontIndirect. La figure 8 montre comment CreateFont est déclaré.
fonction CreateFont(
nHeight, // Hauteur logique de la police.
nWidth, // Largeur logique moyenne des caractères.
nEscapement, // Angle d'échappement. Angle de rotation.
nOrientation, // Angle d'orientation de la ligne de base.
fnWeight : Integer ; // La sous-propriété de poids de la police.
fdwItalic, // Indicateur d'attribut italique. Est-il en italique ?
fdwUnderline, // Indicateur d'attribut de soulignement.
fdwStrikeOut, // Indicateur d'attribut barré s'il faut barrer l'attribut.
fdwCharSet // Identifiant du jeu de caractères.
fdwOutputPrecision, // Précision de sortie.
fdwClipPrecision, // Précision de découpage.
fdwQuality, // Qualité de sortie.
fdwPitchAndFamily : DWORD ; // Emplacement et famille.
lpszFace : PChar // Pointeur vers la chaîne du nom de la police.
) : HFONT ;
Figure 8 : Déclaration Object Pascal pour la fonction API Windows CreateFont.
Bien que cette fonction comporte de nombreux paramètres, vous souhaiterez généralement modifier uniquement un ou deux attributs du texte. Dans de tels cas, vous devez plutôt utiliser la fonction CreateFontIndirect. Elle ne prend qu'un seul argument : un enregistrement de type TLogFont, comme le montre la figure. 9.
Bien que cette fonction prenne de nombreux paramètres, vous n'avez généralement besoin de modifier qu'une ou deux propriétés du texte. Dans ce cas, vous utiliserez plutôt la fonction CreateFontIndirect. Il ne nécessite qu'un seul paramètre : un paramètre de type d'enregistrement de TlogFont, comme le montre la figure 9.
tagLOGFONTA = enregistrement compressé
lfHauteur : entier long ;
lfWidth : entier long ;
lfEscapement : entier long ;
lfOrientation : entier long ;
lfPoids : entier long ;
lfItalique : octet ;
lfSouligné : Octet ;
lfStrikeOut : octet ;
lfCharSet : octet ;
lfOutPrecision : octet ;
lfClipPrecision : octet ;
lfQualité : octet ;
lfPitchAndFamily : octet ;
lfFaceName : tableau[0..LF_FACESIZE - 1] d'AnsiChar ;
fin;
TLogFontA = tagLOGFONTA;
TLogFont = TLogFontA;
Figure 9 : L'enregistrement TLogFont.
En regardant cet enregistrement, vous remarquerez que ses membres correspondent aux paramètres de la fonction CreateFont. L'avantage d'utiliser cette combinaison fonction/enregistrement est que vous pouvez remplir les membres de l'enregistrement avec une police connue à l'aide de la fonction API GetObject, modifier les membres vous-même. souhaitez et créez la nouvelle police.
Si vous examinez attentivement ce type d'enregistrement, vous constaterez que ses membres sont très similaires aux paramètres de la fonction CreateFont. L'avantage d'utiliser cette combinaison fonction/enregistrement est que vous pouvez utiliser la fonction API GetObject pour remplir les valeurs membres de cet enregistrement avec une police connue, puis modifier la valeur membre que vous souhaitez modifier pour générer une nouvelle police.
Pour dessiner du texte pivoté, le seul membre que vous devez modifier est lfEscapement, qui définit l'angle du texte en dixièmes de degrés. Ainsi, si vous souhaitez que le texte soit dessiné à 45 degrés, vous devez définir lfEscapement sur 450.
Pour dessiner du texte pivoté, le seul membre que vous devez modifier est lfEscapement, qui définit l'angle de la police en dixièmes de degré. Donc, si vous voulez que le personnage pivote de 45 degrés, vous devez définir
lfEscapement est de 450.
Notez qu'il existe des indicateurs pour dessiner du texte en italique, souligné et barré, mais il n'y a pas d'indicateur pour dessiner du texte en gras. Cela se fait avec le membre lfWeight, un nombre compris entre 0 et 1000. 400 est un texte normal, des valeurs supérieures. dessinez du texte en gras et les valeurs en dessous dessinent du texte clair.
Notez qu'il existe de nombreux marqueurs pour mettre en italique, souligner et surligner le texte, mais il n'y a aucun marqueur pour mettre le texte en gras. En effet, le membre lfWeight est utilisé à la place et la valeur de ce membre est comprise entre 0 et 1 000. 400 est la valeur normale, tout ce qui est au-dessus est en gras et tout ce qui est en dessous est mince.
Le code de la figure 10 dessine le texte selon des angles allant de 0 degrés à 360 degrés, à des intervalles de 20 degrés. Il s'agit du gestionnaire d'événements OnPaint du formulaire. Le texte est donc redessiné à chaque fois que le formulaire est peint.
Le code de la figure 10 dessine des caractères tous les 20 degrés de 0 à 360 degrés. Ceci est déclenché dans l'événement OnPaint du formulaire, de sorte que le texte est redessiné à chaque fois que le formulaire est peint. L’effet est visible sur la figure 11.
procédure TForm1.FormPaint(Expéditeur : TObject);
var
Ancienne Police, Nouvelle Police : hFont ;
LogFont : TLogFont ;
je : Entier ;
commencer
// Récupère la poignée de la police du canevas.
Obtient le handle de l'objet police du formulaire
OldFont := Canvas.Font.Handle;
je := 0;
// Dessin transparent.
Définir la propriété de transparence
SetBkMode(Canvas.Handle, Transparent);
// Remplir la structure LogFont avec des informations
Remplissez la structure LogFont avec des informations
// à partir de la police actuelle.
à partir de la police actuelle
GetObject(OldFont, Sizeof(LogFont), @LogFont);
// Les angles vont de 0 à 360.
de 0 à 360 degrés
alors que je < 3600 commence
// Réglez l'échappement sur un nouvel angle.
Définir l'orientation du texte sur un nouvel angle
LogFont.lfEscapement := i;
//Créer une nouvelle police.
Créer une nouvelle police
NewFont := CreateFontIndirect(LogFont);
// Sélectionnez la police à dessiner.
Sélectionnez les polices pour la sortie
SelectObject(Canvas.Handle, NewFont);
// Dessine du texte au milieu du formulaire.
Texte de sortie au milieu du formulaire
TextOut(Canvas.Handle, ClientWidth div 2,
ClientHeight div 2, 'Texte pivoté', 21);
// Nettoyer.
Clair
SupprimerObject(SelectObject(Canvas.Handle, OldFont));
// Incrémente l'angle de 20 degrés.
incréments tous les 20 degrés
Inc(je, 200);
fin;
fin;
Figure 10 : Code pour dessiner du texte pivoté par intervalles de 20 degrés.
Figure 11 : Texte pivoté à 360 degrés.
La police du formulaire est définie sur Arial, une police TrueType. Ce code fonctionne uniquement avec les polices TrueType ; les autres types de polices ne prennent pas en charge la rotation du texte. Pour obtenir les paramètres de police actuels et remplir la structure TLogFont, vous devez utiliser la fonction API GetObject. Le code de la figure 12 montre comment remplir et afficher les paramètres TLogFont pour la police du formulaire.
La police de ce formulaire est Arial, une police TrueType. Ce code s'exécute uniquement sous les polices TrueType ; les autres polices ne prennent pas en charge la rotation du texte. Afin d'obtenir les paramètres de police actuels et de remplir la structure TlogFont, vous devez utiliser la fonction API GetObject. Dans le code de la figure 12, vous pouvez voir comment remplir et afficher les paramètres TlogFont dans le formulaire.
procédure TForm1.Info1Click(Expéditeur : TObject);
var
LogFont : TLogFont ;
commencer
// Remplir la structure LogFont avec des informations
Remplissez les valeurs des membres de la structure LogFont
// à partir de la police actuelle.
à partir de la police actuelle
GetObject(Canvas.Font.Handle, Sizeof(LogFont), @LogFont);
// Afficher les informations sur la police.
Afficher les informations sur la police
avec LogFont, faites ShowMessage (
'lfHeight : ' + IntToStr(lfHeight) + #13 +
'lfWidth : ' + IntToStr(lfWidth) + #13 +
'lfEscapement : '+IntToStr(lfEscapement) + #13 +
'lfOrientation : ' + IntToStr(lfOrientation) + #13 +
'lfWeight : ' + IntToStr(lfWeight) + #13 +
'lfItalic : ' + IntToStr(lfItalic) + #13 +
'lfUnderline : ' + IntToStr(lfUnderline) + #13 +
'lfStrikeOut : ' + IntToStr(lfStrikeOut) + #13 +
'lfCharSet : ' + IntToStr(lfCharSet) + #13 +
'lfOutPrecision : ' + IntToStr(lfOutPrecision) + #13 +
'lfClipPrecision : ' + IntToStr(lfClipPrecision) + #13 +
'lfQuality : ' + IntToStr(lfQuality) + #13 +
'lfPitchAndFamily : '+IntToStr(lfPitchAndFamily) + #13 +
'lfFaceName : ' + chaîne (lfFaceName));
fin;
Figure 12 : Obtention et affichage des attributs de police.
Une fois que vous avez les paramètres dans une structure TLogFont, le seul changement restant est de définir lfEscapement sur l'angle souhaité et de créer une nouvelle police avec CreateFontIndirect. Avant d'utiliser cette nouvelle police, elle doit être sélectionnée avec SelectObject. Une autre façon consiste à attribuer le handle. de cette nouvelle police à la poignée de la police du canevas, avant de dessiner le texte. Après avoir dessiné le texte, ce travail doit être inversé ; l'ancienne police doit être sélectionnée et la nouvelle police supprimée. n'est pas supprimé, il y aura une fuite de mémoire et - si la routine est exécutée plusieurs fois - Windows (en particulier 95/98) manquera de ressources et plantera.
Une fois que vous avez configuré la structure TlogFont, il ne reste plus qu'à modifier la valeur de lfEscapement par la valeur cible et à utiliser CreateFontIndirect pour générer une nouvelle police. Avant d'utiliser cette nouvelle police, vous devez utiliser SelectObject pour la sélectionner. Une autre méthode consiste à utiliser le handle de ce nouvel objet police avec le handle de l’objet police du canevas du formulaire avant de dessiner le texte. Une fois le texte dessiné, le processus commence ; l'ancienne police doit être sélectionnée et la nouvelle police supprimée. Si la nouvelle police n'est pas supprimée, cela provoquera une fuite de mémoire, et -----si le programme est exécuté plusieurs fois------ Windows (en particulier 95/98) manquera de ressources, et
accident.
Lignes élégantes
lignes populaires
Lorsque vous dessinez des lignes, les pixels individuels n'ont généralement pas d'importance ; vous définissez simplement le style de ligne, et il est dessiné par Windows. Parfois, cependant, vous devez faire quelque chose de spécial et dessiner un style de ligne non fourni par Windows. Cela peut être fait. à l'aide d'une fonction API Windows nommée LineDDA, définie dans la figure 13.
Lorsque vous dessinez des lignes, les pixels individuels n'ont généralement pas d'importance ; vous définissez simplement le type de ligne et ce sera à Windows de le dessiner. Parfois, cependant, vous souhaitez créer des types de lignes spéciaux que Windows ne propose pas. Ceci peut être réalisé en utilisant une fonction API appelée LineDDA, dont la définition est visible dans la figure 13.
fonction LigneDDA(
nXStart, // coordonnée x du point de départ de la ligne.
Point de départ de la coordonnée X
nYStart, // coordonnée y du point de départ de la ligne.
Point de départ de la coordonnée Y
nXEnd, // coordonnée x du point final de la ligne.
Point final de la coordonnée X
YEnd : Entier ; // coordonnée y du point final de la ligne.
Point final de la coordonnée Y
// Adresse de la fonction de rappel définie par l'application.
L'adresse de la fonction de rappel définie par l'application
lpLineFunc : TFNLineDDAProc ;
lpData : LPARAM // Adresse des données définies par l'application.
Adresse des données définies par l'application
) : BOOL ;
Figure 13 : Déclaration Object Pascal pour la fonction API Windows, LineDDA.
Les quatre premiers paramètres sont les points de début et de fin de la ligne. Le cinquième paramètre est une fonction de rappel qui sera appelée chaque fois qu'un pixel doit être dessiné ici. Le dernier paramètre est un paramètre utilisateur qui sera dessiné. transmis à la fonction de rappel. Vous pouvez transmettre n'importe quel entier ou pointeur à la fonction, car il s'agit d'un LParam (dans Win32, il est traduit en Longint). La fonction de rappel doit prendre la forme indiquée ici :
Les quatre premiers paramètres sont les points de début et de fin de la ligne. Le cinquième paramètre est une fonction de rappel qui sera appelée à chaque fois qu'un pixel est dessiné. Vous pouvez écrire sur votre processus de dessin ici. Le dernier paramètre est défini par l'utilisateur et peut être transmis à la fonction de rappel. Vous pouvez transmettre n'importe quel entier ou pointeur à cette fonction car c'est
Un type Lparam (dans WIN32, il est interprété comme un type Longint). Cette fonction de rappel doit utiliser un formulaire comme celui-ci :
procédure CallBackDDA(x, y : Integer ;
UserParam : LParam );
où x et y sont les coordonnées du point dessiné et UserParam est un paramètre transmis à la fonction. Cette fonction doit être déclarée comme stdcall. La routine de la figure 14 dessine une ligne de bitmaps et la figure 15 montre le résultat.
Ici, X et Y sont les points de coordonnées dessinés et UserParam est un paramètre. Cette fonction doit être sous-définie comme stdcall. Le programme de la figure 14 trace une ligne BMP et la figure 15 affiche les résultats.
taper
TForm1 = classe(TForm)
ImageList1 : TImageList ;
procédure FormPaint(Expéditeur : TObject);
procédure FormResize(Expéditeur : TObject);
fin;
var
Formulaire1 : TForm1 ;
procédure CallDDA(x, y : Integer ; Form : TForm1) ;
mise en œuvre
{ $R *.DFM }
procédure CallDDA(x, y : Integer ; Form : TForm1) ;
commencer
si x mod 13 = 0 alors
Form.ImageList1.Draw(Form.Canvas, x, y, 0);
fin;
procédure TForm1.FormPaint(Expéditeur : TObject);
commencer
LineDDA(0, 0, ClientLargeur, ClientHauteur,
@CallDDA, Integer(Self));
fin;
procédure TForm1.FormResize(Expéditeur : TObject);
commencer
Invalider;
fin;
Figure 14 : Code pour tracer une ligne de bitmaps.
Figure 15 : Fenêtre avec une ligne personnalisée.
Cette routine gère l'événement OnPaint du formulaire, en appelant LineDDA, donc chaque fois que le formulaire doit être peint, elle redessine la ligne. Un autre événement géré est OnResize, qui invalide la zone client du formulaire, donc la ligne doit être redessinée lorsque quelqu'un la modifie. size. La fonction de rappel LineDDA, CallDDA, est très simple. À chaque 13ème point, elle dessine le bitmap stocké dans ImageList. Comme vous pouvez le remarquer, Self est passé comme dernier paramètre. la fonction de rappel, afin qu'elle puisse accéder aux données de l'instance.
Ce programme gère l'événement OnPaint du formulaire, en appelant LineDDA, il redessinera donc la ligne à chaque fois que le formulaire est peint. Un autre événement est OnResize, qui invalide la zone client du formulaire afin que les lignes soient redessinées lorsque quelqu'un modifie sa taille. La fonction de rappel LineDDA et CallDDA sont très simples. Chaque fois qu'il est appelé 13 fois, il dessinera le bitmap stocké dans ImageList. Peut-être avez-vous remarqué que SELF est passé comme dernier paramètre à la fonction de rappel, afin qu'elle puisse accéder aux données du programme.
Conclusion
en conclusion
Depuis que le dessin du propriétaire a été exposé sur TMainMenu dans Delphi 4, il existe de nombreuses façons d'augmenter vos menus. En utilisant les techniques dont nous avons parlé ici, vous pouvez facilement améliorer les menus de votre application Delphi avec du texte, des bitmaps et des couleurs personnalisés.
Maintenant que le dessin du propriétaire est apparu dans TmainMenu dans Delphi 4, il existe de nombreuses façons d'étendre les fonctionnalités de votre menu. En utilisant les techniques évoquées ci-dessus, vous pouvez facilement améliorer la fonctionnalité de menu de votre application DELPHI avec du texte, des bitmaps et des couleurs personnalisés.