0

I'm building a tool that sends a request besides my browser request using TIdMappedPortTCP from Indy 9.

I want to use string #$d#$A (line breaks) by writing it in memo as %0D%0A but it's not working fine, as you can see in the image.

What's the correct code I should use to make this work?

procedure TForm1.IdMappedPortTCP1Execute(AThread: TIdMappedPortThread);
var
  memo:string;
begin
  memo:= Memo1.text;
  if Combobox4.text='Back' then begin
    AThread.NetData := AThread.NetData +memo  ;
    form2.Memo1.Lines.Add(AThread.NetData);

IdMappedPortTCP request & log

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Daywalker
  • 11
  • 1
  • 3

1 Answers1

2

TIdMappedPortTCP is a multi-threaded component. The OnExecute event is triggered in the context of a worker thread. You CANNOT access your TMemo and TComboBox controls directly like you have shown. You MUST synchronize with the UI thread in order to access them safely and correctly.

Try something more like this:

uses
  ..., IdSync;

type
  TGetForm1BackMemoTextSync = class(TIdSync)
  protected
    FText: string;
    procedure DoSynchronize; override;
  public
    class function GetText: string;
  end;

  TAddToForm2MemoSync = class(TIdSync)
  protected
    FText: string;
    procedure DoSynchronize; override;
  public
    class procedure AddToMemo(const S: string);
  end;

procedure TGetForm1BackMemoTextSync.DoSynchronize;
begin
  if Form1.ComboBox4.Text = 'Back' then
    FText := Form1.Memo1.Text;
end;

class function TGetForm1BackMemoTextSync.GetText: string;
begin
  with Create do
  try
    Synchronize;
    Result := FText;
  finally
    Free;
  end;
end;

procedure TAddToForm2MemoSync.DoSynchronize;
begin
  Form2.Memo1.Lines.Add(FText);
end;

class procedure TAddToForm2MemoSync.AddToMemo(const S: string);
begin
  with Create do
  try  
    FText := S;
    Synchronize;
  finally
    Free;
  end;
end;

//...

procedure TForm1.IdMappedPortTCP1Execute(AThread: TIdMappedPortThread);
var
  memo: string;
begin
  memo := TGetMemoBackTextSync.GetText;
  if memo <> '' then begin
    AThread.NetData := AThread.NetData + memo;
    TAddToForm2MemoSync.AddToMemo(AThread.NetData);
  //...
end;

With that said, you should not be putting %0D%0A in the Memo text at all. Each line in a Memo is already separated by a line break. Reading the Memo.Text property returns a string where each line is separated by the value of the RTL's sLineBreak constant (which is defined as #13#10 on Windows). So just omit %0D%0A from your text and type in natural line breaks instead, and let the RTL handle the rest for you.

If you absolutely must keep %0D%0A in the text, you will have to strip off the native line breaks and then convert %0D%0A into native line breaks manually, eg:

procedure TGetForm1BackMemoTextSync.DoSynchronize;
begin
  if Form1.ComboBox4.Text = 'Back' then
  begin
    FText := StringReplace(Form1.Memo1.Text, sLineBreak, '', [rfReplaceAll]);
    FText := StringReplace(FText, '%0D%0A', #13#10, [rfReplaceAll]);
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770