 |
| |
|
|
 |
Autor |
Nachricht |
 |
| |
| himitsu |
#16| Verfasst am: 31.01.2010, 12:55 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
OK, es scheint jetzt zu funktionieren.
Falls ihr also mal testen wollt, ob es so auch nutzbar ist (siehe Anhang) ... es müssen ja einige Indize/Längen angepaßt/verändert/verfälscht werden.
Wenn es dann so OK ist, dann werd' ich die ClassHelper-Version auch noch umstellen.
Und kann mich eventuell noch ein bissl ans Optimieren machen.
Für diese direkte Änderung werde/muß ich dann noch die interne StringList (TRichEditStrings) irgendwie ändern, da .Lines.Add und Co. teilweise mit den "falschen" Werten arbeitet und es somit zu Fehlern kommt.
PS: Emba hat dort ja mitbekommen, daß die Indize nicht stimmen, haben selber schon Anpassungen vorgenommen, aber nur dort und sie prüfen am Ende das Ergebnis, welches ja jetzt, dank der "korrekten" Indize, natürlich anders ist.
Delphi-Quellcode: | zusammenfalten | markieren | 1 · · · 5 · · · · 10 · · · · 15 · · · · 20 · · · · 25 · · · · 30
| procedure TRichEditStrings.Insert(Index: Integer; const S: string);
...
const
CRLF = #13;
...
begin
if Index >= 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
if Selection.cpMin >= 0 then
Fmt := '%s' + CRLF
else
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index - 1, 0);
if Selection.cpMin < 0 then Exit;
L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
if L = 0 then Exit;
Inc(Selection.cpMin, L);
Fmt := CRLF + '%s';
end;
Selection.cpMax := Selection.cpMin;
SendStructMessage(RichEdit.Handle, EM_EXSETSEL, 0, Selection);
Str := Format(Fmt, [S]);
SendTextMessage(RichEdit.Handle, EM_REPLACESEL, 0, Str);
// RichEdit 2.0 replaces CRLF pairs with CR. We need to account for that when
// verifying that the insertion succeeded in case S contains a CRLF pair.
if RichEdit.SelStart <> (Selection.cpMax + Length(Str) - CountLineBreaks(Str)) then
raise EOutOfResources.Create(sRichEditInsertError);
end;
end; |
|
if RichEdit.SelStart <> liefert ja nun ein anderes Ergebnis, darum die Exception bei .Add . |
| [ An diesen Beitrag wurden eine oder mehrere Dateien angehängt. Zum Herunterladen bitte anmelden. ] |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 31.01.2010, 13:22, insgesamt 1-mal bearbeitet. |
 |
|
|
|
| |
| himitsu |
#17| Verfasst am: 01.02.2010, 20:59 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
Bin grad dabei den letzen Feinschliff am Code vorzunehmen.
Die sehr unoptimalen Stringoperationen und Schleifen bin ich aber schonmal losgeworden.
Aber eines kann ich schonmal sagen:
Den Patch wird es nurnoch in Form des Class Helpers geben
Der Grund: Die interne StringListe, an deren Deklaration ich nicht rankomm und weswegen sich dort so "schlecht" was dran patchen läßt.
Aber ohne einen Patch der StringList, ließe sie sich nicht mehr verwenden und bei .Lines.Add und .Lines.Insert würde es Exceptions durch eine nun fehlerhafte Prüfung geben, Aufgrund des Patches im RichEdit.
Der komplette Patch sollte dann also besser direkt von Emba als Update erfolgen.
Diesen stell ich aber auch grad zusammen und lade ihn dann im EDN-Artikel hoch.
(wenn unbedingt nötig kann sich dann ja jeder selber diese Codes von dort holen, die ComCtrls.pas patchen und natürlich neu kompilieren) |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 01.02.2010, 21:01, insgesamt 1-mal bearbeitet. |
 |
|
|
|
| |
| himitsu |
#18| Verfasst am: 01.02.2010, 22:42 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
| Hazebukelar hat folgendes geschrieben: | Danke - ich habe Deinen Code#2 mal geprüft.
Läuft prima wenn man im Memo von oben nach unten sucht.
Bei Suchrichtung von unten nach oben wird der erste Suchbegriff gefunden und
auch richtig markiert, aber nicht nach dem nächsten SearchString weitergesucht... |
Da es hier nur was am Selektieren geändert wurde, sollte dieses nicht von der Suchrichtung abhängen ... ich würde also einen derartigen "Fehler" eher im Suchalgo vermuten?
(fall es denn nicht an der noch fehlerhaften Selektierung lag)
Kannst du daher bitte den Class-Helper nochmals testen?
Delphi-Quellcode: | zusammenfalten | markieren | 1 · · · 5 · · · · 10 · · · · 15 · · · · 20 · · · · 25 · · · · 30 · · · · 35 · · · · 40 · · · · 45 · · · · 50 · · · · 55 · · · · 60 · · · · 65 · · · · 70 · · · · 75 · · · · 80 · · · · 85 · · · · 90 · · · · 95 · · · · 100 · · · · 105 · · · · 110 · · · · 115 · · · · 120 · · · · 125 · · · · 130 · · · · 135 · · · · 140 · · · · 145 · · · · 150 · · · · 155 · · 158
| TRichEditHelper = Class Helper for TRichEdit
Private
Function AdjustInternalLineBreaks(Const S: String): String;
Function XGetSelStart: Integer;
Procedure XSetSelStart ( Value: Integer);
Function XGetSelLength: Integer;
Procedure XSetSelLength( Value: Integer);
Function XGetSelText: String;
Procedure XSetSelText (Const Value: String);
Function XGetTextStr: String;
Procedure XSetTextStr (Const Value: String);
Public
Property SelStartX: Integer Read XGetSelStart Write XSetSelStart;
Property SelLengthX: Integer Read XGetSelLength Write XSetSelLength;
Property SelTextX: String Read XGetSelText Write XSetSelText;
Property TextX: String Read XGetTextStr Write XSetTextStr;
End;
Uses RichEdit, StrUtils;
Function TRichEditHelper.AdjustInternalLineBreaks(Const S: String): String;
Var i, i1, i2: Integer;
Begin
Result := S;
i1 := -1;
i2 := -1;
i := 1;
While True do Begin
If (i1 <> 0) and (i1 <= i) Then i1 := PosEx(#13#10, Result, i);
If (i2 <> 0) and (i2 <= i) Then i2 := PosEx(#10, Result, i);
i := i1;
If (i2 > 0) and (i2 < i) Then i := i2;
If i <= 0 Then Break;
If Result[i] = #13 Then Delete(Result, i + 1, 1) Else Result[i] := #13;
Inc(i);
End;
End;
Function TRichEditHelper.XGetSelStart: Integer;
Var CharRange: TCharRange;
Begin
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
Result := CharRange.cpMin + SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0);
End;
Procedure TRichEditHelper.XSetSelStart(Value: Integer);
Var L, T, Tx, i: Integer;
CharRange: TCharRange;
Begin
L := SendMessage(Handle, EM_GETLINECOUNT, 0, 0);
If (L > 0) and (Value > 0) Then Begin
i := SendMessage(Handle, EM_LINEINDEX, L - 1, 0);
If i + L - 1 + SendMessage(Handle, EM_LINELENGTH, i, 0) >= Value Then Begin
Tx := (L + 1) div 2;
T := 0;
i := 0;
While (Value < i) or (i + SendMessage(Handle, EM_LINELENGTH, i - T, 0) + 1 < Value) do Begin
Inc(T, Tx);
If T < 0 Then T := 0 Else If T >= L Then T := L - 1;
i := SendMessage(Handle, EM_LINEINDEX, T, 0) + T;
If (i > Value) and (Tx > 0) Then Tx := -(Tx + 1) div 2;
If (i < Value) and (Tx < 0) Then Tx := (-Tx + 1) div 2;
End;
Dec(Value, T);
End Else Dec(Value, L);
End;
CharRange.cpMin := Value;
CharRange.cpMax := Value;
SendStructMessage(Handle, EM_EXSETSEL, 0, CharRange);
End;
Function TRichEditHelper.XGetSelLength: Integer;
Var TextLen: TGetTextLengthEx;
MaxLen: Integer;
CharRange: TCharRange;
Begin
TextLen.Flags := GTL_NUMCHARS;
TextLen.CodePage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Result := CharRange.cpMax - CharRange.cpMin
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0)
+ SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0);
End;
Procedure TRichEditHelper.XSetSelLength(Value: Integer);
Var i: Integer;
CharRange: TCharRange;
Begin
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
CharRange.cpMax := CharRange.cpMin + Value + 1;
i := SendMessage(Handle, EM_LINEINDEX, SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0), 0);
Repeat
Inc(i, SendMessage(Handle, EM_LINELENGTH, i, 0) + 1);
Dec(CharRange.cpMax);
Until i >= CharRange.cpMax;
SendStructMessage(Handle, EM_EXSETSEL, 0, CharRange);
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
End;
Function TRichEditHelper.XGetSelText: String;
Var TextLen: TGetTextLengthEx;
MaxLen, Len: Integer;
CharRange: TCharRange;
T: TGetTextEx;
Begin
TextLen.Flags := GTL_NUMCHARS;
TextLen.CodePage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Len := CharRange.cpMax - CharRange.cpMin
+ SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0)
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0);
SetLength(Result, Len);
T.cb := (Len + 1) * SizeOf(Char);
T.Flags := GT_SELECTION or GT_USECRLF;
T.codepage := 1200;
T.lpDefaultChar := nil;
T.lpUsedDefChar := nil;
SendMessage(Handle, EM_GETTEXTEX, WPARAM(@T), LPARAM(PChar(Result)));
End;
Procedure TRichEditHelper.XSetSelText(Const Value: String);
Begin
SendTextMessage(Handle, EM_REPLACESEL, 0, AdjustInternalLineBreaks(Value));
End;
Function TRichEditHelper.XGetTextStr: String;
Var TextLen: TGetTextLengthEx;
Len: Integer;
CharRange: TCharRange;
T: TGetTextEx;
Begin
TextLen.Flags := GTL_NUMCHARS or GT_USECRLF;
TextLen.CodePage := 1200;
Len := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SetLength(Result, Len);
T.cb := (Len + 1) * SizeOf(Char);
T.Flags := GT_USECRLF;
T.codepage := 1200;
T.lpDefaultChar := nil;
T.lpUsedDefChar := nil;
SendMessage(Handle, EM_GETTEXTEX, WPARAM(@T), LPARAM(PChar(Result)));
End;
Procedure TRichEditHelper.XSetTextStr(Const Value: String);
Begin
SendTextMessage(Handle, WM_SETTEXT, 0, AdjustInternalLineBreaks(Value));
End; |
|
Hier doch nochmal den aktuellen Code, also alles was in der ComCtrls.pas geändert werden müßte.
(wenn der Class-Helper OK ist, dann würde ich dieses dann an Emba weiterleiten)
Delphi-Quellcode: | zusammenfalten | markieren | 1 · · · 5 · · · · 10 · · · · 15 · · · · 20 · · · · 25 · · · · 30 · · · · 35 · · · · 40 · · · · 45 · · · · 50 · · · · 55 · · · · 60 · · · · 65 · · · · 70 · · · · 75 · · · · 80 · · · · 85 · · · · 90 · · · · 95 · · · · 100 · · · · 105 · · · · 110 · · · · 115 · · · · 120 · · · · 125 · · · · 130 · · · · 135 · · · · 140 · · · · 145 · · · · 150 · · · · 155 · · · · 160 · · · · 165 · · · · 170 · · · · 175 · · · · 180 · · · · 185 186
| Function TRichEdit.GetSelStart: Integer;
Var CharRange: TCharRange;
Begin
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
Result := CharRange.cpMin + SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0);
End;
Procedure TRichEdit.SetSelStart(Value: Integer);
Var L, T, Tx, i: Integer;
CharRange: TCharRange;
Begin
L := SendMessage(Handle, EM_GETLINECOUNT, 0, 0);
If (L > 0) and (Value > 0) Then Begin
i := SendMessage(Handle, EM_LINEINDEX, L - 1, 0);
If i + L - 1 + SendMessage(Handle, EM_LINELENGTH, i, 0) >= Value Then Begin
Tx := (L + 1) div 2;
T := 0;
i := 0;
While (Value < i) or (i + SendMessage(Handle, EM_LINELENGTH, i - T, 0) + 1 < Value) do Begin
Inc(T, Tx);
If T < 0 Then T := 0 Else If T >= L Then T := L - 1;
i := SendMessage(Handle, EM_LINEINDEX, T, 0) + T;
If (i > Value) and (Tx > 0) Then Tx := -(Tx + 1) div 2;
If (i < Value) and (Tx < 0) Then Tx := (-Tx + 1) div 2;
End;
Dec(Value, T);
End Else Dec(Value, L);
End;
CharRange.cpMin := Value;
CharRange.cpMax := Value;
SendStructMessage(Handle, EM_EXSETSEL, 0, CharRange);
End;
Function TRichEdit.GetSelLength: Integer;
Var TextLen: TGetTextLengthEx;
MaxLen: Integer;
CharRange: TCharRange;
Begin
TextLen.Flags := GTL_NUMCHARS;
TextLen.CodePage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Result := CharRange.cpMax - CharRange.cpMin
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0)
+ SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0);
End;
Procedure TRichEdit.SetSelLength(Value: Integer);
Var i: Integer;
CharRange: TCharRange;
Begin
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
CharRange.cpMax := CharRange.cpMin + Value + 1;
i := SendMessage(Handle, EM_LINEINDEX,
SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0), 0);
Repeat
Inc(i, SendMessage(Handle, EM_LINELENGTH, i, 0) + 1);
Dec(CharRange.cpMax);
Until i >= CharRange.cpMax;
SendStructMessage(Handle, EM_EXSETSEL, 0, CharRange);
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
End;
Function TRichEdit.GetSelText: String;
Var TextLen: TGetTextLengthEx;
MaxLen, Len: Integer;
CharRange: TCharRange;
T: TGetTextEx;
Begin
TextLen.Flags := GTL_NUMCHARS;
TextLen.CodePage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Len := CharRange.cpMax - CharRange.cpMin
+ SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0)
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0);
SetLength(Result, Len);
T.cb := (Len + 1) * SizeOf(Char);
T.Flags := GT_SELECTION or GT_USECRLF;
T.codepage := 1200;
T.lpDefaultChar := nil;
T.lpUsedDefChar := nil;
SendMessage(Handle, EM_GETTEXTEX, WPARAM(@T), LPARAM(PChar(Result)));
End;
//Procedure TRichEdit.SetSelText(Const Value: String);
// Begin
// {$IF DEFINED(CLR)}
// If not Assigned(Value) Then
// SendTextMessage(Handle, EM_REPLACESEL, 0, '')
// Else
// {$IFEND}
// SendTextMessage(Handle, EM_REPLACESEL, 0, FRichEditStrings.AdjustInternalLineBreaks(Value));
// End;
Function TRichEditStrings.AdjustInternalLineBreaks(Const S: String): String;
Var i, i1, i2: Integer;
Begin
Result := S;
i1 := -1;
i2 := -1;
i := 0;
While True do Begin
If (i1 <> 0) and (i1 < i) Then i1 := PosEx(#13#10, Result, i + 1);
If (i2 <> 0) and (i2 < i) Then i2 := PosEx(#10, Result, i + 1);
i := i1;
If (i2 > 0) and (i2 < i) Then i := i2;
If i <= 0 Then Break;
If Result[i] = #13 Then System.Delete(Result, i + 1, 1) Else Result[i] := #13;
End;
End;
Function TRichEditStrings.GetTextStr: String;
Var TextLen: TGetTextLengthEx;
Len: Integer;
CharRange: TCharRange;
T: TGetTextEx;
Begin
TextLen.Flags := GTL_NUMCHARS or GT_USECRLF;
TextLen.CodePage := 1200;
Len := SendMessage(RichEdit.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SetLength(Result, Len);
T.cb := (Len + 1) * SizeOf(Char);
T.Flags := GT_USECRLF;
T.codepage := 1200;
T.lpDefaultChar := nil;
T.lpUsedDefChar := nil;
SendMessage(RichEdit.Handle, EM_GETTEXTEX, WPARAM(@T), LPARAM(PChar(Result)));
End;
Procedure TRichEditStrings.SetTextStr(Const Value: String);
Begin
SendTextMessage(RichEdit.Handle, WM_SETTEXT, 0, AdjustInternalLineBreaks(Value));
End;
procedure TRichEditStrings.Put(Index: Integer; const S: string);
var
Selection: TCharRange;
begin
if Index >= 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
if Selection.cpMin <> -1 then
begin
Selection.cpMax := Selection.cpMin +
SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
SendStructMessage(RichEdit.Handle, EM_EXSETSEL, 0, Selection);
SendTextMessage(RichEdit.Handle, EM_REPLACESEL, 0, AdjustInternalLineBreaks(S));
end;
end;
end;
procedure TRichEditStrings.Insert(Index: Integer; const S: string);
var
L: Integer;
Selection: TCharRange;
Str: string;
Fmt: Boolean;
begin
if Index >= 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
Fmt := Selection.cpMin < 0;
if Selection.cpMin < 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index - 1, 0);
L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
if (L = 0) or (Selection.cpMin < 0) then Exit;
Inc(Selection.cpMin, L);
end;
Selection.cpMax := Selection.cpMin;
SendStructMessage(RichEdit.Handle, EM_EXSETSEL, 0, Selection);
Str := AdjustInternalLineBreaks(S);
if Fmt then System.Insert(#13, Str, 1) else System.Insert(#13, Str, Length(Str) + 1);
SendTextMessage(RichEdit.Handle, EM_REPLACESEL, 0, Str);
end;
end; |
|
Wenn also jemand hier noch verbesserungs Potential sieht, dann möge er jetzt sprechen oder für immer schweigen.
[edit 02.01. 09:15]
'nen Fehler behoben und Testprojekte überarbeitet |
| [ An diesen Beitrag wurden eine oder mehrere Dateien angehängt. Zum Herunterladen bitte anmelden. ] |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 02.02.2010, 09:17, insgesamt 3-mal bearbeitet. |
 |
|
|
|
| |
| Hazebukelar |
#19| Verfasst am: 04.02.2010, 11:02 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
Mitglied Alter: 45 Status: offline Beiträge: 18 angemeldet: 28.09.2009 Wohnort: Nähe Bodensee

|
Super - ich werde es nochmals testen, komme aber diese Woche nicht mehr dazu.
So viel schon vorab:
Die Suche funktioniert nun richtig, egal in welche Richtung, auch Suche nach ganzen Wörtern geht einwandfrei.
Scheint wohl doch noch an der Selektion gelegen zu haben. |
Zuletzt bearbeitet von Hazebukelar am 04.02.2010, 11:03, insgesamt 1-mal bearbeitet. |
 |
|
|
|
| |
| Hazebukelar |
#20| Verfasst am: 05.02.2010, 20:08 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
Mitglied Alter: 45 Status: offline Beiträge: 18 angemeldet: 28.09.2009 Wohnort: Nähe Bodensee

|
Hallo,
ich versuche mich gerade an der ComCtrls.pas - kriegs aber nicht hin.
Blöde Frage - für welche bzw. mit welcher Delphi Version hast die gearbeitet 2009 oder 2010?
Ich habe hier 2010. |
|
 |
|
|
|
| |
| himitsu |
#21| Verfasst am: 05.02.2010, 20:29 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
Soweit ich das gesehn hab, sollten diesbezüglich die Codes zwischen D2009 und D2010 identisch sein.
Hab grad kein Delphi mit dabei, aber bei Gelegeneit wollte ich nächste Woche eh nochmal drüberschauen, bevor ich's bei Emba hochlad.
Das Problem beim Rumspielen an den VCL-Codes ist, daß der Compiler die DCUs zum Kompilieren der Anwendungen nimmt und die PAS werden nur für Debugzwecke verwendet.
Dazu hat Delphi auch noch 2 Sätze von DCUs (mit und ohne Debuginfos).
Man muß also schon ein kleines bissl Aufwand betreiben, will man da selber etwas ändern.
[edit]
hab die Codes soeben im EDN hochgeladen. |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 06.02.2010, 09:57, insgesamt 2-mal bearbeitet. |
 |
|
|
|
| |
| himitsu |
#22| Verfasst am: 08.02.2010, 20:01 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
Nachdem ich nun bemerkt hab, daß TStrings jetzt eine .LineBreak-Eigenschaft besitzt,
durfte ich leider Vieles nochmals berarbeiten.
Nun suche ich einige Tester, welche die geänderte ComCtrls.pas in D2010 und eventuell in D2009 testen.
Freiwillige bitte melden > ich schicke diesen dann die .pas zu.
(diese hier öffentlich hochzuladen dürfte aus rechtlichen Gründen nicht möglich sein)
In einem Testprojekt hab ich die ComCtrls.pas in das Programmverzeichnis kopiert, verändert und das Programm diese nutzen lassen.
OK, selber ändern geht auch (nur für D2009 oder D2100).
Hier alle geänderten und neuen Funktionen:
Delphi-Quellcode: | zusammenfalten | markieren | 1 · · · 5 · · · · 10 · · · · 15 · · · · 20 · · · · 25 · · · · 30 · · · · 35 · · · · 40 · · · · 45 · · · · 50 · · · · 55 · · · · 60 · · · · 65 · · · · 70 · · · · 75 · · · · 80 · · · · 85 · · · · 90 · · · · 95 · · · · 100 · · · · 105 · · · · 110 · · · · 115 · · · · 120 · · · · 125 · · · · 130 · · · · 135 · · · · 140 · · · · 145 · · · · 150 · · · · 155 · · · · 160 · · · · 165 · · · · 170 · · · · 175 · · · · 180 · · · · 185 · · · · 190 · · · · 195 · · · · 200 · · · · 205 · · · · 210 · · · · 215 · · · · 220 · · · · 225 · · · · 230 · · · · 235 · 237
| Type TRichEditStrings = Class(TStrings)
...
Procedure AdjustExternalLineBreaks(Var S: String);
Function AdjustInternalLineBreaks(Const S: String): String;
Function GetTextStr: String; Override;
End;
Function TCustomRichEdit.GetSelStart: Integer;
Var CharRange: TCharRange;
Begin
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
Result := CharRange.cpMin + (Length(sLineBreak) - 1)
* SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0);
End;
Procedure TCustomRichEdit.SetSelStart(Value: Integer);
Var CharRange: TCharRange;
L, T, Tx, i: Integer;
Begin
L := SendMessage(Handle, EM_GETLINECOUNT, 0, 0);
If (L > 0) and (Value > 0) Then Begin
i := SendMessage(Handle, EM_LINEINDEX, L - 1, 0);
If i + L - 1 + SendMessage(Handle, EM_LINELENGTH, i, 0) >= Value Then Begin
Tx := (L + 1) div 2;
T := 0;
i := 0;
While (Value < i) or (i + SendMessage(Handle, EM_LINELENGTH,
i - T * (Length(sLineBreak) - 1), 0) + 1 < Value) do Begin
Inc(T, Tx);
If T < 0 Then T := 0 Else If T >= L Then T := L - 1;
i := SendMessage(Handle, EM_LINEINDEX, T, 0) + T;
If (i > Value) and (Tx > 0) Then Tx := -(Tx + 1) div 2;
If (i < Value) and (Tx < 0) Then Tx := (-Tx + 1) div 2;
End;
Dec(Value, T);
End Else Dec(Value, L);
End;
CharRange.cpMin := Value;
CharRange.cpMax := Value;
SendStructMessage(Handle, EM_EXSETSEL, 0, CharRange);
End;
Function TCustomRichEdit.GetSelLength: Integer;
Var TextLen: TGetTextLengthEx;
MaxLen: Integer;
CharRange: TCharRange;
Begin
TextLen.flags := GTL_NUMCHARS;
TextLen.codepage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Result := CharRange.cpMax - CharRange.cpMin + (SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0)
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0)) * (Length(sLineBreak) - 1);
End;
Procedure TCustomRichEdit.SetSelLength(Value: Integer);
Var i: Integer;
CharRange: TCharRange;
Begin
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
CharRange.cpMax := CharRange.cpMin + Value + (Length(sLineBreak) - 1);
i := SendMessage(Handle, EM_LINEINDEX, SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0), 0);
Repeat
Inc(i, SendMessage(Handle, EM_LINELENGTH, i, 0) + 1);
Dec(CharRange.cpMax, (Length(sLineBreak) - 1));
Until i >= CharRange.cpMax;
SendStructMessage(Handle, EM_EXSETSEL, 0, CharRange);
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
End;
Function TCustomRichEdit.GetSelText: String;
Const UseCRLF: Array[Boolean] of Integer = (0, $1);
Var TextLen: TGetTextLengthEx;
MaxLen, Len: Integer;
CharRange: TCharRange;
T: TGetTextEx;
Begin
TextLen.flags := GTL_NUMCHARS;
TextLen.codepage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Len := CharRange.cpMax - CharRange.cpMin + (SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0)
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0)) * (Length(sLineBreak) - 1);
(*TextLen.flags := GTL_NUMCHARS or {GTL_USECRLF} UseCRLF[sLineBreak = #13#10];
TextLen.codepage := 1200;
MaxLen := SendMessage(Self.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SendGetStructMessage(Handle, EM_EXGETSEL, 0, CharRange);
If CharRange.cpMax >= MaxLen Then CharRange.cpMax := MaxLen;
Result := CharRange.cpMax - CharRange.cpMin + (SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMax, 0)
- SendMessage(Handle, EM_LINEFROMCHAR, CharRange.cpMin, 0)) * (Length(sLineBreak) - 1);*)
SetLength(Result, Len);
T.cb := (Len + 1) * SizeOf(Char);
T.flags := GT_SELECTION or {GT_USECRLF} UseCRLF[sLineBreak = #13#10];
T.codepage := 1200;
T.lpDefaultChar := nil;
T.lpUsedDefChar := nil;
SendMessage(Handle, EM_GETTEXTEX, WPARAM(@T), LPARAM(PChar(Result)));
TRichEditStrings(FRichEditStrings).AdjustExternalLineBreaks(Result, True);
End;
//Procedure TCustomRichEdit.SetSelText(Const Value: String);
// Begin
// {$IF DEFINED(CLR)}
// If not Assigned(Value) Then
// SendTextMessage(Handle, EM_REPLACESEL, 0, '')
// Else
// {$IFEND}
// SendTextMessage(Handle, EM_REPLACESEL, 0,
// TRichEditStrings(FRichEditStrings).AdjustInternalLineBreaks(Value));
// End;
Procedure TRichEditStrings.AdjustExternalLineBreaks(Var S: String; isEditText: Boolean = False);
Var LB: String;
Begin
If isEditText Then LB := sLineBreak Else LB := LineBreak;
If (LB <> #13#10) and (LB <> #13) Then S := StringReplace(S, #13, LB, [rfReplaceAll]);
End;
Function TRichEditStrings.AdjustInternalLineBreaks(Const S: String): String;
Var LB: String;
i, i1, i2, i3, L: Integer;
Begin
LB := LineBreak;
Result := S;
i1 := -1;
i2 := -1;
i3 := -1;
i := 1;
If (LB = #13#10) or (LB = #10) or (LB = #13) or (LB = '') Then i3 := 0;
While True do Begin
If (i1 <> 0) and (i1 <= i) Then i1 := PosEx(#13#10, Result, i);
If (i2 <> 0) and (i2 <= i) Then i2 := PosEx(#10, Result, i);
If (i3 <> 0) and (i3 <= i) Then i3 := PosEx(LB, Result, i);
i := i1;
L := 1;
If (i2 > 0) and (i2 < i) Then Begin
i := i2;
L := 0;
End;
If (i3 > 0) and (i3 < i) Then Begin
i := i3;
L := Length(LB) - 1;
End;
If i <= 0 Then Break;
If L <> 0 Then Begin
System.Delete(Result, i + 1, L);
Result[i] := #13;
End Else If Result[i] = #13 Then Result[i] := #13;
Inc(i);
End;
End;
Function TRichEditStrings.GetTextStr: String;
Const UseCRLF: Array[Boolean] of Integer = (0, $1);
Var LB: String;
TextLen: TGetTextLengthEx;
Len: Integer;
CharRange: TCharRange;
T: TGetTextEx;
Begin
LB := LineBreak;
TextLen.flags := GTL_NUMCHARS or {GTL_USECRLF} UseCRLF[LB = #13#10];
TextLen.codepage := 1200;
Len := SendMessage(RichEdit.Handle, EM_GETTEXTLENGTHEX, LPARAM(@TextLen), 0);
SetLength(Result, Len);
T.cb := (Len + 1) * SizeOf(Char);
T.flags := {GT_USECRLF} UseCRLF[LB = #13#10];
T.codepage := 1200;
T.lpDefaultChar := nil;
T.lpUsedDefChar := nil;
SendMessage(RichEdit.Handle, EM_GETTEXTEX, WPARAM(@T), LPARAM(PChar(Result)));
AdjustExternalLineBreaks(Result);
End;
Procedure TRichEditStrings.SetTextStr(Const Value: String);
Begin
SendTextMessage(RichEdit.Handle, WM_SETTEXT, 0, AdjustInternalLineBreaks(Value));
End;
procedure TRichEditStrings.Put(Index: Integer; const S: string);
var
Selection: TCharRange;
begin
if Index >= 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
if Selection.cpMin <> -1 then
begin
Selection.cpMax := Selection.cpMin +
SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
SendStructMessage(RichEdit.Handle, EM_EXSETSEL, 0, Selection);
SendTextMessage(RichEdit.Handle, EM_REPLACESEL, 0, AdjustInternalLineBreaks(S));
end;
end;
end;
procedure TRichEditStrings.Insert(Index: Integer; const S: string);
var
L: Integer;
Selection: TCharRange;
Str: string;
Fmt: Boolean;
begin
if Index >= 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
Fmt := Selection.cpMin < 0;
if Selection.cpMin < 0 then
begin
Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index - 1, 0);
L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
if (L = 0) or (Selection.cpMin < 0) then Exit;
Inc(Selection.cpMin, L);
end;
Selection.cpMax := Selection.cpMin;
SendStructMessage(RichEdit.Handle, EM_EXSETSEL, 0, Selection);
Str := AdjustInternalLineBreaks(S);
if Fmt then System.Insert(#13, Str, 1) else System.Insert(#13, Str, Length(Str) + 1);
SendTextMessage(RichEdit.Handle, EM_REPLACESEL, 0, Str);
end;
end; |
|
SelStart, SelLength, SelText, Lines.Text, Lines.Add und Lines.Insert wurde geändert
und es sollte jetzt auch unterschieldiche Lines.LineBreak beachten. |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 08.02.2010, 22:22, insgesamt 2-mal bearbeitet. |
 |
|
|
|
| |
| toms |
#23| Verfasst am: 08.02.2010, 21:22 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
CodeLib-Manager Alter: 31 Status: offline Beiträge: 4.451 angemeldet: 10.06.2002 Delphi 6 Professional

|
Gibt es ein Test-Programm, welches testet, ob die Funktion funktioniert? |
|
 |
|
|
|
| |
| himitsu |
#24| Verfasst am: 08.02.2010, 22:21 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
| toms hat folgendes geschrieben: | Gibt es ein Test-Programm, welches testet, ob die Funktion funktioniert?  |
Die einzelnen Funktionen scheinen zu laufen, dafür gibt es auch (teilweise) Testprogramme,
aber ob das Zusammenspiel auch so funktioniert ... nja, darum wäre es schön, wenn es praktisch in "komplexeren" Programmen mal getestet würde.
Im Anhang ein Testprogram inkl. der vorkompilierten EXE, in welche die neue ComCtrls.pas einkompiliert wurde. |
| [ An diesen Beitrag wurden eine oder mehrere Dateien angehängt. Zum Herunterladen bitte anmelden. ] |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 08.02.2010, 22:23, insgesamt 1-mal bearbeitet. |
 |
|
|
|
| |
| JoWi81 |
#25| Verfasst am: 09.02.2010, 21:17 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
Mitglied Alter: 28 Status: offline Beiträge: 1 angemeldet: 08.05.2009

|
Hallo zusammen!
Erstmal so am Rande, ich bin neu hier in „Delphi-PRAXiS Forum“ bezüglich Beiträge schreiben aber schon seid längerem als Beobachter dabei! Viele der vorhandenen Beiträge haben mich schon aus der Klemme geholfen!
Nun zum eigentlichen… hab auch das gleiche Problem mit CRLF in Verbindung mit SelStart und SelLength und hatte auch schon mit „EM_LINEFROMCHAR“ dies zu korrigieren versucht, jedoch ohne Erfolg.
Das Problem lag darin, dass „EM_LINEFROMCHAR“ nicht nur beim CRLF die Anzahl der Lines lieferte, sondern auch bei WordWrap (ohne horizontalen Scrollbalken)!
Ist es nur bei mir so oder hatte ich was übersehen gehabt (mit dem Testprojekt von himitsu konnte ich es leider, wegen den vorhandenen horizontalen Scrollbalken nicht Testen)
Gruß JoWi |
|
 |
|
|
|
| |
| himitsu |
#26| Verfasst am: 09.02.2010, 22:07 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
Ich bin mir jetzt nicht ganz sicher, aber ich glaub die zusätzlichen/automatischen Umbrüche sind auch in .Text enthalten, wenn man dieses ausließt.
Wenn jetzt auch SelStart dieses genauso behandelt, dann sollte dieses kein Problem darstellen.
Oh, Danke für den Hinweis.
Da werd' ich mir wohl noch was einfallen lassen müssen.
In EM_LINEFROMCHAR, sowie .Lines, bzw. .Lines.Text sind diese Umbrüche mit enthalten, aber in .Text, .SelText, .SelStart und .SelLength leider nicht.
Hmmmm, theoretisch müßte es dieses spezielle Problem dann doch auch im älteren RichEdit (bis D2007) und auch in den Memos geben?
[edit] meine allererste Variante dürfte damit keine Probleme haben, da dort kein EM_LINEFROMCHAR und Co. verwendet wird,
aber leider sind diese Codes nicht grade "schnell", Aufgrund der vielen Stringoperationen.
[edit2]
Komisch, das Edit scheint damit kein Problem zu haben ... dort stimmt selbst bei zusätzlichen Zeilenumrüchen EM_LINEFROMCHAR und somit alles in .Lines
Aber TRichEdit hat damit schon immer Probleme ... also noch komischer, daß dieses "Problem" seit Jahren immernoch vorhanden und ungelöst ist.
Einem gewissern David Liebtag ist dieses auch schon aufgefallen, aber er hat anscheinend auch noch keine Lösung gefunden.
http://www.generation-nt.com/us/answe ... n-logical-line-help-27995072.html |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 10.02.2010, 02:42, insgesamt 5-mal bearbeitet. |
 |
|
|
|
| |
| Hazebukelar |
#27| Verfasst am: 10.02.2010, 08:53 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
Mitglied Alter: 45 Status: offline Beiträge: 18 angemeldet: 28.09.2009 Wohnort: Nähe Bodensee

|
Mal eine ganz andere Frage zu der Sache.
Wie verhält sich eigentlich Emba in so einem Fall?
Bekommt man da irgendein Feedback, wie, ob und wann das von denen gefixt wird?
Wrapper, Classhelper und Co. sind ja eigentlich nicht dazu gedacht Fehler der VCL auszubügeln.
Ich würde da eigentlich einen Patch oder mindestens eine Antwort oder Reaktion erwarten.
Der Ur-Beitrag zu diesem Thema stammt ja von mir, und wenn ich das nun seit über zwei Wochen
verfolge und sehe wie viele Leute sich um dieses Thema bemühen, welche Ausmasse das ganze
annimmt, und wie viel Zeit da verblasen wird könnte der Urheber (Emba) auch mal ran.
Oder sehe ich das falsch? |
|
 |
|
|
|
| |
| himitsu |
#28| Verfasst am: 10.02.2010, 09:27 Titel: Re: Fehlerhafte CRLF<>CR-Umsetzung im RichEdit (D2009+ |
 |
 |
 |
|
sehr aktives Mitglied Alter: 30 Status: offline Beiträge: 13.853 angemeldet: 11.10.2003 Wohnort: Elbflorenz Delphi 2010 Professional

|
nja, gehört hab ich von denen nichts, aber was die gemacht haben:
- anfangs meinen Beitrag als Duplicat markiert
- und dann "heimlich" diese Markierung wieder weggemacht
Wenn ich mal mehr Zeit hab, um über ein Thema etwas mehr nachzudenken,
dann wende ich mich wieder meinem "VCL-Recompiler" zu.
- da könnte man dann diese Änderung selber einbauen und die VCL leicht neu kompilieren lassen
- schlimm ist immer mal wieder, daß Units mit falschen Optionen kompiliert wurden
> z.B. sind/waren (weiß es aktuell nicht genau) in D2009 die Indy-Units alle mit Debuginfos kompiliert ... macht sich beim Debuggen besch***
PS: wenn ich keine bessere Lösung finde, dann swerde ich wohl beise Versionen einbauen
> bei WordBreak=true > mit den alten "unoptimaleren" Stringoperationen
> bei WordBreak=false > mit den aktuellen "optimierten" Codes
(wobei ich noch versuch die Stingoperationen etwas zu optimieren)
PSS: hab gestern noch bemerkt, daß leider die Verarbeitung ab 64.000 Zeilen im Edit durchdrehte
(leider die alte EM_LINEFROMCHAR verwendet, statt der neueren EM_EXLINEFROMCHAR) |
 an alle schlaflosen Programmierer ... macht ein Upgrade, denn mit neuer Technik passiert sowas nicht > http://xkcd.com/571
www.fnse.de/img.htm
Zuletzt bearbeitet von himitsu am 10.02.2010, 09:34, insgesamt 3-mal bearbeitet. |
 |
|
|
|
 |
|
 |
| |
|
|
| |
 
|
|
| |
|
Du darfst keine Beiträge in dieses Forum schreiben. Du darfst auf Beiträge in diesem Forum nicht antworten. Du darfst Deine Beiträge in diesem Forum nicht bearbeiten. Du darfst Deine Beiträge in diesem Forum nicht löschen. Du darfst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum nicht posten. Du kannst Dateien in diesem Forum nicht herunterladen.
|
|
 |