2

行数が多すぎない場合は、WM_VSCROLLメッセージで問題ありません。RichEditに多数の行がある場合(私の場合、平均150文字で約130K行)、機能しません。 RichEdit1.Perform(WM_VSCROLL, MakeWParam(SB_THUMBPOSITION, N), 0);上にスクロール(N> 5)または必要以上にスクロールします(N <= 5)。他の方法で垂直スクロールを行うことはできますか?

Psテストには、SertacAkyuzによって作成されたこのコードを使用できます。

4

1 に答える 1

1

質問へのコメントで述べた理由により、質問にリンクされているコードをリッチエディットバージョン2.0で動作できるように適合させる方法を考えることはできません。しかし、幸いなことに、それは必要ないかもしれません。

Windows XP SP1以降の場合、リッチエディットバージョン3.0がOSに含まれています。MSDNの「リッチエディットコントロールについて」を参照してください。バージョン3.0を使用するために何もする必要はありません。バージョン2.0と3.0のクラス名は同じです。バージョン3.0の「riched20.dll」がシステムに展開されている場合、VCLはそれを使用できるようになります。

興味深いことに、に問題はありませんWM_VSCROLL。メッセージは引き続き単語サイズのスクロール位置を使用しますが、リッチエディットコントロールはそれ自体に適応します。最大65535のスクロール範囲が得られます。

の問題については、バージョン3.0のリッチエディットコントロールで、wParamEM_POSFROMCHARのaにポインターを渡すと、コントロールがそれを検出し、座標を返す代わりにパラメーターを入力します。POINTL


したがって、同じコードのバージョンをわずかに変更したサンプルを次に示します(必要に応じてエラー/特殊なケースの処理を追加してください)(WordWrapfalseに設定した場合にのみ機能します):

const
  Line = 'The SCROLLINFO structure contains scroll bar parameters...'#13#10;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  s: string;
begin
  s := '';
  for i := 1 to 130000 do
    s := s + IntToStr(i) + ' - ' + Line;
  SendMessage(RichEdit1.Handle, WM_SETTEXT, 0, LPARAM(PChar(s)));
end;

procedure VertCenterLine(RichEdit: TRichEdit; LineNum: Integer);
var
  LineIndex, MaxLineIndex: lResult;
  LinePos, MaxPos: TPoint;
  ScrollInfo: TScrollInfo;
  ScrollPos: Extended;
begin
  SendMessage(RichEdit.Handle, EM_SETSEL, 0, 0);
  SendMessage(RichEdit.Handle, winapi.messages.EM_SCROLLCARET, 0, 0);
  RichEdit.SetFocus;

  LineIndex := SendMessage(RichEdit.Handle, EM_LINEINDEX, LineNum, 0);
  MaxLineIndex := SendMessage(RichEdit.Handle, EM_LINEINDEX,
      RichEdit.Lines.Count, 0);   // to account for possible line feed at end
  if MaxLineIndex = -1 then
    MaxLineIndex := SendMessage(RichEdit.Handle, EM_LINEINDEX,
        RichEdit.Lines.Count - 1, 0);

  SendMessage(RichEdit.Handle, EM_POSFROMCHAR, WPARAM(@LinePos), LineIndex);
  SendMessage(RichEdit.Handle, EM_POSFROMCHAR, WPARAM(@MaxPos), MaxLineIndex);

  ScrollInfo.cbSize := SizeOf(ScrollInfo);
  ScrollInfo.fMask := SIF_RANGE;
  GetScrollInfo(RichEdit.Handle, SB_VERT, ScrollInfo);

  ScrollPos := (LinePos.y - RichEdit.ClientHeight / 2) / MaxPos.y;
  ScrollPos := ScrollPos * (ScrollInfo.nMax - ScrollInfo.nMin);
  SendMessage(RichEdit.Handle, WM_VSCROLL,
                            MakeWParam(SB_THUMBPOSITION, Round(ScrollPos)), 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  VertCenterLine(RichEdit1, 110000);
end;
于 2012-06-04T19:55:44.413 に答える