独自Recordをクリップボードで出し入れしたい

解決


印刷屋  2007-06-11 09:31:38  No: 26583

はじめてクリップボード使うんですが、なかなかコンパイルが通らないので教えてください。

type
  TMyRecord = record
    AAAA   :String;
    BBBB   :Integer;
    CCCC   :String;
    DDDD   :Integer;
   end;

var
  ABCD:TMyRecord;
  MyFormat:UINT;

//クリップボード型の宣言
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  MyFormat := RegisterClipboardFormat('MYFORMAT');
end;

//コピー
procedure TfrmMain.actEditCopyExecute(Sender: TObject);
var
  DataHandle:THandle;
  Pnt:Pointer;
begin
  //メモリ確保
  DataHandle := GlobalAlloc(GHND,SizeOf(ABCD));
  //メモリのポインタ取得
  Pnt := GlobalLock(DataHandle);
  //クリップボードへの書き込み
  ClipBoard.Open;
  ClipBoard.Clear;
  ClipBoard.SetAsHandle(MyFormat,DataHandle);
  GlobalUnLock(DataHandle);
  ClipBoard.Close;
end;

//編集貼付
procedure TfrmMain.actEditPasteExecute(Sender: TObject);
var
  DataHandle:THandle;
  Pnt:Pointer;
begin
  //クリップボード読み出し
  if Clipboard.HasFormat(MyFormat) then
  begin
    ClipBoard.Open;
    DataHandle := ClipBoard.GetAsHandle(MyFormat);
    Pnt := GlobalLock(DataHandle);
    ABCD := Pnt;//←このへんがよくわかりません。
    GlobalUnlock(DataHandle);
    Clipboard.Close;
  end;
end;

おかしなところがあったら教えてもらえますか?


風来坊  2007-06-11 22:33:29  No: 26584

SizeOf(ABCD) の戻り値は常に16だし…
文字列の長さは SizeOf じゃ求められないですよ。

>  //メモリのポインタ取得
>  Pnt := GlobalLock(DataHandle);
>  //クリップボードへの書き込み
>  ClipBoard.Open;
>  ClipBoard.Clear;
>  ClipBoard.SetAsHandle(MyFormat,DataHandle);
>  GlobalUnLock(DataHandle);
>  ClipBoard.Close;
クリップボードに肝心のデータが何も書き込まれていません。
Pnt に入れてあげなきゃ…
Clipbrd.pas を読んで参考にしましょう。


orz  2007-06-12 04:56:15  No: 26585

あたしゃ、こんな感じでストリームから書き込みしとる。
TMemStreamじゃなく、TFileStream使えば、ファイルとして保存できる。

//書き
var
  mstrm: TMemoryStream;
  mHnd: THandle;
  dPtr: Pointer;
begin
  mstrm  := TMemoryStream.Create;

  //mstrmに情報書き込み

  {メモリ確保}
  mHnd := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, mstrm.Size);
  {ロック}
  dPtr := GlobalLock(mHnd);
  try
    {ストリームから書き込み}
    mstrm.Position := 0;
    mstrm.ReadBuffer(dPtr^, mstrm.Size);
  finally
    {アンロック}
    GlobalUnlock(mHnd);
  end;
  {クリップボードに貼り付け}
  ClipBoard.Open;
  try
    SetClipboardData(RegisterClipboardFormat('てきとうなフォーマット名'), mHnd);
  finally
    ClipBoard.Close;
  end;
  mstrm.Free;
end;

//読み
var
  mstrm: TMemoryStream;
  mHnd: THandle;
  dPtr: Pointer;
begin
  Result := '';
  mstrm  := TMemoryStream.Create;

  ClipBoard.Open;
  try
    {クリップボードから取得}
    mHnd := ClipBoard.GetAsHandle(RegisterClipboardFormat('てきとうなフォーマット名'));
    if mHnd > 0 then begin
      {ロック}
      dPtr := GlobalLock(mHnd);
      {ストリームに書き込み}
      mstrm.WriteBuffer(dPtr^, GlobalSize(mHnd));
      {アンロック}
      GlobalUnlock(mHnd);
    end
    else begin
      Result := 'クリップボードにデータがありません。';
    end;
  finally
    ClipBoard.Close;
  end;
  //ストリームから読み込み
end;

実コードからの一部抜粋だが、まぁそれなりに動くだろう。

ちなみに 
var
  aaa:String;

SizeOf(aaa) = 4 ≠Length(aaa)


印刷屋  2007-06-14 05:00:50  No: 26586

どうやら苦手なストリームを使わないといけないみたいですね。
先にストリームを勉強してからクリップボードに着手します。
ありがとうございました。


印刷屋  2007-06-15 08:39:51  No: 26587

おかげさまで、なんとかサンプルプログラムが思い通りに動きました。
ありがとうございました。

procedure TForm1.Button1Click(Sender: TObject);
var
  MS:TMemoryStream;
  DataHandle:THandle;
  Pnt:Pointer;
  Len:Byte;
  Inte:Integer;
begin
  MS := TMemoryStream.Create;
  try
    Len := Length(Edit1.Text) + 1;
    MS.Write(Len,SizeOf(Len));
    MS.Write(PChar(Edit1.text)^,Len);
    Inte := ComboBox1.ItemIndex;
    MS.Write(Inte,SizeOf(Integer));
    Len := Length(Edit2.Text) + 1;
    MS.Write(Len,SizeOf(Len));
    MS.Write(PChar(Edit2.text)^,Len);
    Inte := ComboBox2.ItemIndex;
    MS.Write(Inte,SizeOf(Integer));
    //
  //メモリ確保
  DataHandle := GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,MS.Size);
  //メモリのポインタ取得
  Pnt := GlobalLock(DataHandle);
  MS.Position := 0;//巻き戻し
  MS.ReadBuffer(Pnt^,MS.Size);
  finally
  MS.Free;
  end;

  //クリップボードへの書き込み
  ClipBoard.Open;
  ClipBoard.Clear;
  ClipBoard.SetAsHandle(MyFormat,DataHandle);
  GlobalUnLock(DataHandle);
  ClipBoard.Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  DataHandle:THandle;
  Pnt:Pointer;
  MS:TMemoryStream;
  Len:Byte;
  StMem:PChar;
  Inte:Integer;
begin
  //クリップボード読み出し
  if Clipboard.HasFormat(MyFormat) then
  begin
    ClipBoard.Open;
    DataHandle := ClipBoard.GetAsHandle(MyFormat);
    Pnt := GlobalLock(DataHandle);
    MS := TMemoryStream.Create;
    try
      MS.WriteBuffer(Pnt^,GlobalSize(DataHandle));
      GlobalUnLock(DataHandle);
      MS.Position := 0;

      MS.Read(Len,SizeOf(Len));
      StMem := StrAlloc(Len);
      MS.Read(StMem^,Len);
      Edit1.Text := StMem;
      MS.Read(Inte,SizeOf(Integer));
      ComboBox1.ItemIndex := Inte;

      MS.Read(Len,SizeOf(Len));
      StMem := StrAlloc(Len);
      MS.Read(StMem^,Len);
      Edit2.Text := StMem;
      MS.Read(Inte,SizeOf(Integer));
      ComboBox2.ItemIndex := Inte;
    finally
    MS.Free;
    end;

    Clipboard.Close;
  end;
end;


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加