[gelöst] Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Für Fragen von Einsteigern und Programmieranfängern...
Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

[gelöst] Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

Hallo zusammen,

da ich mir ernstlich überlege, doch eine TreeList in Anlehung an DevExpress zu basteln, sind natürlich als Lazarus-Komplettneueinsteiger zuerst einmal die Basics dran. Hier das Zeichnen.
Das tut er im Prinzip eh okay, aber ein Problem tauchte an unerwarteter Stelle auf: Umlaute. Auf die Wndows-Funktion kann ich verzichten, aber die Canvas Methode lässt sich nicht anpassen. Habt ihr dazu einen Tipp?

Hier die beiden Varianten:

1: Beispiel mit Errechnen der nötigen Texthöhe. Zwei Probleme: a) Umlaute und b) füllt Bereich nicht sauber aus. Okay, Letzterem kann man begegnen, indem man noch einmal das Rechteck, nun mit richtiger Höhe explizit zeichnet (siehe auskommentiert). Aber was mach ich mit a)? Kann es sowohl aus dem String als auch dem Memo holen, ist immer dasselbe. Habt ihr einen Tipp dafür?

Bild

Code: Alles auswählen

procedure TForm1.pbPaint(Sender: TObject);
                    // Umlaute in dem Fall falsch!
const Tx: string = 'Das ist ein längerer Text für diesen Futzi, schauen, ob er den Windows-Kram sauber macht inklusive Zeilenumbruch beim Zeichnen?';
var R: TRect;
    S: string;
begin
  R := Classes.Rect(50, 50, 300, 100);
  with pb.Canvas do
  begin
    Brush.Color := pa3.Color;
    Pen.Style := psClear;
    Rectangle(pb.ClientRect);
    Brush.Color := pa4.Color;
    Rectangle(R);
    if cbTxMemo.Checked then
      S := m.Text
    else
      S := Utf8ToAnsi(Tx);  // alles Mögliche probiert, hilft nix

    // Texthöhe ausrechnen
    Windows.DrawText(Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or DT_CALCRECT);
    // Nötig, um das Rechteck sauber hinzubekommen; wenn das fehlt, so wie laut Bild 1
//    R.Right := 300;
//    Rectangle(R);
    // Eigentliche Ausgabe
    Windows.DrawText(Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL);
    // Anzeige Rechteck zur Kontrolle
    sh.Height := R.Bottom-R.Top;
  end;
end;
2. Beispiel mit der Canvas-Methode macht zwar die Umlaute korrekt, verwehrt aber das Einstellen des TextStyles der Canvas. Meldung bei den Zuweisungen: Error: Argument cannot be assigned to (siehe <<<< ...)

Bild

Code: Alles auswählen

procedure TForm1.pbPaint(Sender: TObject);
                    // Umlaute in dem Fall falsch!
const Tx: string = 'Das ist ein längerer Text für diesen Futzi, schauen, ob er den Windows-Kram sauber macht inklusive Zeilenumbruch beim Zeichnen?';
var R: TRect;
    S: string;
begin
  R := Classes.Rect(50, 50, 300, 100);
  with pb.Canvas do
  begin
    Brush.Color := pa3.Color;
    Pen.Style := psClear;
    Rectangle(pb.ClientRect);
    Brush.Color := pa4.Color;
    Rectangle(R);
    if cbTxMemo.Checked then
      S := m.Text
    else
      S := Utf8ToAnsi(Tx);

    // Texthöhe ausrechnen
    Windows.DrawText(Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or DT_CALCRECT);

    R.Right := 300;
    Rectangle(R);
    Brush.Style := bsClear;
    TextStyle.Wordbreak := True;      <<<<<<<<<<<<<<<
    TextStyle.EndEllipsis := True;      <<<<<<<<<<<<<<<
    TextRect(R, 52, 52, S);
    sh.Height := R.Bottom-R.Top;
  end;
end; 
Zuletzt geändert von Jim Knopf am Di 3. Aug 2021, 22:28, insgesamt 5-mal geändert.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Michl »

Verwende nicht die Unit Windows sondern die LCL-Pendants. Z.B.:

Code: Alles auswählen

uses ..., LCLIntf, LCLType; 
...
 S := Tx;
 DrawText(Handle, PChar(S), Length(S), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or DT_CALCRECT);  
Wegen dem TextStyle. Nimm einfach eine Variable und weise diese zu. Z.B.:

Code: Alles auswählen

var
  ATextStyle: TTextStyle;
begin
  ATextStyle := pb.Canvas.TextStyle;
  ATextStyle.Wordbreak := True;
  ATextStyle.EndEllipsis := True;
  pb.Canvas.TextStyle := ATextStyle; 
PS: Meine persönliche Meinung dazu, den Umstieg von Delphi zu Lazarus mit einer eigenen Komponente zu beginnen, halte ich für sehr gewagt.
Zuletzt geändert von Michl am Mo 2. Aug 2021, 16:55, insgesamt 1-mal geändert.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Benutzeravatar
Aidex
Beiträge: 60
Registriert: Do 24. Sep 2020, 07:02
OS, Lazarus, FPC: Win10 64bit, Laz v2.0.10
CPU-Target: AMD64

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Aidex »

Den TextStyle eines Canvas konnte ich auch nicht ändern. Stattdessen habe ich eine Kopie des Records genommen, darin die Eigenschaften geändert und es dann der TextRect()-Methode als zusätzlichen (letzten) Parameter übergeben.

Code: Alles auswählen

var ts: TTextStyle;
ts:=TextStyle;
ts.Wordbreak := True;
TextRect(R, 52, 52, S, ts);
Und solltest du trotzdem die Windows-Funktion nehmen wollen, empfehle ich die WideChar-Variante Windows.DrawTextW()

Code: Alles auswählen

var ws: UnicodeString;
ws:=s;
Windows.DrawTextW(Handle,PWChar(ws),Length(ws),...);

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Winni »

Hi!

Umlaute

Woher kommt der Text? Irgendwelche älteren Texte auf Windows erstellt?
Da war noch alles Codepage 1252 - wenn ich mich recht entsinne.

Sieh mal in die unit LConvEncoding. Da ist alles für die Konvertierung der "alten" Codepages nach UTF8 drin.

Für Dein Beispiel ist wahrscheinlich dies zuständig:

Code: Alles auswählen

function CP1252ToUTF8(const s: string): string; // latin 1  
TextRect:

Erstmal vergiss die ganzen Zugriffe aus der Windows-Unit. Damit fällst Du bei Mac oder Linux sofort auf die Nase. Die Komponenten Form, Image, Paintbox, Panel und viele mehr besitzen einen Canvas.

Die Größe gibt es durch

maxX := canvas.TextWidth('Irgendein Text');
maxY := canvas.TextHeight ('Noch n Text');

TextHeight brauch man nicht messen - das ist nach der Einstellung der Fonthöhe eine Konstante.

Und TextRect funktioniert im Zusammenhang mit dem Canvas und TextStyle so:

Code: Alles auswählen

 procedure Canvas.TextRect(ARect: TRect; X, Y: integer; const Text: string;
                       const Style: TTextStyle)
wobei Du Dir den TTextstyle erstmal separat definieren musst. Und mit den gewünschten werten initialisieren.

Falls Du Blocksatz brauchst: Das hatte ich vor Jahren mal für die BGRAbitmap gemacht.
Da kann man allerdings mit Single arbeiten. Ich weiß nicht mehr, ob das einfach für den Canvas umzuschreiben ist, denn der braucht Integer. Ich Kram mal rum.

Winni

Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

Hallo Michl und Aidex,

danke für den Tipp, ist irgendwie strange, dass sich WordBreak nicht direkt setzen lässt, hat Set und Get beim Property - aber man muss nicht alles (gleich) verstehen (sonst schon :-) )
Funktionieren tut es trotzdem nicht, obwohl ich so keinen Fehler sehe. Es kommt immer noch das von Bild 2 heraus.
Seht ihr hier in dem Routinchen das Böse ...?

Code: Alles auswählen

procedure TForm1.pbPaint(Sender: TObject);
                    // Umlaute in dem Fall falsch!
const Tx: string = 'Das ist ein längerer Text für diesen Futzi, schauen, ob er den Windows-Kram sauber macht inklusive Zeilenumbruch beim Zeichnen?';
var R: TRect;
    S: string;
    TS: TTextStyle;
begin
  R := Classes.Rect(50, 50, 300, 100);
  with pb.Canvas do
  begin
    ts := TextStyle;
    ts.WordBreak := True;
    ts.EndEllipsis := True;

    Brush.Color := pa3.Color;
    Pen.Style := psClear;
    Rectangle(pb.ClientRect);
    Brush.Color := pa4.Color;
    Rectangle(R);
    if cbTxMemo.Checked then
      S := m.Text
    else
//      S := Utf8ToAnsi(Tx);  // hilft alles nix, aber ist logisch, dass Windows-Unit keine gute Idee ist (auch wenn die ja Lazarus-Windows sein sollte ... oder nicht?)?
      S := UTF8Encode(Tx);

    // Texthöhe ausrechnen  (DT_CALCRECT) - wie sonst, wenn die Unit Windows nicht zu empfehlen ist?
    Windows.DrawTextW(Handle, PWideChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or DT_CALCRECT);

    // Variante I - Windows
    if not cbV2.Checked then
    begin
      // Nötig, um das Rechteck sauber hinzubekommen; wenn das fehlt, so wie laut Bild 1
      R.Right := 300;
      Rectangle(R);
      // Eigentliche Ausgabe
      Windows.DrawText(Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL);
    end

    else
    begin
      // Variante II - Lazarus
      R.Right := 300;
      Rectangle(R);
      Brush.Style := bsClear;
//      TextStyle.Wordbreak := True;     // Geht nicht direkt
//      TextStyle.EndEllipsis := True;   //     - " -
      TextStyle := ts;                      // also hier
      TextRect(R, 52, 52, S);
    end;
    // Anzeige Rechteck drumherum (Shape)
    sh.Height := R.Bottom-R.Top;
  end;
end; 

Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

Hi Winni,
Winni hat geschrieben:
Mo 2. Aug 2021, 17:03
Woher kommt der Text? Irgendwelche älteren Texte auf Windows erstellt?
Der kommt direkt ausm Programm (siehe Code voriges Post) bzw. aus einem Memo aufm Formular.

Winni hat geschrieben:
Mo 2. Aug 2021, 17:03
Erstmal vergiss die ganzen Zugriffe aus der Windows-Unit. Damit fällst Du bei Mac oder Linux sofort auf die Nase. Die Komponenten Form, Image, Paintbox, Panel und viele mehr besitzen einen Canvas.

Die Größe gibt es durch

maxX := canvas.TextWidth('Irgendein Text');
maxY := canvas.TextHeight ('Noch n Text');

TextHeight brauch man nicht messen - das ist nach der Einstellung der Fonthöhe eine Konstante.
Diw Windows-Unit interessiert mich nur insofern, als ich sonst keine Idee habe, wie ich die Texthöhe dynamisch ermitteln könnte. Ich brauche ja nicht TextHeight, sondern die sich nach Wortumbruch ergebende Mehrzeilenhöhe (um später Zeilenhöhen zu ermitteln) des Rechtecks, dem ich die Breite vorgebe - also das, was or DT_CALCRECT macht.

Winni hat geschrieben:
Mo 2. Aug 2021, 17:03
Da kann man allerdings mit Single arbeiten. Ich weiß nicht mehr, ob das einfach für den Canvas umzuschreiben ist, denn der braucht Integer. Ich Kram mal rum.
Danke, Blocksatz brauch ich keinen, würde vor allem bei schmaleren Spalten nur mit Silbentrennung Sinn machen. Habe allerdings noch nicht ausprobiert, ob Lazarus in seinem TextRect soft hyphens kann. Delphi jedenfalls kanns nicht.

Viele Grüße
Martin

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von wp_xyz »

Jim Knopf hat geschrieben:
Mo 2. Aug 2021, 21:52
Diw Windows-Unit interessiert mich nur insofern, als ich sonst keine Idee habe, wie ich die Texthöhe dynamisch ermitteln könnte. Ich brauche ja nicht TextHeight, sondern die sich nach Wortumbruch ergebende Mehrzeilenhöhe (um später Zeilenhöhen zu ermitteln) des Rechtecks, dem ich die Breite vorgebe - also das, was or DT_CALCRECT macht.
Genau das kannst du mit DrawText erreichen, wenn das DT_CALCRECT Flag gesetzt ist. Aber nimm nicht die Unit Windows in die Uses-Zeile auf, sondern die Unit LCLIntf. Je nach Widgetset wird dabei die entsprechende Funktion aufgerufen.

Im Prinzip geht das auch mit Canvas.TextRect und entsprechend gesetztem TextStyle, aber ich habe vor kurzem gesehen, dass das Ergebnis etwas anders ausfällt. Das von DrawText ist "richtiger".

Das folgende Beispiel zeichnet einen passgenauen Rahmen um einen Text (mit Umlauten):

Code: Alles auswählen

uses
  LCLIntf, LCLType;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  txt: String;
  R: TRect;
  Flags: Integer;
begin
  txt := 'Hätte, hätte, Fahrradkette.';
  Paintbox1.Canvas.Brush.Color := clWhite;
  Paintbox1.Canvas.Brush.Style := bsSolid;
  Paintbox1.Canvas.FillRect(0, 0, Paintbox1.Width, Paintbox1.Height);

  R := Rect(20, 20, 100, 20);
  Flags := DT_WORDBREAK;
  DrawText(Paintbox1.Canvas.Handle, PChar(txt), Length(txt), R, Flags or DT_CALCRECT);
  Paintbox1.Canvas.Brush.Style := bsClear;
  Paintbox1.Canvas.Pen.Color := clRed;
  Paintbox1.Canvas.Rectangle(R);
  DrawText(Paintbox1.Canvas.Handle, PChar(txt), Length(txt), R, Flags);
end; 

Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

Hallo wp_xyz,

jaa, das mit den anderen Units war es, sozusagen Lazarus-Windows - danke! Funzt jetzt alles tadellos, sowohl Text aus dem Memo oder dem String. Super, zu wissen, war sehr lehrreich!

Bild

Viele Grüße
Martin

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: [gelöst] Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von wp_xyz »

Noch ein Tipp zur Windows-Unit: Delphi fügt automatisch die Windows- und Messages-Unit in jede Unit hinzu, obwohl sie oft gar nicht gebraucht werden. Versuche schon in Delphi diese Units zu entfernen. Wenn das Projekt weiterhin kompiliert, hast du wieder ein kleines Hindernis auf dem Cross-Platform-Weg beseitigt.

Wenn die Windows- und Messages-Unit drinnen bleiben müssen, ersetze Windows durch LCLIntf und LCLType (das weißt du ja jetzt; manchmal braucht man auch LCLProc) und Messages durch LMessages (in ein {$IFDEF FPC} setzen, damit die Unit auch noch unter Delphi verwendbar bleibt). Also:

Code: Alles auswählen

// Delphi
uses
  Windows, Messages, ...
  
// Lazarus
uses
{$IFDEF FPC}
  LCLIntf, LCLType, LMessages, ...
{$ELSE}
  Windows, Messages, ...
{$ENDIF}

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von PascalDragon »

Jim Knopf hat geschrieben:
Mo 2. Aug 2021, 21:44
danke für den Tipp, ist irgendwie strange, dass sich WordBreak nicht direkt setzen lässt, hat Set und Get beim Property - aber man muss nicht alles (gleich) verstehen (sonst schon :-) )
Der Typ der TextStyle Eigenschaft ist ein record. Wenn der Canvas dieses zurückgibt, arbeitest du auf einer temporären Kopie, das heißt alle Änderungen, die du dort machst kommen nicht am eigentlichen TextStyle des Canvas an (das ist so by-design!). Damit der User sich nun nicht stundenlang darüber wundert, dass sein Code nicht funktioniert ist das entsprechende Konstrukt (Schreibzugriff auf ein Feld einer record-Eigenschaft) in FPC (und auch neueren Delphi Versionen) verboten.
FPC Compiler Entwickler

Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: [gelöst] Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

@wp_xyz: Danke, sehr hilfreiche Informationen. Darüber, dass diese Units gar nicht immer gebraucht werden hate ich zu meiner Schande nie wirklich nachgedacht - ist aber sehr einleuchtend.

@PacalDragon: Auch danke für die Info.
Dass man bei DrawText den Record mitgeben kann, hat mich schon gewundert - eben deshalb, weil es ja nur temporär sein kann. Obwohl - er wird dann ja doch an den Canvas übergeben. Der ganze Record lässt sich aber mühelos austauschen und damit scheint es dann doch ...? Wo ist da unterm Strich der Unterschied? Das Textstyle-Property verweist doch direkt nach FTextStyle mitten in TCanvas. Warum dann solche Restriktionen? Dadurch wird man nur dazu angeleitet, sich zur Vereinfachung Funktionen wie diese zu machen, die das ganze ›Sicherheitssystem‹ einfach aushebeln.

Ich bin nun aber, wo ich mal reingeschaut habe, doch verwirrt: via TCanvas lande ich bei DrawText flugs un der winapih.inc. Ist die jetzt ›plattformsauber‹ oder wie kann ich sonst die Höhe von Mehrzeilentext errechnen und ihn dann ausgeben?

Viele Grüße
Martin

P.S.: Quatsch, Quatsch, ich hab auf die Variante 1 in meinem Text geschaut mit DrawText, die ja zu vermeiden ist. Richtigstellung kommt gleich

Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

Jetzt hoffentlich klarer.
Bitte nicht ungehalten sein, dass ich nicht ganz kapiere und darauf rumreite. Ich muss etwas ganz verstehen, sonst kann ich diese Richtung nicht mit gutem Gewissen weiter verfolgen.


ich habe zwei Varianten.

Variante 1 mit DrawText

Code: Alles auswählen

const Tx: string = 'Das ist ein längerer Text für diesen Futzi, schauen, ob er den Windows-Kram sauber macht inklusive Zeilenumbruch beim Zeichnen?';
var R: TRect;
    S: string;
begin
  R := Classes.Rect(50, 50, 300, 100);
  with pb.Canvas do
  begin
    Brush.Color := pa3.Color;
    Pen.Style := psClear;
    Rectangle(pb.ClientRect);
    Brush.Color := pa4.Color;
    Rectangle(R);
    if cbTxMemo.Checked then
      S := m.Text
    else
      S := Tx;

    // Texthöhe ausrechnen
    DrawText(Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or DT_CALCRECT);
    // Nötig, um das Rechteck sauber hinzubekommen; wenn das fehlt, so wie laut Bild 1
    R.Right := 300;
    Rectangle(R);
    // Eigentliche Ausgabe
    [b]DrawText[/b](Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL);
  end;
Fazit:
uses ..., Windows; - Umlaute falsch. Hier komme ich mit DrawText nach Redef.inc, scheint die reine Windows-Variante zu sein
uses ..., LCLIntf, LCLType; - Umlaute okay. Hier lande ich mit DrawText in winapih.inc ... ist die plattformsauber?
Bild

Variante 2 mit TextRect

Code: Alles auswählen

const Tx: string = 'Das ist ein längerer Text für diesen Futzi, schauen, ob er den Windows-Kram sauber macht inklusive Zeilenumbruch beim Zeichnen?';
var R: TRect;
    S: string;
    TS: TTextStyle;
begin

  R := Classes.Rect(50, 50, 300, 100);
  with pb.Canvas do
  begin
    ts := TextStyle;
    ts.WordBreak := True;
    ts.EndEllipsis := True;

    Brush.Color := pa3.Color;
    Pen.Style := psClear;
    Rectangle(pb.ClientRect);
    Brush.Color := pa4.Color;
    Rectangle(R);
    if cbTxMemo.Checked then
      S := m.Text
    else
      S := Tx;

    // Texthöhe ausrechnen
    DrawText(Handle, PChar(S), Length(Tx), R, DT_LEFT or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or DT_CALCRECT);
    // Variante II - Lazarus
    R.Right := 300;
    Rectangle(R);
    Brush.Style := bsClear;
    TextStyle := ts;
    [b]TextRect[/b](R, 52, 52, S, ts);
    // Anzeige Rechteck
    sh.Height := R.Bottom-R.Top;
  end;
Fazit:
Auch hier sauber mit: uses ..., LCLIntf, LCLType; - Umlaute zwar okay. Aber nur eine Zeile, und die abgeschnitten, pfeift also auf den Wortumbruch, obwohl er via ts eingestellt worden ist.
Bild

Kann ich also dafür nur DrawText verwenden? Ist die winapih.inc plattformkompatibel??

Nochmal sorry, dass ich hier so ein Fass aufmache. Aber wenn ich erst später draufkomme, dass was nicht geht, ist das bei einer größeren Sache ziemlich blöd.
Viele Grüße
Martin

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von fliegermichl »

Ich kann die angehängten Bilder nicht sehen.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von wp_xyz »

Ja, winapi ist plattformunabhängig, wenn LCLIntf verwendet wird. Vergiss den Namen. Der Compiler stellt fest, welches Widgetset zuständig ist, und leitet alle Aufrufe von widgetset-abhängigen Routinen in die entsprechende Unit bzw. Include-datei des Widgetset um. Du findest diese im entsprechenden Unterordner von lcl/interfaces der Lazarus-Installation. Unter Windows führt ein Aufruf von DrawText in die Include Datei win32/win32winapi(h).inc, wo nach einer Konvertierung von ANSI-String zu WideString die Windows-Funktion DrawTextW für WideStrings aufgerufen wird. Unter Linux gtk2 führt DrawText in gtk2/gtk2winapi.inc auf Umwegen zur Methode DrawTextWithColor des TGtkDeviceContext. Analog für andere Widgetsets.

Dass beim Aufruf von Windows.DrawText die Umlaute nicht richtig sind, liegt daran, dass die Windows-Unit per default Code-Seiten-codierte Strings erwartet, bei uns CP1252, Lazarus aber einen UTF8-codierten String anbietet (dort sind die Umlaute zwei Bytes lang). LCLIntf.DrawText führt dagegen, wie schon erwähnt, eine Umcodierung der Strings durch. Du könntest auch Windows.DrawTextW verwenden - da ist der String ein Widestring in UTF16-Kodierung, bei dem jedes Zeichen (vereinfacht) aus zwei Bytes besteht, aber nun müsstest du vor dem Aufruf in Lazarus den UTF8-String nach UTF16 umwandeln. Daher: Vergiss die Windows-Unit (bis auf die paar Fälle, in denen nicht alles nach Lazarus portiert wurde).

Benutzeravatar
Jim Knopf
Beiträge: 98
Registriert: So 18. Mai 2014, 15:16
OS, Lazarus, FPC: Win10
CPU-Target: 64Bit
Wohnort: Klagenfurt
Kontaktdaten:

Re: Windows.DrawText oder Canvas.Textrect - keines tut, was es soll?

Beitrag von Jim Knopf »

@Fliegermichl: Rechte Maustaste > Grafikadresse kopieren und die im Browser eingeben ...?

@wp_xyz: Danke, dann bin ich mal beruhigt, dass ich via winapi DrawText verwenden kann. Von der Windows-Unit werde ich also nachhaltig die Finger lassen.

Antworten