RitchEdit内容の一部移動をクリップボードを壊さないで行う

解決


賭博アルプス王ハイジ  2005-05-15 03:19:05  No: 14793

今回もTRichEditの質問です。

「RichEdit1の内容の一部を、RichEdit2の途中に挿入する」
というとき、一文字づつテキスト内容と書式を調べては移動して設定すると遅くて使い物になりませんので、今はクリップボードを介して行っています。

しかし、これではもともとクリップボードに入っている内容が壊れてしまいます。
なんとかクリップボードの内容に影響を与えないようにしたいのです。(それが画像だろうが文字だろうが)

考えられる方法として
・クリップボードを介さないで、書式付テキスト情報を移動
とか
・クリップボードの内容を一時的にメモリイメージごとバックアップしてあとで戻す
などということができないか探しています。

あるいは、まったく違う方法でもいいのですが、良い解決方法があれば教えていただければ助かります。


Fusa  2005-05-15 10:35:09  No: 14794

こんなのでどうでしょうか?

uses
  RichEdit;を追加

type
  TEditStreamMode=(esmWrite,esmRead);

  TForm1 = class(TForm)
..
  public
    FStreamRec: TEditStream; {←構造体です}
    FStream: TMemoryStream;
  end;
..

implementation

function EditStreamCallBack(dwCookie: Longint; pbBuff: PByte;
    cb: Longint; var pcb: Longint): Longint; stdcall; forward;
{forward 宣言}

//生成と破棄
procedure TForm1.FormCreate(Sender: TObject);
begin
  FStream := TMemoryStream.Create;
  FStreamRec.pfnCallback := @EditStreamCallBack;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FStream.Free;
end;

//RichTextメモり確保用コールバック関数
function EditStreamCallBack(dwCookie: Longint; pbBuff: PByte;
    cb: Longint; var pcb: Longint): Longint; stdcall;
begin
  try
    case TEditStreamMode(dwCookie) of
      esmWrite: pcb:= Form1.FStream.Write(pbBuff^,cb);
      esmRead : pcb:= Form1.FStream.Read(pbBuff^,cb);

    end;
    Result:= 0;
  except
    Result:= 1;

  end;
end;

//コピーボタン
procedure TForm1.Button13Click(Sender: TObject);
begin
  FStream.Clear;
  FStreamRec.dwCookie := Longint(esmWrite);
  RichEdit1.Perform( EM_STREAMOUT,SF_RTF or SFF_SELECTION,Longint(@FStreamRec));
end;

//ペーストボタン
procedure TForm1.Button14Click(Sender: TObject);
begin
  FStream.Position:=0;
  FStreamRec.dwCookie := Integer(esmRead);
  RichEdit1.Perform( EM_STREAMIN,SF_RTF or SFF_SELECTION,Longint(@FStreamRec));
end;


賭博アルプス王ハイジ  2005-05-15 11:12:19  No: 14795

Fusaさん、ありがとうございます。

実は本当は、C++Builderを使っていて、ここのDelphiの内容をいつも参考にしていたのですが、今回はコールバック関数とかもあるのでBCB用にするのにちょっと調べながらやってみます。

さっそくMSDNヘルプで教えていただいた
  EM_STREAMIN
  EditStreamCallback
あたりを見ていますが、なるほど、たしかにかなりよさげな感じです。

そっか〜、EDITSTREAMという機能があるのか〜〜

実際にうまく動作できたとこで解決チェックとさせていただきますので、一日ほどお時間をいただきます。


賭博アルプス王ハイジ  2005-05-15 13:17:19  No: 14796

ちょっとがんばって、教えていただいたコードをBCB上でうまく動作させることに成功しました。解決とさせていただきます。
大変たすかりました。

ちなみにBCBだと以下のようになりました。(ここにBCBのコードを書くことは恐縮ですが・・・・)

<<ヘッダ>>

enum TEditStreamMode { esmWrite , esmRead };
DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie,LPBYTE pbBuff, LONG cb, LONG *pcb);

class TForm1 : public TForm
{
  ★省略★
public:    // ユーザー宣言
    TEditStream FStreamRec; //{←構造体です}
    TMemoryStream *FStream;
};

<<本体>>

//RichTextメモり確保用コールバック関数
DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie,LPBYTE pbBuff, LONG cb, LONG *pcb)
{
  try  {
    switch( TEditStreamMode(dwCookie) )
    {
          case esmWrite:
                  *pcb = (LONG)Form1->FStream->Write(pbBuff,cb);
            break;
          case esmRead :
                  *pcb = (LONG)Form1->FStream->Read(pbBuff,cb);
            break;
    }
        }
  catch ( ... )
        {
    return 1; //失敗nonzero
        }
  return 0; //成功zero

}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  FStream = new TMemoryStream();
        FStreamRec.pfnCallback = EditStreamCallback;
}

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
  delete FStream;
}

//一発でRichEdit1からRichEdit2へコピペ
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  FStream->Clear();
  FStreamRec.dwCookie = (DWORD_PTR)esmWrite;
  RichEdit1->Perform( EM_STREAMOUT , SF_RTF | SFF_SELECTION , (LPARAM)&FStreamRec );

  FStream->Position = 0 ;
  FStreamRec.dwCookie = (DWORD_PTR)esmRead;
  RichEdit2->Perform( EM_STREAMIN , SF_RTF | SFF_SELECTION , (LPARAM)&FStreamRec );
}

動くには動くんですが、一カ所不安なところがあります。
コールバック関数のところで
*pcb = (LONG)Form1->FStream->Write(pbBuff,cb);
*pcb = (LONG)Form1->FStream->Read(pbBuff,cb);
で、pcbポインタの指すlong値を、TMemoryStreamのWriteやReadメソッドの戻り値に置き換えていますが、ちゃんとDelphiのコードと同じ意味のことをしているのでしょうか?ObjectPascalを不正確に覚えているので、自身がなくて・・・・・。すみません。


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

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






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