RichEdit和WM_VSCROLL消息

时间:2012-06-04 18:03:06

标签: delphi windows-7 delphi-xe2 richedit

当行数不是太大时,WM_VSCROLL消息没有问题。当RichEdit有大量的行(在我的情况下~130K行,平均150个字符)它不起作用。 RichEdit1.Perform(WM_VSCROLL, MakeWParam(SB_THUMBPOSITION, N), 0);滚动到顶部(N> 5)或更多(N <= 5)。我可以用其他方式进行垂直滚动吗?

P.S。 对于测试,可以使用Sertac Akyuz编写的this code

1 个答案:

答案 0 :(得分:1)

我想不出一种方法来调整问题中链接的代码,以便能够使用富编辑版本2.0,因为我在问题的评论中提到了这一点。但幸运的是,它可能没有必要..

对于Windows XP SP1及更高版本,操作系统附带了丰富的编辑版本3.0。请参阅MSDN上的“About Rich Edit Controls”。您无需执行任何操作即可使用3.0版,版本2.0和3.0的类名相同。如果系统上部署了版本3.0“riched20.dll”,则VCL可以使用它。

有趣的是WM_VSCROLL没有问题。该消息仍然使用单词大小的滚动位置,但丰富的编辑控件适应自己:您获得最多65535的滚动范围。

关于EM_POSFROMCHAR的问题,使用版本3.0丰富的编辑控件,如果您将指针传递给wParam中的POINTL,控件会检测到它而不是返回坐标,它会填充参数。


所以,这里有一个相同代码略有修改版本的示例(请在适当时添加错误/特殊情况处理)(仅适用于WordWrap设置为false):

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;