[Delphi] [VCL] [FMX] クリップボードからブラウザでコピーしたHTMLフォーマットのテキストを取得する

ブラウザでコピーしたテキストデータを普通に取り出そうとすると，テキスト部分だけしか取得できません。
HTMLフォーマットで取り出すと処理が楽になることがあったので，書いてみました。

# VCLの実装
以下のようなコードになります。

```pascal:uVCLClipboardUtil.pas
unit uVCLClipboardUtil;

interface

function HTMLGetFromClipboard: string; // ブラウザからコピーしたソースを取得

implementation

uses
  Winapi.Windows,
  Vcl.Clipbrd;

function HTMLGetFromClipboard: string; // ブラウザからコピーしたUTF8 HTMLソースを取得
var
  Data: THandle;
  CF_HTML:UINT;
begin
  Clipboard.Open;
  CF_HTML:=RegisterClipboardFormat('HTML Format');
  Data := GetClipboardData(CF_HTML);
  try
    if Data <> 0 then begin
      Result := UTF8ToString((PAnsiChar(GlobalLock(Data))));
    end else begin
      Result := '';
    end;
  finally
    if Data <> 0 then begin
      GlobalUnlock(Data);
    end;
    Clipboard.Close;
  end;
end;
```
**Form1(TForm1)** に **Button1(TButton)ボタン** と **Memo1(TMemo)** を配置して， **uVCLClipboardUtil.pas** を **uses** し， **Button1Click(Sender: TObject)** イベントに以下のように書いて実行します。

```pascal:Unit1.pas
uses
  uVCLClipboardUtil;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Text:=HTMLGetFromClipboard;
end;
```
ウェブブラウザで，表示されたページを選択して，クリップボードにコピーした後， **Button1** をクリックすると，クリップボードにコピーされたHTMLフォーマットのテキストが貼り付けられます。

# FMXの実装
以下のようなコードになります。

```pascal:uFMXClipboardUtil.pas
unit uFMXClipboardUtil;

interface

function HTMLGetFromClipboard: string; // ブラウザからコピーしたソースを取得

implementation

uses
  System.Classes, System.SysUtils,
  FMX.Platform, FMX.Clipboard;

function HTMLGetFromClipboard:string; // ブラウザからコピーしたUTF8 HTMLソースを取得
const
  HTMLFormat='HTML Format';
var
  Clipboard: IFMXExtendedClipboardService;
  stream:TMemoryStream;
begin
  Result:='';
  stream:=TMemoryStream.Create;
  try
    if TPlatformServices.Current.SupportsPlatformService(IFMXExtendedClipboardService, Clipboard) then begin
      Clipboard.RegisterCustomFormat(HTMLFormat);
      Clipboard.GetCustomFormat(HTMLFormat,stream);
      Clipboard.UnRegisterCustomFormat(HTMLFormat);
      var st:TStringList;
      st:=TStringList.Create;
      st.LoadFromStream(stream,TEncoding.UTF8);
      Result:=st.Text;
      st.Free;
    end;
  finally
    FreeAndNil(stream);
  end;
end;

end.
```
**Form1(TForm1)** に **Button1(TButton)ボタン** と **Memo1(TMemo)** を配置して， **uVCLClipboardUtil.pas** を **uses** し， **Button1Click(Sender: TObject)** イベントに以下のように書いて実行します。

```pascal:Unit1.pas
unit uFMXClipboardUtil;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Text:=HTMLGetFromClipboard;
end;
```
ウェブブラウザで，表示されたページを選択して，クリップボードにコピーした後，Button1をクリックすると，クリップボードにコピーされたHTMLフォーマットのテキストが貼り付けられます。

# HTMLフォーマット
Memo1にコピーされたHTMLフォーマットの構造は以下の通りです。

#### ヘッダ
|ヘッダ               | 説明                          |
|:--------------------|:------------------------------|
|Version: | クリップボードのバージョン番号です。2024/10/13現在 Edge, Chrome, Firefoxでは0.9が入ります。|
|StartHTML:| クリップボードの先頭からコンテキストの先頭までのオフセット(バイト単位) コンテキストがない場合は -1|
|EndHTML:  | クリップボードの先頭からコンテキストの末尾までのオフセット(バイト単位) コンテキストがない場合は -1|
|StartFragment:| オプション クリップボードの先頭からフラグメントの先頭までのオフセット(バイト単位)|
|EndFragment:|   オプション クリップボードの先頭から選択の終了までのオフセット(バイト単位)|
|SourceURL:| 取得したHTMLのURL|

オフセットの桁数はブラウザにより違うようです。

####  その他のタグ
\<body>の中に書かれます。
|タグ(コメント)                 | 説明                          |
|:--------------------|:------------------------------|
|\<!--StartFragment-->| コピーの際に選択されたHTMLの先頭|
|\<!--EndFragment-->  | コピーの際に選択されたHTMLの最後|

詳細は https://learn.microsoft.com/ja-jp/windows/win32/dataxchg/html-clipboard-format をご覧ください。

なお，クリップボードにコピーされるHTMLフォーマットテキストは，ブラウザがダウンロードしたHTMLファイルを加工したもので，すべてを選択しても，ヘッダ部分はコピーされていません。
必要に応じて，SourceURLから取得します。

# 謝辞
FMXのクリップボードの使い方は，@pik (Jun HOSOKAWA)様の
https://qiita.com/pik/items/fe7b9ef9ca01a1fbcdc1
を参考にしました。ありがとうございました。

問題などありましたらご指摘いただけるとありがたいです。