今回もTRichEditの質問です。
「RichEdit1の内容の一部を、RichEdit2の途中に挿入する」
というとき、一文字づつテキスト内容と書式を調べては移動して設定すると遅くて使い物になりませんので、今はクリップボードを介して行っています。
しかし、これではもともとクリップボードに入っている内容が壊れてしまいます。
なんとかクリップボードの内容に影響を与えないようにしたいのです。(それが画像だろうが文字だろうが)
考えられる方法として
・クリップボードを介さないで、書式付テキスト情報を移動
とか
・クリップボードの内容を一時的にメモリイメージごとバックアップしてあとで戻す
などということができないか探しています。
あるいは、まったく違う方法でもいいのですが、良い解決方法があれば教えていただければ助かります。
こんなのでどうでしょうか?
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;
Fusaさん、ありがとうございます。
実は本当は、C++Builderを使っていて、ここのDelphiの内容をいつも参考にしていたのですが、今回はコールバック関数とかもあるのでBCB用にするのにちょっと調べながらやってみます。
さっそくMSDNヘルプで教えていただいた
EM_STREAMIN
EditStreamCallback
あたりを見ていますが、なるほど、たしかにかなりよさげな感じです。
そっか〜、EDITSTREAMという機能があるのか〜〜
実際にうまく動作できたとこで解決チェックとさせていただきますので、一日ほどお時間をいただきます。
ちょっとがんばって、教えていただいたコードを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を不正確に覚えているので、自身がなくて・・・・・。すみません。
ツイート | ![]() |