[Delphi] Vcl TMemoの1行の文字制限について

本投稿は [Delphi Advent Calendar 2023 #2](https://qiita.com/advent-calendar/2023/delphi) の記事です。
## はじめに
Windowsでテキスト加工をしてやり取りするときTMemoを使うことがあります。
あるとき，DelphiのMemoからコピーできるのに，Memoにコピーをすると一行の文字数が少なくなることがありました。そこで，Delphiとテキストエディタを使って文字列のやり取りをして，一行の文字数の制限がどのようになっているかを調べてみました。

## 実験1 TMemo から テキストエディタ へのコピー
ネットで調べてみるとVCLのTMemoの一行の最大は1024文字だという記述がありましたので，とりあえず1024文字+αで試してみることにしました。Windows VCLフォームのアプリケーションを作成し，TButtonを2つ，TMemoを2つ，Tlabelを1つ配置して以下のようなコードを書きました。
Button1とButton2にそれぞれMemo1に文字を追加するコード，Memoの一行目の文字を数えるコードを書いています。

```Unit1.pas
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  s0,s1:string;
  i:integer;
begin
  s0:='0123456789ABCDEF'; // 16文字
  s1:='';
  for i:=1 to 64 do begin // 64回加えて1024文字
    s1:=s1+s0;
  end;
  s1:=s1+'++++++++++'; // 1024文字以降は”+”を追加
  Memo1.Clear;
  Memo1.Lines.Add(s1);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  s:string;
begin
  s:=Memo1.Lines[0]; // Memo1の一行目を取り出す
  Label1.Caption:=IntToStr(Length(s)); // 文字列の長さをLabel1に表示
end;

end.
```
実行してButton1をクリックしてMemo1に文字を入力して，表示された文字をCtrl+Aで全て選択してCtrl+Cでコピーし，テキストエディタにペーストすると，出力された文字列が一列で表示されます。
文字数を数えると，**1034** 文字 確かに全ての文字が一列で渡されています。 

では，Button2をクリックしてMemo1で一行が何文字になっているのか調べてみましょう。
**94** 文字だといいます。あれれ，，
どうやら，Memo1に1列で表示されている文字数が返されているようです。

## 実験2 TMemoをフォームのサイズに合わせてリサイズしてみる
オブジェクトインスペクタで，Memo1の`Anchers`を開いて`akRight`と`akTop`を`True`にして，上記のプログラムを実行します。
Button1をクリックして，Memo1に文字列を表示させ，フォームのサイズを変えてButton2をクリックすると，実験1とは違った数がLabel1に表示されることが分かります。
このことから，**TMemoでは，表示された文字が保持されているが，画面表示を反映して1行の文字列が取り出される**ことが分かります。

## 実験3 TMemoにスクロールバーをつける
フォームに`TCheckBox`を追加し，追加したCheckBox1のClickイベントに以下のコードを追加します。
```Unit1.pas 
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  if Checkbox1.Checked then begin
    Memo1.ScrollBars:=ssboth;
  end else begin
    Memo1.ScrollBars:=ssNone;
  end;
end;
```
プログラムを実行して，Button1をクリックして文字列を追加し，Checkbox1をクリックしてMemo1にスクロールバーを表示させてから，Button2をクリックすると **1024** がLabel1に表示されました。
テキストエディタにペーストしておいた文字列をMemo1にコピーしてButton2をクリックしても1024が表示されます。
このことから，**Memo1から取り出せる1行の文字の最大値は1024文字である**ということが分かりました。
Delphiはユニコードに対応していますので，全角文字を使っても同様の結果となります。一行の制限はバイト数ではなく文字数です。(もしかすると，これはWindows側の問題で，Delphiの問題ではないかもしれません。)

## まとめ
これらの実験から以下のことが分かりました。
- Delphi VCLアプリの`TMemo`からテキストエディタなどの他のアプリケーションへのコピー＆ペーストでは，`TMemo`に代入された文字列がそのままペースト可能です。文字数の制限は特に意識する必要は無いようです。
- テキストエディタなどの他のアプリケーションからDelphi VCLアプリの`TMemo`にテキストをペーストする場合1024文字の制限があります。その時`TMemo`には最低でも横スクロールバーをつけておかねばならず，横スクロールバーがない場合は，表示されたままの文字がその行の一列として扱われます。

ちなみに，TMemoの全行の文字数の制限は`MaxLength`で指定できます。
詳細はDocwikiの [Vcl.StdCtrls.TCustomEdit.MaxLength](https://docwiki.embarcadero.com/Libraries/Athens/ja/Vcl.StdCtrls.TCustomEdit.MaxLength) から確認していただけます。
この情報が皆様のお役に立てば幸いです。間違いがございましたらお知らせください。