Erstellung der seltsamen Speisekarte von DELPHI
Übersetzer: Li Junyu E-Mail: [email protected], [email protected]
Benutzerdefinierte Menüs, Text, Linien / Delphi 4, 5
Benutzerdefiniertes Menü, Text, Zeile/Delphi 4, 5
Ausgefallene Menüs usw.
Bizarre Menüs usw.
Benutzerdefinierte Menüs, gedrehter Text und Sonderlinien
Benutzerdefinierte Menüs, gedrehter Text und spezielle Zeilen
Vor Delphi 4 war es schwierig, ein Menü anzupassen (ein Bitmap hinzuzufügen, eine Schriftart zu ändern usw.), da die Besitzerzeichnung (dh benutzerdefinierte Zeichnung) – obwohl von Windows implementiert – nicht von der TMainMenu-Klasse verfügbar gemacht wurde. Diese Situation wurde jedoch behoben und wir können mit den Menüs unseren Willen durchsetzen.
Vor Delphi 4 war es schwierig, ein Menü anzupassen (z. B. ein BMP-Bild hinzuzufügen, die Schriftart zu ändern usw.), da das Besitzerzeichnungsereignis (d. h. das benutzerdefinierte Zeichnungsereignis) – obwohl es von Windows ausgeführt wird – nicht angezeigt wird TMainMenu-Klasse. Seit Delphi 4,
Diese Situation hat sich geändert und wir haben jetzt die Möglichkeit, Menüs anzupassen.
In diesem Artikel werden einige Techniken hervorgehoben, mit denen Sie das Erscheinungsbild von Menüs in Ihren Delphi-Anwendungen anpassen können. In diesem Artikel besprechen wir die Platzierung von Text, die Größe von Menüs, die Zuweisung von Schriftarten und die Verwendung von Bitmaps und Formen bietet außerdem Techniken zum Erstellen von gedrehtem Text und benutzerdefinierten Linien. Alle in diesem Artikel besprochenen Techniken werden in PRojects zum Herunterladen demonstriert.
Dieser Artikel konzentriert sich auf einige Techniken, mit denen Sie das Erscheinungsbild der Menüs in Ihren DELPHI-Anwendungen anpassen können. Wir behandeln die Textplatzierung, die Menügröße, die Schriftarteinstellungen und die Verbesserungen mit BMP-Dateien sowie den Anzeigeeffekt des Menüs . Nur zum Spaß wird in diesem Artikel auch eine Nahaufnahme der Techniken zum Drehen von Text und benutzerdefinierten Linien vorgestellt. Alle in diesem Artikel besprochenen Techniken wurden in Projektdateien debuggt und können online heruntergeladen werden.
Benutzerdefinierte Schriftarten und -größen
Legen Sie Schriftart und -größe fest
Um ein benutzerdefiniertes Menü zu erstellen, setzen Sie die OwnerDraw-Eigenschaft der Menükomponente -TMainMenu oder TPopupMenu - auf True und stellen Sie Ereignishandler für die Ereignisse OnDrawItem und OnMeasureItem bereit. Ein OnMeasureItem-Ereignishandler wird beispielsweise wie folgt deklariert:
Um ein benutzerdefiniertes Menü zu erstellen, setzen Sie die OwnerDraw-Eigenschaft der TmainMenu- oder TpopupMenu-Komponente auf TRUE und erstellen Sie die Ereignisprozeduren OnDrawItem und OnMeasureItem. Beispielsweise könnte eine OnMeasureItem-Ereignisprozedur wie folgt deklariert werden:
procedure TForm1.Option1MeasureItem(Sender: TObject;
ACanvas: TCanvas; var Breite, Höhe: Ganzzahl);
Legen Sie die Variablen „Breite“ und „Höhe“ fest, um die Größe des Menüelements anzupassen. Der OnDrawItem-Ereignishandler ist der Ort, an dem Sie Ihr Menü zeichnen und alle speziellen Einstellungen vornehmen, um die Menüoption mit der Schriftart Times New Roman zu zeichnen , Sie sollten zum Beispiel so etwas tun:
Stellen Sie die Variablen „Breite“ und „Höhe“ des Menüelements in der obigen Ereignisprozedur auf die entsprechenden Größen ein. Alle wichtigen Dinge werden durch das Ereignis „OnDrawItem“ ausgelöst. Um beispielsweise einen Menüpunkt in der Schriftart Times New Roman neu zu zeichnen, gehen Sie wie folgt vor:
procedure TForm1.Times1DrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect; Ausgewählt: Boolean);
beginnen
ACanvas.Font.Name := 'Times New Roman';
ACanvas.TextOut(ARect.Left+1, ARect.Top+1,
(Absender als TMenuItem).Caption);
Ende;
Dieser Code ist jedoch fehlerhaft, wenn er am linken Rand des Menüs ausgerichtet wird. Dies entspricht normalerweise nicht dem Standardverhalten von Windows. Daher gibt es Platz zum Einfügen von Bitmaps und Häkchen. Sie sollten den für dieses Häkchen benötigten Platz mit einem Code wie in Abbildung 1 berechnen. Abbildung 2 zeigt das resultierende Menü.
Dieser Code ist jedoch fehlerhaft. Wenn Sie diesen Code ausführen, wird die Beschriftung des Menüelements links vom Menüelement ausgerichtet. Dies ist nicht das Standardverhalten von Windows. Normalerweise gibt es auf der linken Seite des Menüs einen Platz für ein BMP-Bild und eine Auswahl markieren. Daher sollten Sie Code verwenden, um zu berechnen, wie viel Platz zum Platzieren der Auswahlflagge benötigt wird, wie in Abbildung 1 dargestellt. Abbildung 2 zeigt das Menü in Aktion.
procedure TForm1.Times2DrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect; Ausgewählt: Boolean);
var
dwCheck: Ganzzahl;
MenuCaption: string;
beginnen
// Die Häkchendimensionen abrufen.
Ermitteln Sie die Anzahl der für das Auswahllogo erforderlichen Pixel
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// Linke Position anpassen.
Linke Position anpassen
ARect.Left := ARect.Left + LoWord(dwCheck) + 1;
MenuCaption := (Absender als TMenuItem).Caption;
// Der Schriftartname ist die Menüüberschrift.
ACanvas.Font.Name := 'Times New Roman';
// Zeichne den Text.
Text zeichnen
DrawText(ACanvas.Handle, PChar(MenuCaption),
Länge(MenuCaption), ARect, 0);
Ende;
Abbildung 1: Dieser OnDrawItem-Ereignishandler platziert den Menüelementtext korrekt.
[Der Übersetzer hat alle Abbildungen weggelassen, dasselbe unten]
Abbildung 2: Ein mit benutzerdefinierten Schriftarten gezeichnetes Menü.
Wenn der Text zu groß ist, um in das Menü gezeichnet zu werden, wird er von Windows passend zugeschnitten. Daher sollten Sie die Größe des Menüelements so einstellen, dass der gesamte Text gezeichnet werden kann. Dies ist die Rolle des in Abbildung 3 gezeigten OnMeasureItem-Ereignishandlers .
Wenn der Text zu lang ist, schneidet Windows ihn automatisch passend zu. Daher sollten Sie das Menü so dimensionieren, dass der gesamte Text angezeigt werden kann. Dasselbe sollte auch für das OnMeasureItem-Ereignis gelten, das in Abbildung 3 zu sehen ist.
procedure TForm1.Times2MeasureItem(Sender: TObject;
ACanvas: TCanvas; var Breite, Höhe: Ganzzahl);
beginnen
ACanvas.Font.Name := 'Times New Roman';
ACanvas.Font.Style := [];
// Die Breite ist der Platz des Menüs
Diese Länge ist die Länge der Menüauswahlmarkierung
// plus die Breite des Artikeltextes.
Plus die Länge des Menüpunkts
Breite := GetSystemMetrics(SM_CXMENUCHECK) +
ACanvas.TextWidth((Sender as TMenuItem).Caption) + 2;
Höhe := ACanvas.TextHeight(
(Absender als TMenuItem).Caption) + 2;
Ende;
Abbildung 3: Dieser OnMeasureItem-Ereignishandler stellt sicher, dass ein Element in sein Menü passt.
Benutzerdefinierte Formen und Bitmaps
Richten Sie Grafiken und Bitmaps ein
Es ist auch möglich, Menüelemente durch das Einbinden von Bitmaps oder anderen Formen anzupassen, indem Sie der Eigenschaft TMenuItem.Bitmap einfach eine Bitmap-Datei zuweisen – mit dem Objektinspektor zur Entwurfszeit oder mit Code zur Laufzeit Als Überschrift eines Menüelements können Sie den in Abbildung 4 gezeigten OnDrawItem-Ereignishandler verwenden. Abbildung 5 zeigt das Ergebnis.
Es ist möglich, Menüs mit Bitmaps und anderen Grafiken einzurichten, indem Sie zur Entwurfszeit einfach eine BMP-Datei der Bitmap-Eigenschaft von TmenuItem zuweisen. Eine Zuweisung ist auch zur Laufzeit möglich. Um den Menütitel durch ein farbiges Rechteck zu ersetzen, können Sie das OnDrawItem-Ereignis verwenden, wie in Abbildung 4 dargestellt. In Abbildung 5 sind die Ergebnisse dargestellt.
procedure TForm1.ColorDrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect; Ausgewählt: Boolean);
var
dwCheck: Ganzzahl;
MenuColor: TColor;
beginnen
// Die Häkchendimensionen abrufen.
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
ARect.Left := ARect.Left + LoWord(dwCheck);
// Konvertieren Sie die Beschriftung des Menüelements in eine Farbe.
Konvertieren Sie den Titel des Menüelements in eine Farbe
MenüFarbe :=
StringToColor((Sender as TMenuItem).Caption);
// Ändern Sie die Farbe des Leinwandpinsels.
Ändern Sie die Pinselfarbe der Leinwand
ACanvas.Brush.Color := MenuColor;
// Zeichnet das Rechteck. Wenn das Element ausgewählt ist,
Zeichnet ein Rechteck, wenn das Menüelement ausgewählt ist
// Zeichne einen Rand.
Grenzen ziehen
wenn ausgewählt, dann
ACanvas.Pen.Style := psSolid
anders
ACanvas.Pen.Style := psClear;
ACanvas.Rectangle(ARect.Left, ARect.Top,
ARect.Right, ARect.Bottom);
Ende;
Abbildung 4: Verwenden des OnDrawItem-Ereignisses zum Zeichnen farbiger Rechtecke auf Menüelementen.
Abbildung 5: Ein Menü mit farbigen Rechtecken als Elementen.
Es gibt nur einen Haken: Wenn Sie Delphi 5 verwenden, müssen Sie die AutoHotkeys-Eigenschaft des Menüs auf „maManual“ setzen. Wenn Sie die Standardeinstellung „maAutomatic“ beibehalten, fügt Delphi der Beschriftung ein kaufmännisches Und-Zeichen (&) hinzu, wodurch dies unterbrochen wird Eine andere Lösung besteht darin, das kaufmännische Und-Zeichen mit der StripHotKey-Funktion zu entfernen.
Der beliebtere Ansatz besteht darin, dass Sie bei Verwendung von Delphi 5 die AutoHotkeys-Eigenschaft des Menüs auf maManual setzen sollten. Wenn Sie dies nicht tun und den Standardwert maAutomatic beibehalten, fügt Delphi dem Titel automatisch ein kaufmännisches Und hinzu, wodurch der Code beschädigt wird. Eine andere Lösung besteht darin, die StripHotKey-Funktion zu verwenden, um das kaufmännische Und-Zeichen zu entfernen.
Eine andere Möglichkeit, die Ereignisse „OnDrawItem“ und „OnMeasureItem“ zu verwenden, besteht darin, Text vertikal in ein Menü zu schreiben (siehe Abbildung 7). Dazu müssen Sie eine gedrehte Schriftart erstellen. Dies ist nur mit der Windows-API-Funktion „CreateFont“ oder „CreateLogFont“ möglich (siehe). Der Tipp „Gedrehter Text“ weiter unten in diesem Artikel. Dann müssen Sie ihn im OnDrawItem-Ereignishandler zeichnen. Dieses Ereignis wird jedes Mal ausgelöst, wenn ein Menüelement gezeichnet wird Bei 20 Elementen wird es 20 Mal gezeichnet. Um es schneller zu machen, wird der vertikale Text nur gezeichnet, wenn das Menüelement ausgewählt ist (da jeweils nur ein Menüelement ausgewählt ist). und Abbildung 7 zeigt das Laufzeitergebnis.
Eine weitere Verwendung für die Ereignisse „OnDrawItem“ und „OnMeasureItem“ besteht darin, vertikalen Text neben das Menü zu schreiben (wie in Abbildung 7 dargestellt). Dazu müssen Sie eine gedrehte Schriftart erstellen. Die einzige Möglichkeit besteht darin, die Funktion „CreateFont“ oder „CreateLogFont“ der Windows-API zu verwenden (siehe die Technik „gedrehter Text“ weiter unten in diesem Artikel). Sie müssen es also im OnDrawItem-Ereignis neu zeichnen. Dieses Ereignis wird ausgeführt, wenn das Menüelement herausgezogen wird. Wenn ein Menü also 20 Elemente enthält, wird es 20 Mal ausgeführt. Um es schneller zu machen, kann der vertikale Text jedes Mal neu gezeichnet werden, wenn ein Menüelement ausgewählt wird (obwohl jeweils nur ein Menüelement ausgewählt ist). Abbildung 6 zeigt, wie der Code ausgeführt wird, während Abbildung 7 die Ergebnisse zeigt.
procedure TForm1.VerticalDrawItem(Sender: TObject;
ACanvas: TCanvas; ARect: TRect; Ausgewählt: Boolean);
var
lf: TLogFont;
OldFont:HFont;
clFore, clBack: LongInt;
Rechteck: TRect;
dwCheck: LongInt;
MenuHeight : Ganzzahl;
beginnen
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// Dies wird einmal durchgeführt, wenn das Element ausgewählt wird.
Dies wird ausgeführt, wenn der Menüpunkt ausgewählt wird
Wenn ausgewählt, dann beginnen
// Erstelle eine gedrehte Schriftart.
Erstellen Sie eine gedrehte Schriftart
FillChar(lf, SizeOf(lf), 0);
lf.lfHeight := -14;
lf.lfEscapement := 900;
lf.lfOrientation := 900;
lf.lfWeight := Fw_Bold;
StrPCopy(lf.lfFaceName, 'Arial');
// Wählen Sie diese Schriftart zum Zeichnen aus.
Wählen Sie diese Schriftart zum Zeichnen aus
OldFont := SelectObject(ACanvas.Handle,
CreateFontIndirect(lf));
// Vordergrund- und Hintergrundfarben ändern.
Ändern Sie die Vordergrund- und Hintergrundfarben
clFore := SetTextColor(ACanvas.Handle, clSilver);
clBack := SetBkColor(ACanvas.Handle, clBlack);
// Holen Sie sich die Menühöhe.
Menühöhe abrufen
MenuHeight := (ARect.Bottom-ARect.Top) *
((Sender als TMenuItem).Parent als TMenuItem).Count;
Rectang := Rect(-1, 0, dwCheck-1, MenuHeight);
// Zeichne den Text.
Text zeichnen
ExtTextOut(ACanvas.Handle, -1, MenuHeight, Eto_Clipped,
@Rectang, 'Made in Borland', 15, Null);
// Kehrt in den ursprünglichen Zustand zurück.
Rückkehr zum ursprünglichen Zustand
DeleteObject(SelectObject(ACanvas.Handle, OldFont));
SetTextColor(ACanvas.Handle, clFore);
SetBkColor(ACanvas.Handle, clBack);
Ende;
// Den echten Menütext zeichnen.
Zeichnen Sie echten Menüpunkttext
ARect.Left := ARect.Left + LoWord(dwCheck) + 2;
DrawText(ACanvas.Handle,
PChar((Sender as TMenuItem).Caption),
Length((Sender as TMenuItem).Caption), ARect, 0);
Ende;
Abbildung 6: Verwenden von OnDrawItem zum Zeichnen von vertikalem Text in einem Menü.
Abbildung 7: Menü mit vertikalem Text.
Ein kniffliges Detail besteht darin, zu wissen, wo mit dem Zeichnen des Textes am Ende des letzten Menüpunkts begonnen werden soll. Um seine Position zu ermitteln, ermitteln wir die Höhe des Menüpunkts mithilfe von:
Sie sollten wissen, wo Sie mit dem Zeichnen von Text beginnen sollen. Es sollte am Ende des letzten Menüpunkts beginnen. Um diese Position zu erhalten, ermitteln wir die Höhe des Menüpunkts wie folgt:
ARect.Top - ARect.Bottom
und multiplizieren Sie es mit der Anzahl der Elemente im Menü:
Und multipliziert mit der Anzahl der Menüpunkte:
(((Sender als TMenuItem).Parent als TMenuItem).Count)
Gedrehter Text
gedrehter Text
Mit der Windows-API können Sie Text in jedem beliebigen Winkel zeichnen. Dazu müssen Sie die API-Funktion „CreateFont“ oder „CreateFontIndirect“ verwenden, wie in Abbildung 8 gezeigt.
Mit der Windows-API können Sie Text in jedem Winkel zeichnen. Um dies in Delphi zu tun, müssen Sie die beiden API-Funktionen CreateFont oder CreateFontIndirect verwenden. Abbildung 8 zeigt, wie CreateFont deklariert wird.
Funktion CreateFont(
nHeight, // Logische Höhe der Schriftart. Die logische Höhe der Schriftart.
nWidth, // Logische durchschnittliche Zeichenbreite.
nEscapement, // Winkel der Hemmung
nOrientation, // Grundlinienorientierungswinkel.
fnWeight: Integer; // Schriftstärke-Untereigenschaft der Schriftart
fdwItalic, // Kursivschrift-Attributflag. Ist es kursiv?
fdwUnderline, // Unterstreichungsattribut-Flag Ob unterstrichen werden soll
fdwStrikeOut, // Strikeout-Attribut-Flag, ob das Attribut durchgestrichen werden soll
fdwCharSet // Zeichensatzkennung
fdwOutputPrecision, // Ausgabegenauigkeit.
fdwClipPrecision, // Clipping-Präzision.
fdwQuality, // Ausgabequalität.
fdwPitchAndFamily: DWORD; // Pitch und Familie.
lpszFace: PChar // Zeiger auf Schriftartnamenzeichenfolge.
): HFONT; stdcall;
Abbildung 8: Die Object Pascal-Deklaration für die Windows-API-Funktion „CreateFont“.
Obwohl diese Funktion über viele Parameter verfügt, möchten Sie normalerweise nur ein oder zwei Attribute des Texts ändern. In solchen Fällen sollten Sie stattdessen die Funktion „CreateFontIndirect“ verwenden. Sie benötigt nur ein Argument – einen Datensatz vom Typ TLogFont, wie in Abbildung gezeigt 9.
Obwohl diese Funktion viele Parameter benötigt, müssen Sie normalerweise nur eine oder zwei Eigenschaften des Textes ändern. In diesem Fall würden Sie stattdessen die Funktion CreateFontIndirect verwenden. Es ist nur ein Parameter erforderlich – ein Datensatztypparameter von TlogFont, wie in Abbildung 9 zu sehen ist.
tagLOGFONTA = gepackter Datensatz
lfHeight: Longint;
lfWidth: Longint;
lfHemmung: Longint;
lfOrientation: Longint;
lfWeight: Longint;
lfItalic: Byte;
lfUnderline: Byte;
lfStrikeOut: Byte;
lfCharSet: Byte;
lfOutPrecision: Byte;
lfClipPrecision: Byte;
lfQuality: Byte;
lfPitchAndFamily: Byte;
lfFaceName: array[0..LF_FACESIZE - 1] von AnsiChar;
Ende;
TLogFontA = tagLOGFONTA;
TLogFont = TLogFontA;
Abbildung 9: Der TLogFont-Datensatz.
Wenn Sie sich diesen Datensatz ansehen, werden Sie feststellen, dass seine Mitglieder mit den Parametern für die Funktion „CreateFont“ übereinstimmen. Der Vorteil der Verwendung dieser Kombination aus Funktion und Datensatz besteht darin, dass Sie die Mitglieder des Datensatzes mithilfe der GetObject-API-Funktion mit einer bekannten Schriftart füllen und die Mitglieder ändern können möchten, und erstellen Sie die neue Schriftart.
Wenn Sie sich diesen Datensatztyp genau ansehen, werden Sie feststellen, dass seine Mitglieder den Parametern der CreateFont-Funktion sehr ähnlich sind. Der Vorteil der Verwendung dieser Funktions-/Datensatzkombination besteht darin, dass Sie die GetObject-API-Funktion verwenden können, um die Mitgliedswerte dieses Datensatzes mit einer bekannten Schriftart zu füllen und dann den zu ändernden Mitgliedswert zu ändern, um eine neue Schriftart zu generieren.
Um gedrehten Text zu zeichnen, müssen Sie als einziges Element lfEscapement ändern, das den Textwinkel in Zehntelgraden festlegt. Wenn Sie also möchten, dass Text in einem Winkel von 45 Grad gezeichnet wird, müssen Sie lfEscapement auf 450 einstellen.
Um gedrehten Text zu zeichnen, müssen Sie als einziges Mitglied lfEscapement ändern, das den Winkel der Schriftart in Zehntelgraden festlegt. Wenn Sie also möchten, dass sich das Zeichen um 45 Grad dreht, müssen Sie dies festlegen
lfEscapement ist 450.
Beachten Sie, dass es Flags zum Zeichnen von kursivem, unterstrichenem und durchgestrichenem Text gibt, aber kein Flag zum Zeichnen von fettem Text. Dies erfolgt mit dem lfWeight-Mitglied, einer Zahl zwischen 0 und 1000. 400 ist normaler Text, Werte darüber Zeichnen Sie fetten Text und Werte darunter zeichnen hellen Text.
Beachten Sie, dass es eine ganze Reihe von Markierungen gibt, um Text kursiv, unterstrichen und hervorzuheben, aber keine Markierungen, um Text fett zu machen. Dies liegt daran, dass stattdessen das lfWeight-Mitglied verwendet wird und der Wert dieses Mitglieds zwischen 0 und 1000 liegt. 400 ist der Normalwert, alles darüber ist fett und alles darunter ist dünn.
Der Code in Abbildung 10 zeichnet Text in Winkeln von 0 Grad bis 360 Grad in 20-Grad-Intervallen. Es handelt sich um den OnPaint-Ereignishandler des Formulars, sodass der Text jedes Mal neu gezeichnet wird, wenn das Formular gezeichnet wird.
Der Code in Abbildung 10 zeichnet Zeichen alle 20 Grad von 0 bis 360 Grad. Dies wird im OnPaint-Ereignis des Formulars ausgelöst, sodass der Text bei jedem Malen des Formulars neu gezeichnet wird. Der Effekt ist in Abbildung 11 zu sehen.
procedure TForm1.FormPaint(Sender: TObject);
var
OldFont, NewFont: hFont;
LogFont: TLogFont;
i: Ganzzahl;
beginnen
// Griff der Canvas-Schriftart abrufen.
Ruft das Handle für das Formularschriftartobjekt ab
OldFont := Canvas.Font.Handle;
ich := 0;
// Transparente Zeichnung.
Transparenzeigenschaft festlegen
SetBkMode(Canvas.Handle, Transparent);
// LogFont-Struktur mit Informationen füllen
Füllen Sie die LogFont-Struktur mit Informationen aus
// aus der aktuellen Schriftart.
aus der aktuellen Schriftart
GetObject(OldFont, Sizeof(LogFont), @LogFont);
// Winkel reichen von 0 bis 360.
von 0 bis 360 Grad
während ich < 3600 beginne
// Hemmung auf neuen Winkel einstellen.
Stellen Sie die Textausrichtung auf einen neuen Winkel ein
LogFont.lfEscapement := i;
//Neue Schriftart erstellen.
Erstellen Sie eine neue Schriftart
NewFont := CreateFontIndirect(LogFont);
// Wählen Sie die zu zeichnende Schriftart aus.
Wählen Sie Schriftarten für die Ausgabe aus
SelectObject(Canvas.Handle, NewFont);
// Text in der Mitte des Formulars zeichnen.
Geben Sie den Text in der Mitte des Formulars aus
TextOut(Canvas.Handle, ClientWidth div 2,
ClientHeight div 2, 'Gedrehter Text', 21);
// Aufräumen.
Klar
DeleteObject(SelectObject(Canvas.Handle, OldFont));
// Winkel um 20 Grad erhöhen.
Schritte alle 20 Grad
Inc(i, 200);
Ende;
Ende;
Abbildung 10: Code zum Zeichnen von in 20-Grad-Intervallen gedrehtem Text.
Abbildung 11: Text um 360 Grad gedreht.
Die Schriftart des Formulars ist auf Arial eingestellt, eine TrueType-Schriftart. Andere Schriftarten unterstützen keine Textrotation. Um die aktuellen Schriftarteneinstellungen abzurufen und die TLogFont-Struktur zu füllen, müssen Sie die GetObject-API-Funktion verwenden. Der Code in Abbildung 12 zeigt, wie die TLogFont-Einstellungen für die Schriftart des Formulars ausgefüllt und angezeigt werden.
Die Schriftart dieses Formulars ist auf Arial, eine TrueType-Schriftart, eingestellt. Dieser Code läuft nur unter TrueType-Schriftarten; andere Schriftarten unterstützen keine Textdrehung. Um die aktuellen Schriftarteinstellungen zu erhalten und die TlogFont-Struktur auszufüllen, müssen Sie die GetObject-API-Funktion verwenden. Im Code in Abbildung 12 können Sie sehen, wie die TlogFont-Einstellungen im Formular ausgefüllt und angezeigt werden.
procedure TForm1.Info1Click(Sender: TObject);
var
LogFont: TLogFont;
beginnen
// LogFont-Struktur mit Informationen füllen
Füllen Sie die Mitgliedswerte der LogFont-Struktur aus
// aus der aktuellen Schriftart.
aus der aktuellen Schriftart
GetObject(Canvas.Font.Handle, Sizeof(LogFont), @LogFont);
// Schriftartinformationen anzeigen.
Schriftartinformationen anzeigen
mit LogFont 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: ' + string(lfFaceName));
Ende;
Abbildung 12: Schriftartattribute abrufen und anzeigen.
Sobald Sie die Einstellungen in einer TLogFont-Struktur haben, müssen Sie nur noch lfEscapement auf den gewünschten Winkel einstellen und mit CreateFontIndirect eine neue Schriftart erstellen. Bevor Sie diese neue Schriftart verwenden, müssen Sie sie mit SelectObject auswählen Fügen Sie diese neue Schriftart dem Handle der Leinwandschrift hinzu, bevor Sie den Text zeichnen. Anschließend muss die alte Schriftart ausgewählt und die neue Schriftart gelöscht werden. Wird die Routine nicht gelöscht, kommt es zu einem Speicherverlust und – wenn die Routine mehrmals ausgeführt wird – gehen Windows (insbesondere 95/98) die Ressourcen aus und es kommt zum Absturz.
Nachdem Sie die TlogFont-Struktur eingerichtet haben, müssen Sie nur noch den Wert von lfEscapement auf den Zielwert ändern und mit CreateFontIndirect eine neue Schriftart generieren. Bevor Sie diese neue Schriftart verwenden können, müssen Sie sie mit SelectObject auswählen. Eine andere Methode besteht darin, vor dem Zeichnen des Textes das Handle dieses neuen Schriftartobjekts mit dem Handle des Schriftartobjekts auf der Leinwand des Formulars zu verbinden. Nachdem der Text gezeichnet wurde, beginnt der Vorgang; die alte Schriftart muss ausgewählt und die neue Schriftart gelöscht werden. Wenn die neue Schriftart nicht entfernt wird, führt dies zu einem Speicherverlust und -----wenn das Programm mehrmals ausgeführt wird ------ Windows (insbesondere 95/98) gehen die Ressourcen aus und
Absturz.
Stilvolle Linien
beliebte Linien
Beim Zeichnen von Linien spielen die einzelnen Pixel normalerweise keine Rolle; Sie legen einfach den Linienstil fest, und dieser wird von Windows gezeichnet. Manchmal müssen Sie jedoch etwas Besonderes tun und einen Linienstil zeichnen, der von Windows nicht bereitgestellt wird Verwenden einer Windows-API-Funktion namens LineDDA, definiert in Abbildung 13.
Wenn Sie Linien zeichnen, sind einzelne Pixel normalerweise unwichtig; Sie legen einfach den Linientyp fest und das Zeichnen wird Windows überlassen. Manchmal möchten Sie jedoch einige spezielle Linientypen ausführen, die Windows nicht bietet. Dies kann mithilfe einer API-Funktion namens LineDDA erreicht werden, deren Definition in Abbildung 13 zu sehen ist.
Funktion LineDDA(
nXStart, // x-Koordinate des Startpunkts der Linie.
Startpunkt der X-Koordinate
nYStart, // Y-Koordinate des Startpunkts der Linie.
Y-Koordinaten-Startpunkt
nXEnd, // x-Koordinate des Endpunkts der Linie.
Endpunkt der X-Koordinate
YEnd: Ganzzahl; // y-Koordinate des Endpunkts der Linie.
Endpunkt der Y-Koordinate
// Adresse der anwendungsdefinierten Rückruffunktion.
Die Adresse der anwendungsdefinierten Rückruffunktion
lpLineFunc: TFNLineDDAProc;
lpData: LPARAM // Adresse der anwendungsdefinierten Daten.
Adresse anwendungsdefinierter Daten
): BOOL; stdcall;
Abbildung 13: Object Pascal-Deklaration für die Windows-API-Funktion LineDDA.
Die ersten vier Parameter sind die Start- und Endpunkte der Linie. Der fünfte Parameter ist eine Callback-Funktion, die jedes Mal aufgerufen wird, wenn ein Pixel gezeichnet werden soll. Der letzte Parameter ist ein Benutzerparameter An die Rückruffunktion übergeben Sie können eine beliebige Ganzzahl oder einen beliebigen Zeiger an die Funktion übergeben, da es sich um einen LParam handelt (in Win32 wird er in einen Longint übersetzt). Die Rückruffunktion muss die hier gezeigte Form annehmen.
Die ersten vier Parameter sind die Start- und Endpunkte der Linie. Der fünfte Parameter ist eine Rückruffunktion, die jedes Mal aufgerufen wird, wenn ein Pixel gezeichnet wird. Hier können Sie über Ihren Zeichenprozess schreiben. Der letzte Parameter ist benutzerdefiniert und kann an die Callback-Funktion übergeben werden. Sie können dieser Funktion eine beliebige Ganzzahl oder einen beliebigen Zeiger übergeben, da dies der Fall ist
Ein Lparam-Typ (in WIN32 wird er als Longint-Typ interpretiert). Diese Rückruffunktion muss ein Formular wie das folgende verwenden:
Prozedur CallBackDDA(x, y: Integer;
UserParam: LParam);
Dabei sind x und y die Koordinaten des gezeichneten Punkts und UserParam ist ein Parameter, der an die Funktion übergeben wird. Diese Funktion muss als stdcall deklariert werden. Die Routine in Abbildung 14 zeichnet eine Reihe von Bitmaps und Abbildung 15 zeigt das Ergebnis.
Hier sind X und Y die gezeichneten Koordinatenpunkte und UserParam ist ein Parameter. Diese Funktion muss als stdcall unterdefiniert werden. Das Programm in Abbildung 14 zeichnet eine BMP-Linie und Abbildung 15 zeigt die Ergebnisse an.
Typ
TForm1 = Klasse(TForm)
ImageList1: TImageList;
procedure FormPaint(Sender: TObject);
procedure FormResize(Sender: TObject);
Ende;
var
Form1: TForm1;
procedure CallDDA(x, y: Integer; Form: TForm1);
Durchführung
{ $R *.DFM }
procedure CallDDA(x, y: Integer; Form: TForm1);
beginnen
wenn x mod 13 = 0 dann
Form.ImageList1.Draw(Form.Canvas, x, y, 0);
Ende;
procedure TForm1.FormPaint(Sender: TObject);
beginnen
LineDDA(0, 0, ClientWidth, ClientHeight,
@CallDDA, Integer(Self));
Ende;
procedure TForm1.FormResize(Sender: TObject);
beginnen
Ungültig machen;
Ende;
Abbildung 14: Code zum Zeichnen einer Reihe von Bitmaps.
Abbildung 15: Fenster mit einer benutzerdefinierten Zeile.
Diese Routine verarbeitet das OnPaint-Ereignis des Formulars und ruft LineDDA auf. Jedes Mal, wenn das Formular gezeichnet werden muss, wird die Zeile neu gezeichnet. Ein weiteres behandeltes Ereignis ist OnResize, das den Clientbereich des Formulars ungültig macht, sodass die Zeile neu gezeichnet werden muss, wenn jemand sie ändert Die Callback-Funktion von LineDDA, CallDDA, ist sehr einfach. An jedem 13. Punkt wird die in der ImageList gespeicherte Bitmap gezeichnet die Callback-Funktion, damit sie auf die Instanzdaten zugreifen kann.
Dieses Programm verarbeitet das OnPaint-Ereignis des Formulars und ruft LineDDA auf, sodass die Linie jedes Mal neu gezeichnet wird, wenn das Formular gezeichnet wird. Ein weiteres Ereignis ist OnResize, das den Clientbereich des Formulars ungültig macht, sodass die Linien neu gezeichnet werden, wenn jemand die Größe ändert. Die LineDDA-Rückruffunktion und CallDDA sind sehr einfach. Bei jedem 13-maligen Aufruf wird die in der ImageList gespeicherte Bitmap gezeichnet. Vielleicht ist Ihnen aufgefallen, dass SELF als letzter Parameter an die Callback-Funktion übergeben wird, damit diese auf die Daten des Programms zugreifen kann.
Abschluss
abschließend
Seit die Eigentümerzeichnung in TMainMenu in Delphi 4 verfügbar gemacht wurde, gibt es viele Möglichkeiten, Ihre Menüs zu erweitern. Mit den hier besprochenen Techniken können Sie die Menüs Ihrer Delphi-Anwendung ganz einfach mit benutzerdefiniertem Text, Bitmaps und Farben erweitern.
Da die Eigentümerzeichnung nun in TmainMenu in Delphi 4 verfügbar ist, gibt es viele Möglichkeiten, die Funktionalität Ihres Menüs zu erweitern. Mit den oben besprochenen Techniken können Sie die Menüfunktionalität Ihrer DELPHI-Anwendung ganz einfach durch benutzerdefinierten Text, Bitmaps und Farben erweitern.