Autor Beitrag
Christian213
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 66
Erhaltene Danke: 3

Win XP, Win 7 64Bit
Lazarus 1.0.10
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 19.07.13 12:05 
verstehe ich das richtig? du hast z.B. den String
Zitat:
[fsItalic,fsBold]

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:
ausblenden 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..
ausblenden 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 );       //1 Bit (von rechts) auf 1 setzten
if pos( 'fsItalic', DeinString )>0 then inc( Zustand, 2 );     //2 Bit auf 1
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 := []; //wird nie eintreffen !
  end;
end;

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!

Für diesen Beitrag haben gedankt: Christian213
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: 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
ausblenden 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 );       //1 Bit (von rechts) auf 1 setzten
if pos( 'fsItalic', DeinString )>0 then inc( Zustand, 2 );     //2 Bit auf 1
if pos( 'fsUnderline', DeinString )>0 then inc( Zustand, 4 );  //...
if pos( 'fsStrikeOut', DeinString )>0 then inc( Zustand, 8 );

richedit1.Font.Style := TFontStyles(ZuStand); //hätte mir oben die Case-Abfrage erspart
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 :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: 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.
ausblenden 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):

ausblenden 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,

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: 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 :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Fr 19.07.13 13:21 
Hi,

user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconChristian213 hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 66
Erhaltene Danke: 3

Win XP, Win 7 64Bit
Lazarus 1.0.10
BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
GetEnumValue(TypeInfo : PTypeInfo;const Name : string) : Integer;					

Also in meinem Fall müsste
ausblenden Delphi-Quelltext
1:
Color := GetEnumValue(TypeInfo(TColor), 'clRed');					

Für Color den TColor-Wert $0000FF ergeben und damit dann...
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: 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

_________________
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 66
Erhaltene Danke: 3

Win XP, Win 7 64Bit
Lazarus 1.0.10
BeitragVerfasst: Fr 19.07.13 14:52 
user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:

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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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:
ausblenden volle Höhe 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: stringout ConvertedValue: T): Boolean; static;
  end;

// ...

class function TTest.ConvertToSet<T>(const AValue: stringout 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:
ausblenden 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