Autor Téma: Podivné chování RxRichEdit  (Přečteno 288 krát)

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 3
  • Karma: 0
    • Verze Delphi: XE3
Podivné chování RxRichEdit
« kdy: 06-08-2019, 09:42:08 »
Zdravím,
řeším už několik dnů problém a bohužel nevím, jak dál. Používám léta RxRichEdit z RXLIB (poslední verze 275_u_1_0_19) kvůli tomu, že podporuje vkládání obrázků.
Uvedu jednoduchý testovací příklad:
Kód: Delphi [Vybrat]
  1. procedure TForm1.Button8Click(Sender: TObject);
  2. begin
  3.   Showmessage(R1.Lines[0]);
  4.   Showmessage(R1.Text);
  5. end;
  6.  
  7. procedure TForm1.FormCreate(Sender: TObject);
  8. begin
  9.   R1:=TRxRichEdit.Create(self);
  10.   R1.Visible:=False;
  11.   R1.Parent:=Self;
  12.   R1.Text:='POKUS';
  13. end;
  14.  

Tento kód funguje bez problémů a v obou případech Showmessage vypíše 'POKUS'.
Pokud do projektu vložím třeba GestureManager, nebo AdvStringGrid, nebo ActionMainMenuBar, tak R1.Lines[0] začne vrace vždy prázdný string. Chová se to stejně při libovolném množství řádků.
Pokud obsah R1 uložím do souboru (nebo streamu), tak tam data jsou.
Nenasměrujte mě prosím, kde by mohl být problém a proč přestane RxRichEdit fungovat?
Moc vám děkuji.

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 970
  • Karma: 27
    • Verze Delphi: XE8, Seattle
Re:Podivné chování RxRichEdit
« Odpověď #1 kdy: 06-08-2019, 11:29:30 »
Jak se zachová normální richedit?

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 3
  • Karma: 0
    • Verze Delphi: XE3
Re:Podivné chování RxRichEdit
« Odpověď #2 kdy: 06-08-2019, 12:13:20 »
RichEdit funguje bez problémů. Sice né s obrázky, ale jinak je OK.
Našel jsem, že by to mohlo dělat asi toto v RxRichEdit.pas:
Kód: Delphi [Vybrat]
  1. function TRichEditStrings.Get(Index: Integer): string;
  2. var
  3.   Text: array[0..4095] of Char;
  4.   L: Integer;
  5. begin
  6.   Word((@Text)^) := SizeOf(Text);
  7.   L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, Longint(@Text));
  8.   if (Text[L - 2] = #13) and (Text[L - 1] = #10) then Dec(L, 2)
  9.   else if (RichEditVersion >= 2) and (Text[L - 1] = #13) then Dec(L);
  10.   SetString(Result, Text, L);
  11. end;
  12.  
Netuším, proč to normálně jde a když přidám na form komponenty, tak ne.

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 796
  • Karma: 43
    • Verze Delphi: 10.3
Re:Podivné chování RxRichEdit
« Odpověď #3 kdy: 06-08-2019, 13:39:30 »
Kód: Delphi [Vybrat]
  1. function TRichEditStrings.Get(Index: Integer): string;
  2. var
  3.   Text: array[0..4095] of Char;
  4.   L: Integer;
  5. begin
  6.   Word((@Text)^) := SizeOf(Text);
  7.   L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, Longint(@Text));
  8.   if (Text[L - 2] = #13) and (Text[L - 1] = #10) then Dec(L, 2)
  9.   else if (RichEditVersion >= 2) and (Text[L - 1] = #13) then Dec(L);
  10.   SetString(Result, Text, L);
  11. end;
  12.  

Mě by tam dráždilo už jen to  Longint(@Text), protože to zavání tím, že v 64bitové aplikaci to nebude fungovat. Pevně alokovaná velikost bufferu taky vypadá podezřele, jestli tedy neexistuje nějaká dohoda, že delší text tam nikdy být nesmí. Mimochodem, co když L:=SendMessage dosadí do L hodnotu 0 nebo 1? Tak na dalším řádku Text[L-2] se leze bůh ví kam.

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 970
  • Karma: 27
    • Verze Delphi: XE8, Seattle
Re:Podivné chování RxRichEdit
« Odpověď #4 kdy: 06-08-2019, 14:09:29 »
4KB je vnitřně nastavený limit bufferu pro jeden řádek a toto omezení tuším platilo pro verzi richeditu 1, pro vyšší verze asi lze použít jakoukoliv velikost.

kvůli statickému bufferu by tam možná mohlo být na začátku ověření na velikost

Kód: Delphi [Vybrat]
  1. if SendMessage(RichEdit.Handle, EM_LINELENGTH, Index, 0) > SizeOf(Text) then Exit;
« Poslední změna: 06-08-2019, 14:18:06 od JaroB »

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 970
  • Karma: 27
    • Verze Delphi: XE8, Seattle
Re:Podivné chování RxRichEdit
« Odpověď #5 kdy: 06-08-2019, 14:54:11 »
Zkus toto (pro unicode)

Kód: Delphi [Vybrat]
  1. function TRichEditStrings.Get(Index: Integer): string;
  2. var
  3.   Text: array of Char;
  4.   L: Integer;
  5.   W: Word;
  6. begin
  7.   SetLength(Text, SizeOf(Char) * 2048);
  8.   L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Index, 0);
  9.   if L > Length(Text) then SetLength(Text, SizeOf(Char) * L);
  10.   W := Length(Text);
  11.   Text[0] := Char(W);
  12.   L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, Longint(@Text[0]));
  13.   Result := Trim(string(Text));
  14. end;
  15.  
« Poslední změna: 06-08-2019, 15:00:03 od JaroB »

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 970
  • Karma: 27
    • Verze Delphi: XE8, Seattle
Re:Podivné chování RxRichEdit
« Odpověď #6 kdy: 06-08-2019, 14:56:05 »
Ten Trim() je tam navíc, to je asi chybka

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 796
  • Karma: 43
    • Verze Delphi: 10.3
Re:Podivné chování RxRichEdit
« Odpověď #7 kdy: 06-08-2019, 15:04:05 »
Místo Longint(@Text[0]) bych fakt psal NativeInt(@Text[0]).

Offline rmaster

  • Nováček
  • *
  • Příspěvků: 3
  • Karma: 0
    • Verze Delphi: XE3
Re:Podivné chování RxRichEdit
« Odpověď #8 kdy: 06-08-2019, 15:13:45 »
Zkusil jsem to takto a zdá se, že to funguje:
Kód: Delphi [Vybrat]
  1. function TRichEditStrings.Get(Index: Integer): string;
  2. var
  3.   LineIndex, LineLength, I: Integer;
  4. begin
  5.   Result := '';
  6.   LineIndex := SendMessageW(RichEdit.Handle, EM_LINEINDEX, Index, 0);
  7.   if LineIndex >= 0 then
  8.     begin
  9.       LineLength := SendMessageW(RichEdit.Handle, EM_LINELENGTH, LineIndex, 0);
  10.       if LineLength > 0 then
  11.         begin
  12.           SetLength(Result, LineLength);
  13.           Result[1] := Widechar(LineLength);
  14.           I:= SendMessageW(RichEdit.Handle, EM_GETLINE, Index, LPARAM(PWideChar(Result)));
  15.           if I < LineLength then SetLength(Result, I);
  16.         end;
  17.     end;
  18. end;
  19.  
Prosím, vidíte tam na první pohled nějaký problém? Co případně opravit?
Díky.

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 970
  • Karma: 27
    • Verze Delphi: XE8, Seattle
Re:Podivné chování RxRichEdit
« Odpověď #9 kdy: 06-08-2019, 15:13:49 »
Hmm, takže lepší kód, který bude pracovat jak v Delphi 32 tak 64

Kód: Delphi [Vybrat]
  1. function TRichEditStrings.Get(Index: Integer): string;
  2. var
  3.   Text: array of Char;
  4.   L: Integer;
  5.   W: Word;
  6. begin
  7.   SetLength(Text, SizeOf(Char) * 4096);
  8.   L := SendMessage(RichEdit.Handle, EM_LINELENGTH, Index, 0);
  9.   if L > Length(Text) then SetLength(Text, SizeOf(Char) * L);
  10.   W := Length(Text);
  11.   Text[0] := Char(W);
  12.   L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, LongInt(@Text[0]));
  13.   if ((L - 2) >= 0) and (Text[L - 2] = #13) and (Text[L - 1] = #10) then Dec(L, 2)
  14.   else if (RichEditVersion >= 2) and ((L - 1) >= 0) and (Text[L - 1] = #13) then Dec(L);
  15.   SetString(Result, PChar(@Text[0]), L);
  16. end;
« Poslední změna: 06-08-2019, 15:17:07 od JaroB »