Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - TFontParams aus Strings setzen??
Christian213 - Do 18.07.13 13:57
Titel: TFontParams aus Strings setzen??
Hallo,
ich scheitere gerade an folgendem Vorhaben:
Ich habe eine RichMemo-Box und möchte dort farbigen und "gestylten" Text ausgeben.
Da sowohl der Text als auch die Syle-Informationen aus einer Datenquelle kommen, liegen mir diese als Strings vor.
Ich muss also bspw. den String '[fsItalic,fsBold]' irgendwie der Variable TextParams vom Typ TFontParams zuweisen.
Also habe ich folgendes versucht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| type PFontStyles = ^TFontStyles; PColor = ^TColor; var Styles, Color : Integer; InfoStrings : TStringList; TextParams : TFontParams;
Styles := StringToSet(PTypeInfo(TypeInfo(TFontStyles)), MyStyleString); TextParams.Style := PFontStyles(@Styles)^;
TextParams.Color := TColor(GetEnumValue(TypeInfo(TColor), MyColorString)); |
Leider funzt weder die Übergabe des Style, noch das Setzen der Farbe.
Wie macht man es richtig?
Gruß,
Christian
IhopeonlyReader - Fr 19.07.13 12:05
verstehe ich das richtig? du hast z.B. den String
und willst nun den Font.Style entsprechend darauf setzten..
Da sich keiner meldet, gehe ich davon aus, dass es keinen Direkt "umwandlungsbefehl" gibt...
selberschreiben würde ich so etwas folgendermaßen:
Delphi-Quelltext
1: 2: 3:
| richedit1.Font.Style := []; if pos( 'fsItalic', DeinString ) > 0 then richedit1.Font.Style := richedit1.Font.Style + [fsItalic]; |
natürlich kannst du das auch "verschnellern", falls es nötig ist..
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| var Zustand: Byte; begin Zustand := 0; if pos( 'fsBold', DeinString )>0 then inc( Zustand, 1 ); if pos( 'fsItalic', DeinString )>0 then inc( Zustand, 2 ); if pos( 'fsUnderline', DeinString )>0 then inc( Zustand, 4 ); if pos( 'fsStrikeOut', DeinString )>0 then inc( Zustand, 8 ); case Zustand of 0: richedit1.Font.Style := []; 1: richedit1.Font.Style := [fsBold]; 2: richedit1.Font.Style := [fsItalic]; 3: richedit1.Font.Style := [fsBold, fsItalic]; 4: richedit1.Font.Style := [fsUnderline]; 5: richedit1.Font.Style := [fsBold, fsUnderline]; 6: richedit1.Font.Style := [fsItalic, fsUnderline]; 7: richedit1.Font.Style := [fsBold, fsItalic, fsUnderline]; 8: richedit1.Font.Style := [fsStrikeOut]; 9: richedit1.Font.Style := [fsBold, fsStrikeOut]; 10: richedit1.Font.Style := [fsItalic, fsStrikeOut]; 11: richedit1.Font.Style := [fsBold, fsItalic, fsStrikeOut]; 12: richedit1.Font.Style := [fsUnderline, fsStrikeOut]; 13: richedit1.Font.Style := [fsBold, fsUnderline, fsStrikeOut]; 14: richedit1.Font.Style := [fsItalic, fsUnderline, fsStrikeOut]; 15: richedit1.Font.Style := [fsBold, fsItalic, fsUnderline, fsStrikeOut]; else richedit1.Font.Style := []; end; end; |
IhopeonlyReader - Fr 19.07.13 12:21
ich habe es noch EXTREAM vereinfach können :D
der Typ TFontStyles arbeitet genau wie ich, was ich nach einfach Tests herausgefunden habe :D
somit kann man ganz einfach
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var Zustand: Byte; begin Zustand := 0; if pos( 'fsBold', DeinString )>0 then inc( Zustand, 1 ); if pos( 'fsItalic', DeinString )>0 then inc( Zustand, 2 ); if pos( 'fsUnderline', DeinString )>0 then inc( Zustand, 4 ); if pos( 'fsStrikeOut', DeinString )>0 then inc( Zustand, 8 );
richedit1.Font.Style := TFontStyles(ZuStand); end; |
Nachtrag: Beim Style kommt es auf den Zustand der Bits an ! das 1 Bit (bzw. 8 Bit wenn man von links liest) gibt fsBold an (1 = true, 0= false)
das 2 bit fsItalic, und so weiter.. das heißt bei Zustand > 15 werden nur die 4 letzten (also bit 4 bis 1) (aus-)gewertet
somit
16,32,48,64,80,96,112,128,144,160,176,192,208,224,240 ≘(oder kann man ≜ verwenden?) 0
17,33,49,65,81,97,113,129,145,161,177,193,209,225,241 ≘ 1
//und so weiter
Hidden - Fr 19.07.13 12:39
Hi,
Man darf dabei sogar die Eigenschaften von Sets benutzen :) Die sollen es nämlich u.A. erleichtern, eine Reihe von Eigenschaften getrennt zu prüfen und deren Kombination zu sammeln.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var Styles: TFontStyles; begin Styles := []; if Pos( 'fsBold', DeinString ) > 0 then Styles := Styles + [fsBold]; if Pos( 'fsItalic', DeinString ) > 0 then Styles := Styles + [fsItalic]; if Pos( 'fsUnderline', DeinString ) > 0 then Styles := Styles + [fsUnderline]; if Pos( 'fsStrikeOut', DeinString ) > 0 then Styles := Styles + [fsStrikeOut]; richedit1.Font.Style := Styles; |
oder (bei größeren Sets wird dieser Ansatz kürzer):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| const StyleNames: Array [TFontStyle] of String = ('fsBold', 'fsItalic', 'fsUnderline', 'fsStrikeOut'); var i: TFontStyle; Styles: TFontStyles; begin Styles := []; for i := Low(TFontStyle) to High(TFontStyle) do if Pos( StyleNames[i], DeinString ) > 0 then Styles := Styles + [i]; Richedit1.Font.Style := Styles; end; |
Edit: Oder, mit der von dir erwähnten Funktion
GetEnumName,
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var i: TFontStyle; Styles: TFontStyles; begin Styles := []; for i := Low(TFontStyle) to High(TFontStyle) do if Pos( GetEnumName( TypInfo(TFontStyle), i ), DeinString ) > 0 then Styles := Styles + [i]; Richedit1.Font.Style := Styles; end; |
Grüße,
Daniel
IhopeonlyReader - Fr 19.07.13 12:52
wobei man nicht direkt die Variable "richedit1.font.style" direkt beschreiben sollte, sondern das ganze zwischenlagern sollte (ziehe meine variable "zustand", da es dann schneller geht und nicht über propertys etc. die weiteres verursachen
Hidden - Fr 19.07.13 13:21
Hi,
IhopeonlyReader hat folgendes geschrieben : |
wobei man nicht direkt die Variable "richedit1.font.style" direkt beschreiben sollte, sondern das ganze zwischenlagern sollte (ziehe meine variable "zustand", da es dann schneller geht und nicht über propertys etc. die weiteres verursachen |
Gegebenenfalls könnte es wirklich sein, dass dies bei TFont mehrere Repaints auslöst (es gibt ein OnFontChange-Event). Insofern auf jeden Fall eine gute Idee.
Edit: Done.
Christian213 hat folgendes geschrieben : |
Da sowohl der Text als auch die Syle-Informationen aus einer Datenquelle kommen, liegen mir diese als Strings vor. |
Möglicherweise lässt sich dein "Text mit Style-Informationen" auch direkt -- per
StringReplace() -- in das RTF-Format übertragen, welches von
TRichEdit benutzt wird (
TRichMemo kenne ich nicht, ich gehe mal stark davon aus dass
TRichEdit gemeint ist).
Siehe
1 [
http://www.delphipraxis.net/29266-memo-richedit-mit-formatuebergabe.html],
2 [
http://www.delphipraxis.net/167594-richedit-dynamisch-befuellen-mit-formatierung.html].
Grüße,
Daniel
Christian213 - Fr 19.07.13 13:33
Hallo,
Danke für die Antworten. So kann man das natürlich machen, klar, aber ich wollte möglichst wenig "hardcoden" im Programm und vor allem nicht die ENUMs "aufbrechen".
Nach meinem Verständnis gibt genau dafür doch die Funktion:
Delphi-Quelltext
1:
| GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer; |
Also in meinem Fall müsste
Delphi-Quelltext
1:
| Color := GetEnumValue(TypeInfo(TColor), 'clRed'); |
Für Color den TColor-Wert $0000FF ergeben und damit dann...
Delphi-Quelltext
1:
| TextParams.Color := TColor(Color); |
...die Farbe Rot setzen. Aber genau das funzt nicht.
Ich wüsste gerne, was ich hier vom Denkansatz falsch mache.
Hidden - Fr 19.07.13 13:52
Hi,
Da TColor keine Aufzählung ist, gehe ich davon aus dass GetEnumValue mit TColor nicht funktioniert. TFontStyle z.B. ist eine Aufzählung, also könnte man in meinem Quelltext oben das Array StyleNames einsparen und statt dessen GetEnumName(, i) verwenden.
Wie Google mich gerade lehrte, gibt es allerdings die Funktionen StringToColor und ColorToString; vielleicht sind die ja von Nutzen. :zwinker:
Grüße,
Daniel
Christian213 - Fr 19.07.13 14:52
Hidden hat folgendes geschrieben : |
Wie Google mich gerade lehrte, gibt es allerdings die Funktionen StringToColor und ColorToString; vielleicht sind die ja von Nutzen. :zwinker:
|
Daniel, Du bist der Held des Tages! :-D
Dankeschön!
jaenicke - Fr 19.07.13 16:37
Die Umwandlung geht auch ohne Stringsuche mit Pos. Ich hatte sowas mal geschrieben und in noch umfangreicherer Form auch in die Quelltexte eingebaut, die wir in der Firma nutzen. Die einfache Variante sah so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| uses Rtti, TypInfo;
TTest = class public class function ConvertToSet<T>(const AValue: string; out ConvertedValue: T): Boolean; static; end;
class function TTest.ConvertToSet<T>(const AValue: string; out ConvertedValue: T): Boolean; var SetValue: set of Byte; RttiContext: TRttiContext; SetEntries: TStringList; CurrentEntry: string; CurrentValue: Integer; ElementTypeInfo: PTypeInfo; begin RttiContext := TRttiContext.Create; try ElementTypeInfo := (RttiContext.GetType(TypeInfo(T)) as TRttiSetType).ElementType.Handle; Result := True; SetEntries := TStringList.Create; try SetEntries.Delimiter := ','; SetEntries.StrictDelimiter := True; if Length(AValue) > 2 then SetEntries.DelimitedText := Copy(AValue, 2, Length(AValue) - 2); SetValue := []; for CurrentEntry in SetEntries do if TryStrToInt(Trim(CurrentEntry), CurrentValue) then Include(SetValue, CurrentValue) else if Assigned(ElementTypeInfo) then Include(SetValue, GetEnumValue(ElementTypeInfo, Trim(CurrentEntry))) else Result := False; finally SetEntries.Free; end; finally RttiContext.Free; end; ZeroMemory(@ConvertedValue, SizeOf(ConvertedValue)); CopyMemory(@ConvertedValue, @SetValue, SizeOf(ConvertedValue)); end; |
Benutzung:
Delphi-Quelltext
1: 2: 3: 4: 5:
| var Value: TFontStyles; begin if TTest.ConvertToSet<TFontStyles>('[fsItalic, fsBold]', Value) then Font.Style := Value; |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!