Autor |
Beitrag |
Christian213
      
Beiträge: 66
Erhaltene Danke: 3
Win XP, Win 7 64Bit
Lazarus 1.0.10
|
Verfasst: Do 18.07.13 13:57
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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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; |
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Für diesen Beitrag haben gedankt: Christian213
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Fr 19.07.13 12:21
ich habe es noch EXTREAM vereinfach können
der Typ TFontStyles arbeitet genau wie ich, was ich nach einfach Tests herausgefunden habe
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
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: 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
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
Zuletzt bearbeitet von Hidden am Sa 20.07.13 21:32, insgesamt 3-mal bearbeitet
Für diesen Beitrag haben gedankt: Christian213
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Hidden
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: 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, 2.
Grüße,
Daniel
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
Zuletzt bearbeitet von Hidden am Fr 19.07.13 17:15, insgesamt 2-mal bearbeitet
|
|
Christian213 
      
Beiträge: 66
Erhaltene Danke: 3
Win XP, Win 7 64Bit
Lazarus 1.0.10
|
Verfasst: 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
      
Beiträge: 2242
Erhaltene Danke: 55
Win10
VS Code, Delphi 2010 Prof.
|
Verfasst: 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.
Grüße,
Daniel
_________________ Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
Für diesen Beitrag haben gedankt: Christian213
|
|
Christian213 
      
Beiträge: 66
Erhaltene Danke: 3
Win XP, Win 7 64Bit
Lazarus 1.0.10
|
Verfasst: Fr 19.07.13 14:52
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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: 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; |
Für diesen Beitrag haben gedankt: Hidden
|
|
|