TextRect selbst machen

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

TextRect selbst machen

Beitrag von pluto »

Hallo,
ich möchte mir eine Funktion wie TextRect selbst machen. Das ist leider notwendig.

Ich schreibe ja immer noch an meiner GUI. ich habe jetzt neu angefangen, weil ich nach drei Monaten gemerkt habe das es so eigentlich nicht geht wie ich es angefangen habe.

Jetzt die Frage: wie würdet ihr ein eigene TextRect Funktion schreiben ?
Ich habe mir selbstverständlich die Funktion angeschaut und auch ausgedruckt.
Ich habe z.b. gesehen das sie alles doppelt macht. Sie nutzt intern eine TStringlist.
das möchte ich nicht bei meiner Variante.

Ich möchte in meiner GUI die Möglichkeit haben, wenn ein Text gezeichnet wird, das jeder Buchstabe anders aussieht, ich habe mir dafür ein System überlegt was den speicher aufwand auf ein Minimum reduziert.

Und weil jeder Buchstabe anders aussehen soll, brauche ich nun mal eine eigene TextRect Funktion ich habe auch schon angefangen, hier mein versuch:

Code: Alles auswählen

procedure TMyTextDisplay.Draw(ACanvas: TCanvas; const x: Integer;
  const y: Integer; const w: integer; const h: integer);
var
  px,py,pw,ph,ix,oi,oi2,opx,ox,ix2,l:Integer;
  s,wstr:String;
  drawText:Boolean;
  FontItems:Array of TFontItem;
begin
  if CanDraw then begin
    Style.CanDraw:=False;
    Style.Left:=Left;
    Style.Top:=Top;
    Style.Width:=Width;
//    if AutoSize then begin
  //    Style.Height:=GetSizeAuto.Y+AbsY
//    end
  //  else
      Style.Height:=Height;
 
    Style.CanDraw:=True;
    Style.Draw;
 
    px:=Left+absX; py:=Top+absY; pw:=0; ph:=0;
    wstr:=''; drawText:=False;
 
    SetLength(fontItems,0);
    oi:=-1; oi2:=-1; opx:=-1; ox:=-1; l:=0;
    for ix:=0 to fText.Count-1 do begin
      s:=TMyListItem(ftext[ix]).Text;
 
      pw:=canvas.TextWidth(s);
      if (ix <> fText.Count-1) and ((s <> ' ') and (px+pw+2 <= left+Width)) then begin
        wstr:=wstr+s;
        SetLength(fontItems,high(FontItems)+2);
        FontItems[high(FontItems)].s:=s;
        FontItems[high(FontItems)].f:=TmyFont.Create;
        FontItems[high(FontItems)].f.Assign(TMyListItem(ftext[ix]).Font);
      end
      else begin
        if px+canvas.TextWidth(wstr) <=left+Width then begin
          l:=ix;
          for ix2:=1 to Length(wstr) do begin
            canvas.Font.Assign(FontItems[ix2-1].f);
 
            canvas.TextOut(px,py,wstr[ix2]);
            pw:=canvas.TextWidth(Wstr[ix2]);
 
            px:=px+pw;
            if px+pw+2 >= left+Width then begin
              py:=py+canvas.TextHeight(wstr)+absY;
              px:=left+absX;
            end;
          end;
          px:=px+pw;
        end
        else begin
          px:=left+absX;
          py:=py+canvas.TextHeight(wstr)+absY+2
        end;
        wstr:=''; SetLength(fontItems,0);
      end;
    end;
  end; // if CanDraw
end;


Das Klappt auch schon ganz gut, nur bei bestimmten breiten angaben gibt es Probleme. Dann stimmen die Zeilen nicht mehr überein.
Im Anhang ist ein Bild. Der Schrift Style ist jetzt Fett(fsBold).
Auf dem Bild sind noch mehr Elemente der Neuen GUI zu sehen. Also nicht wundern.
Die Radiobuttons z.b. sind in Gruppen angeordnet. es gibt also 3 Gruppen(von 0).
und Drei Checkboxen zum Testen.

Die TextRect Funktion soll natürlich im Word unterbrechen. bzw. schauen ob unterbrochen werden muss oder nicht.

Ich hoffe einer von euch kann mir ein Hilfreichen Tipp dazu geben.

PS: Wenn ihr euch fragt warum ich meine eigene GUI schreiben möchte:
1) Es ist schon lange ein Traum, Bevor Windows kam hatte ich ihn schon
2) Mir macht es Spaß mit Grafik Funktionen zu arbeiten
3) Die GUI soll auf allen Plattformen gleich aussehen
4) Später soll auch noch eine Font-BMP hinzukommen.
das hätte den Vorteil das es die Schrift art auf jeden Fall gibt auf dem Rechner, sie könnte z.b. als Resorce einkomplimentiert werden, als als externe Datei eingebunden werden aus einem Archiv.
5) Ich möchte wissen was für ein Aufwand eine GUI mit sich zieht.
ich weiß schon genau wie ich viele Probleme lösen könnte:
Droq und Drop z.b. oder aber auch eine RTF-Ähnliche Komponente.
Da ich mit den Scrollbalken immer wieder Problem haben, werde ich überall wo es notwendig ist die TScrollBox nutzten.
Dateianhänge
Bildschirmfoto-GUI - Test Anwendung-1.png
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich glaube ich habe jetzt die Lösung gefunden:

Code: Alles auswählen

procedure TMyTextDisplay.Draw(ACanvas: TCanvas; const x: Integer;
  const y: Integer; const w: integer; const h: integer);
var
  px,py,pw,ph,ix,oi,oi2,opx,ox,ix2,l,oh:Integer;
  s,wstr:String;
  drawText:Boolean;
  FontItems:Array of TFontItem;
begin
  if CanDraw then begin
    Style.CanDraw:=False;
    Style.Left:=Left;
    Style.Top:=Top;
    Style.Width:=Width;
//    if AutoSize then begin
  //    Style.Height:=GetSizeAuto.Y+AbsY
//    end
  //  else
      Style.Height:=Height;
 
    Style.CanDraw:=True;
    Style.Draw;
 
    px:=Left+absX; py:=Top+absY; pw:=0; ph:=0;
    wstr:=''; drawText:=False;
 
    SetLength(fontItems,0);
    oi:=-1; oi2:=-1; opx:=-1; ox:=-1; l:=0; oh:=0;
    for ix:=0 to fText.Count-1 do begin
      s:=TMyListItem(ftext[ix]).Text;
      pw:=canvas.TextWidth(s);
      if (ix <> fText.Count-1) and ((s <> ' ') and (px+pw+2 <= left+Width)) then begin
        wstr:=wstr+s;
        SetLength(fontItems,high(FontItems)+2);
        FontItems[high(FontItems)].s:=s;
        FontItems[high(FontItems)].f:=TmyFont.Create;
        FontItems[high(FontItems)].f.Assign(TMyListItem(ftext[ix]).Font);
      end
      else begin
        if px+canvas.TextWidth(wstr) <=left+Width then begin
          l:=ix;
          for ix2:=1 to Length(wstr) do begin
            canvas.Font.Assign(FontItems[ix2-1].f);
 
            canvas.TextOut(px,py,wstr[ix2]);
            pw:=canvas.TextWidth(Wstr[ix2]);
            // Beim lezten Buchstaben im Word wird ein Leerzeichen dran gehangen
            // Weil die werden im Moment rausgefiltern.
            if ix2 = Length(wstr) then
              px:=px+pw+canvas.TextWidth(' ')
            else
              px:=px+pw;
 
            if px+pw+2 >= left+Width then begin
              py:=py+canvas.TextHeight(wstr)+absY;
              px:=left+absX;
            end;
          end;
          // HIER IST DER GRUND DAFÜR, vermutlich
          //px:=px+pw+2;
        end
        else begin
          px:=left+absX;
          if canvas.TextHeight(wstr) > oh then
            oh:=canvas.TextHeight(wstr);
          py:=py+oh+absY+2;
        end;
 
        wstr:=''; SetLength(fontItems,0);
      end;
    end;
  end; // if CanDraw
end;

Optimal ist das ganze zwar noch nicht, ob es läuft erstmal.
Evlt. habt ihr ja noch verbesserungs Vorschläge auf lager oder ähnliches, währe aufjedenfall Toll.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Das scheint zwar eine Lösung zu sein dennoch gibt es bei bestimmten Abmessungen Grafik Fehler z.b. stimmt der Zeilen abstandt nicht mehr.
MFG
Michael Springwald

Antworten