5

Delphi 7EM_SETTEXTMODEのコントロールで使用しようとしています。RichEdit

新しいプロジェクトを作成し、TRichEditコントロールとTButtonコントロールを追加して、次のコードをボタンのクリック ハンドラーに追加するだけです。

  SendMessage(RichEdit1.Handle, WM_SETTEXT, 0, LPARAM(PChar('')));
  Button1.Caption := IntToStr(SendMessage(RichEdit1.Handle, EM_GETTEXTMODE, 0, 0));
  Button1.Caption := Button1.Caption + ' ' + IntToStr(SendMessage(RichEdit1.Handle, EM_SETTEXTMODE, TM_PLAINTEXT, 0));
  Button1.Caption := Button1.Caption + ' ' + IntToStr(SendMessage(RichEdit1.Handle, EM_GETTEXTMODE, 0, 0));

ボタンをクリックした後、ボタンのキャプションは に設定されます。38 0 38これは、テキスト モードがまったく変更されなかったことを意味します。38TM_RICHTEXT or TM_SINGLELEVELUNDO or TM_MULTICODEPAGESETTEXTMODE038

のテキストは、ドキュメントで提案されているように、RichEdit使用する前にクリアされます。EM_SETTEXTMODE

で異なる値を設定しようとしましEM_SETTEXTMODEたが、常にそのまま38です。

コントロールを呼び出す前にテキストが含まれていても、常に (成功)EM_SETTEXTMODEを返すことに気付きました。0RichEdit

RichEdit1.Perform代わりに使用してみましたSendMessage-違いはありません。

この問題に関するさまざまなフォーラムでいくつかのスレッドを見つけましたが、いずれのスレッドでも解決されていません。

なぜこれが機能しないのですか?

4

1 に答える 1

9

古いバージョンの Delphi は、 にある RichEdit コントロールをロードしRICHED32.DLLます。新しい Delphi バージョンがロードされますRICHED20.DLL

RICHED32.DLLあなたのような多くの問題を明らかにします。修正では、comctrls.pas がロードされるように変更されていますRICHED20.DLL。この DLL と VCL コードには互換性の問題がある可能性があるため、これでは十分ではない可能性があります。プロシージャを探しTCustomRichEdit.CreateParams()ます。LoadLibrary 呼び出しが含まれています。

あなたのコードを Delphi XE でテストしたところ、動作するので、最新の Delphi バージョンにアップグレードすることをお勧めします。

アップデート

Delphi 5 でいくつかのテストを行ったところ、2 つの機能を変更するだけで十分なようです。Comctrls.Pas をプロジェクトにコピーし、次の変更を実行します。

1) でTCustomRichEdit.CreateParams()、変更

const
  RichEditModuleName = 'RICHED32.DLL';

の中へ

const
  RichEditModuleName = 'RICHED20.DLL';

CreateSubClass(Params, 'RICHEDIT');

の中へ

CreateSubClass(Params, 'RICHEDIT20A');

2) 手順TRichEditStrings.Insert()で、変更

if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
      raise EOutOfResources.Create(sRichEditInsertError);

の中へ

if RichEdit.SelStart <> (Selection.cpMax + Length(Str) - CountLineBreaks(Str)) then
      raise EOutOfResources.Create(sRichEditInsertError);

のコードCountLineBreaks/PosEx:

function PosEx(const SubStr, S: string; Offset: Cardinal = 1): Integer;
var
 Tmp: PChar;

begin
 Result := 0;
 if (Offset > Cardinal(Length(S))) then exit;
 if Offset = 1 then
  Result := Pos(SubStr, S)
 else
  begin
   Tmp := StrPos(PChar(@S[Offset]), PChar(SubStr));
   if Tmp = nil then exit;
   Result := Cardinal(Tmp - PChar(@S[Offset])) + Offset;
  end;
end;


function CountLineBreaks(const S: string): Integer;
const
  LB = #13#10;
var
  P: Integer;
begin
  Result := 0;
  P := Pos(LB, S);
  while P <> 0 do
  begin
    Inc(Result);
    P := PosEx(LB, S, P + 2);
  end;
end;

Delphi5 でこれを行うと、正しい結果が得られます。

Delphi5

RichEdit 2.0 では CRLF ペアが CR に置き換えられるため、他の問題が発生する可能性があることに注意してください。途中で問題が発生しても、私を撃たないでください...

于 2014-02-11T20:34:25.760 に答える