Richedit

Fragen rund um diverse Windows-Versionen, ihr Verhalten unter Xbase++ und den Umgang mit der API

Moderator: Moderatoren

Antworten
Rolli
Rookie
Rookie
Beiträge: 6
Registriert: Fr, 21. Mär 2014 13:16

Richedit

Beitrag von Rolli »

Hallo,

ich versuche seit einiger Zeit im Internet und in verschiedenen Handbüchern eine Lösung für meine Frag zu finden, leider erfolglos.

in VO kann ich über die API-Funktion

TextOut := SendMessage( hDC, EM_FORMATRANGE, 1, LONG(_CAST, @strucFormatRange))

ein Richedit-Control an einer bestimmten Stelle, z.B. auf einer Druckseite, ausgeben und bekomme als Ergebnis die Anzahl der ausgegebenen Zeichen.

Ich brauche aber die Höhe in Pixeln oderTwips, den der ausgegebene Text wirklich benötigt hat, damit ich berechnen kann, wo der nächste Text beginnt.

Gibt es dafür eine Funktion, die das macht ? Vorab vielen Dank.

Rolli
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Richedit

Beitrag von Jan »

Hallo Rolf,

Du müsstes ja wissen, wie viele Zeilen Du gebraucht hast für den Ausdruck. Wenn Du das hast und die Schriftgröße, dann müsste derRest eigentlich klappen.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Richedit

Beitrag von brandelh »

Was genau möchtest du machen und geht es um VO oder Xbase++ ?

wenn du mit den GraFunktionen drucken willst, gibt es eine Funktion die die Größe des Strings in 5 Werten zurückgibt:
GraQueryTextBox() - Koordinaten für die Umrandung (Rahmen) einer Zeichenkette ermitteln
Beides hängt vom Ausgabesystem ab (Presentationspace) => GraStringAt()

Was dein externes Control kann weis ich nicht, wobei man aus Zeichenhöhe (in point) und Zeilenabstand das schon berechnen kann (wenn der Font stimmte).
Bei gemischtem Text mit NORMAL und BOLD oder verschiedenen Schriften (Größe, Art) wird es natürlich umso schwerer ...

Wenn bei den GRA Funktionen die gleichen Parameter (Auflösung) eingestellt werden und jede Schriftart genau eingestellt wird (also Höhe, Fett, Kursiv etc.)
könnte man mit GraQueryTextBox() die einzelnen Längen berechnen (nur verbreitete Standardschriften verwenden) und mit dem Zeilenvorschub die Gesamtgröße.

Ein heiden Aufwand ohne Erfolgsgarantie !

Eventuell wäre es einfacher entweder ein besseres Control zu nutzen oder einen Reportgenerator verwenden. TOM hat damit viel Erfahrung ;-)
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Richedit

Beitrag von AUGE_OHR »

Rolli hat geschrieben:in VO kann ich über die API-Funktion

TextOut := SendMessage( hDC, EM_FORMATRANGE, 1, LONG(_CAST, @strucFormatRange))
Das selbe kannst du auch unter Xbase++ mit ot4xb machen.
ot4xb wird benötigt für die FORMATRANGE Structure
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

den hDC erhält du mit oPS:lockHDC() / oPS:UnlockHDC() wobei oPS das "XbpPresSpace Object" ist.
Rolli hat geschrieben:ein Richedit-Control an einer bestimmten Stelle, z.B. auf einer Druckseite, ausgeben und bekomme als Ergebnis die Anzahl der ausgegebenen Zeichen.
Frage : ist das RFT Control ein activeX ?

XbpRTF() benötigt RICHTX32.OCX als activeX

Rolli hat geschrieben:Ich brauche aber die Höhe in Pixeln oderTwips, den der ausgegebene Text wirklich benötigt hat, damit ich berechnen kann, wo der nächste Text beginnt.
wie Hubert schon sagte gibt es unter Xbase++ GraQueryTextBox()

selbstverständlich kannst du auch mit der API Function GetTextExtentPoint32 arbeiten

Code: Alles auswählen

GetTextExtents( hDC, substr( cText, 1, i ), @nWidth, @nHeight )

FUNCTION GetTextExtents( hDC, cText, nWidth, nHeight )
LOCAL sSize := space(8)
LOCAL lOK   := FALSE

STATIC tpl
IF tpl = NIL
   tpl := DllPrepareCall( "gdi32.dll", DLL_STDCALL, "GetTextExtentPoint32A" )
ENDIF

IF DllExecuteCall( tpl, hDC, cText, len( cText ), @sSize ) <> 0
   lOK     := TRUE
   nWidth  := Bin2L( substr( sSize, 1, 4 ) )
   nHeight := Bin2L( substr( sSize, 5, 4 ) )
ENDIF

RETURN lOK
gruss by OHR
Jimmy
Rolli
Rookie
Rookie
Beiträge: 6
Registriert: Fr, 21. Mär 2014 13:16

Re: Richedit

Beitrag von Rolli »

Hallo,

erst einmal vielen Dank für die schnellen Antworten.

Ich habe allerdings das Gefühl, dass meine Frage etwas unglücklich und daher unverständlich gestellt war. Daher versuche ich es noch einmal anders.

"PtrOfPrintingDevice" und "strucFormatRange" sind korrekt ausgefüllt. Mit

SendMessage( PtrOfRichedit, WM_GETTEXTLENGTH, 0, 0)

erhalte ich die wirkliche Anzahl der Zeichen im RichEditControl, ohne die RTF-Formatierung. Mit

SendMessage( PtrOfPrintingDevice, EM_FORMATRANGE, 1, @strucFormatRange )

wird die Anzahl der gedruckten Zeichen zurückgegeben. Wenn der gesamte Text in den vorgegebenen Rahmen passt, dann stimmt diese Anzahl mit der Gesamtanzahl überein, wenn nicht, so wird nur die Anzahl der gedruckten Zeichen zurückgegeben.

Das heißt für mich, dass dort eine Berechnung stattfindet, wieviele Pixel oder Twips der Text in Länge und Breite hat und ob er in den Rahmen passt.

Diese Werte hätte ich gern. Daher die Frage : Gibt es eine Möglichkeit über Windows-API an diese Werte zu kommen, z.B. durch einen Aufruf wie diesen :

SendMessage( PtrOfPrintingDevice, EM_GETSIZEOFTEXT, 1, @strucFormatRange )

Ich hoffe ich habe die Verwirrung nicht noch gesteigert.

Rolf
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Richedit

Beitrag von Jan »

Rolf,

aber was nützt Dir die Anzahl der Zeichen, wenn Du nicht weißt, wie viele davon in eine Zeile passen, und wie viele Zeilen das dann letztendlich werden? Denn die Gesamthöhe des Ausdruckes ist doch abhängig von der Schriftart, -größe, und Zeilenzahl.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Rolli
Rookie
Rookie
Beiträge: 6
Registriert: Fr, 21. Mär 2014 13:16

Re: Richedit

Beitrag von Rolli »

Hallo Jan,

wenn ich die Anzahl der ausgegebenen Zeichen mit der Gesamtzahl der Zeichen vergleiche, dann kann ich feststellen ob alles gedruckt ist oder ob ich für den Rest eine neue Seite aufrufen muß. Daher ist es für mich wichtig, dass ich die Anzahl der bereits ausgegebenen Zeichen kenne.
Das hat aber nichts mit meiner Frage zu tun. Ich möchte wissen, wieviel Pixel oder Twips für die Ausgabe benötigt werden, wenn der Text kleiner ist als die von mir vorgegebene Größe des Rahmens.

Beispiel :
Ich deklariere als Ausgabebereich das komplette DIN-A4-Blatt. z.B. 10000 Breite * 16000 Länge Twips
Dann drucke ich den ersten RTF-Text ( 100 Zeichen ) aus.
Diese 100 Zeichen benötigen aber nur 10000 * 3000 Twips.
Ich könnte also bei Länge 3100 den nächsten Text ausgeben, wenn ich wüsste, dass der erste Text nur eine Länge von 3000 Twips gebraucht hätte.
"Sendmessage" gibt mir nur die Anzahl der Zeichen, die es gedruckt hat, nicht die Twips ( Breit und Höhe ), die es dafür benötigt hat.
Die Anzahl der Twips können aber jedesmal unterschiedlich sein, auch wenn die Anzahl der Zeichen gleich sind, das ist von den Fonts abhängig, die im Text vertreten sind.

Ich hatte nun gehofft, dass, da "Sendmessage( ... )" in der Lage ist, mir zu sagen, wieviele Zeichen in einen bestimmten Bereich der Druckseite passen, mir eine ähnliche Funktion auch sagen kann wieviel Twips dafür benötigt werden.

Rolf
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Richedit

Beitrag von AUGE_OHR »

Rolli hat geschrieben:"PtrOfPrintingDevice" und "strucFormatRange" sind korrekt ausgefüllt. Mit

SendMessage( PtrOfRichedit, WM_GETTEXTLENGTH, 0, 0)

erhalte ich die wirkliche Anzahl der Zeichen im RichEditControl, ohne die RTF-Formatierung. Mit

SendMessage( PtrOfPrintingDevice, EM_FORMATRANGE, 1, @strucFormatRange )

wird die Anzahl der gedruckten Zeichen zurückgegeben. Wenn der gesamte Text in den vorgegebenen Rahmen passt, dann stimmt diese Anzahl mit der Gesamtanzahl überein, wenn nicht, so wird nur die Anzahl der gedruckten Zeichen zurückgegeben.
Xbase++ kann keine STRUCTURE, dafür benötigst du ot4xb.

die FORMATRANGE Structure enthält :

Type: HDC
Type: RECT
Type: CHARRANGE
Rolli hat geschrieben:Das heißt für mich, dass dort eine Berechnung stattfindet, wieviele Pixel oder Twips der Text in Länge und Breite hat und ob er in den Rahmen passt.

Diese Werte hätte ich gern. Daher die Frage : Gibt es eine Möglichkeit über Windows-API an diese Werte zu kommen, z.B. durch einen Aufruf wie diesen :

SendMessage( PtrOfPrintingDevice, EM_GETSIZEOFTEXT, 1, @strucFormatRange )
der Type RECT liefert dir doch die Werte :
Units are measured in twips.
Xbase++ hat einen Presentationspace als Object dessen Handle ( hDC ) du mit oPS:lockHDC() bekommst.
die API Function GetTextExtentPoint32 gibt dir nun Pixel zurück welche du, bezogen auf den verwendeten Desktop Font (DPI), in Twips umrechnen kannst.

Code: Alles auswählen

DLLFUNCTION GetDC(hwnd) USING STDCALL FROM user32.dll
DLLFUNCTION ReleaseDC(hwnd,hdc) USING STDCALL FROM user32.dll

#define HWND_DESKTOP 0
#define LOGPIXELSX   88
#define LOGPIXELSY   90

FUNCTION TwipsPerPixel()
LOCAL nX
LOCAL nY
LOCAL hDC

   hDC := GetDC(HWND_DESKTOP)

   nX := 1440 / GetDeviceCaps(hDC,LOGPIXELSX)
   nY := 1440 / GetDeviceCaps(hDC,LOGPIXELSY)

   ReleaseDC(HWND_DESKTOP,hDC)

RETURN {nX,nY}
gruss by OHR
Jimmy
Rolli
Rookie
Rookie
Beiträge: 6
Registriert: Fr, 21. Mär 2014 13:16

Re: Richedit

Beitrag von Rolli »

Hallo,

Euch allen vielen Dank. Das Problem ist mit Hilfe Eurer Denkanstösse gelöst.

Rolf
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Re: Richedit

Beitrag von UliTs »

Rolli hat geschrieben:Hallo,
Euch allen vielen Dank. Das Problem ist mit Hilfe Eurer Denkanstösse gelöst.
Rolf
Wie hast Du es gelöst?

Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Rolli
Rookie
Rookie
Beiträge: 6
Registriert: Fr, 21. Mär 2014 13:16

Re: Richedit

Beitrag von Rolli »

Es ist eigentlich ganz einfach, wenn man es weiß. Hier der VO-Code :

SendMessage( SELF:Handle(), EM_FORMATRANGE, 0, LONG(_CAST, @strucFormatRange ) )
nTextHeight := strucFormatRange.rc.Bottom - strucFormatRange.rc.top

wobei „SELF:Handle()“ der Pointer auf das Richedit-Control ist und „strucFormatRange „ eine Windows-Struktur ist :

STRUCT _winformatrange
MEMBER hdc AS PTR
MEMBER hdcTarget AS PTR
MEMBER rc IS _WINRECT
MEMBER rcPage IS _WINRECT
MEMBER chrg IS _wincharrange

Wobei mit “Sendmessage” in „rc“ die Koordinaten des wirklich ausgegeben Textbereichs zurückgegeben werden und man dann mit ( rc.bottom – rc.top ) die Länge ermitteln kann.

Rolf
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Richedit

Beitrag von Jan »

Rolf,

so sehr es mich freut das Dir geholfen werden konnte - bist Du sicher, das Du hier im richtigen Forum bist? Das hier ist für Xbase++, nicht VO. Mit Deinem Code kann daher hier auch eher niemand etwas anfangen.

Es gibt hier einen Forenbereich für Entwickler von Verwandten Sprachen. Da kann man Fragen zu diesen Sprachen stellen, die aber nicht zwingend auch beantwortet werden (können). Da die Entwickler hier eben halt andere Schwerpunkte haben.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Richedit

Beitrag von brandelh »

Jan hat geschrieben:Rolf,
so sehr es mich freut das Dir geholfen werden konnte - bist Du sicher, das Du hier im richtigen Forum bist?
JAN meint, dass bei unseren dürftigen bis gar nicht vorhandenen VO Kenntnissen kaum einer helfen kann ... :-)

Ich weiß von PowerBasic, dass man mit sendMessage() die Controls ansprechen kann (aber was und wie ... ne ich will HochSprache !),
die vielen Casts (igitt igitt) die man in VO (1...) verwenden musste damit es überhaupt lief neben den Instabilitäten waren aber mit ein Grund warum ich VO den Rücken gekehrt habe.
Wenn ich C++ hätte programmieren wollen, wäre ich zu Visual C++ gegangen ;-)
Gruß
Hubert
Rolli
Rookie
Rookie
Beiträge: 6
Registriert: Fr, 21. Mär 2014 13:16

Re: Richedit

Beitrag von Rolli »

Hallo,

ich bin eigentlich davon ausgegangen, dass Alaska xBase, Clipper und der Clipper-Nachfolger Visual Object zu einer Sprachenfamilie gehören und somit zur xBase-Welt gehören. Ich selber habe bis vor 10 Jahren bei der Deutschen Post zuerst in Clipper und dann in xBase programmiert und meinte deshalb, dass hier meine Probleme beantwortet werden können, da die beiden Sprachen fast identisch waren.
Außerdem hatte ich meine Frage bewust in der Rubrik Windows API eingestellt. Wie sich herausstellte war es dann ja auch die Windowsfunktion "Sendmessage", die zur Lösung des Problems beitrug. VO-Wissen war garnicht nötig.

Trotz allem noch einmal vielen Dank.

Rolf
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Richedit

Beitrag von Jan »

Hallo Rolf,

nicht das wir uns mißverstehen: Dich will hier keiner los werden! Wir sind hier ein wirklich netter Haufen :-D

Allerdings haben sich die verschiedenen Clipper-Nachfolger ja dermaßen auseinander entwickelt, das man bis auf ein paar Grundlagen schwer gegenseitige Hilfe bieten kann. In Deinem Fall hat das zum Glück geklappt, aber auch eher zufällig.

Daher einfach nur mein Kommentar oben. Klar kannst Du auch weiterhin hier Fragen stellen. Wenn es dabei wieder um VO geht, dann aber bitte lieber in dem passenden Unterforum. Dann weiß gleich jeder, das es abseits des Foren-Mainstreams geht und was ihn in Deiner Frage grob erwartet. Und erwarte halt nicht zu viel. Ich weiß von mindestens einem, der sowohl Xbase++ als auch VO schreibt, und der hier im Forum sporadisch unterwegs ist. Aber tieferes VO-Wissen wirst Du hier normalerweise halt nicht finden können.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Richedit

Beitrag von AUGE_OHR »

hi,

Rolf hat im Prinzip recht ... Der Title des Form ist falsch !

Es gibt eine Windows API, auf der auch Xbase++ aufbaut, und keine "spezielle" Xbase++ Windows API.
vielmehr ist die "spezielle" Xbase++ Windows API eingeschränkt und man braucht z.b. ot4xb für STRUCTURE was viele API Aufrufe benötigen.

man sollte also froh darüber sein wenn jemand Windows API Fragen hat die "auch" für Xbase++ anwendbar sind.
gruss by OHR
Jimmy
Antworten