想实现ReadBook那样的平滑滚动,听说现在一般的做法是把文字变成图片,然后输出到一个image上,再滚动,但是这样很浪费资源,而且改变窗口大小时,窗口闪的厉害。其实大家可以做一下这个实验
如果你的鼠标有滚轮的话,打开一个记事本,多输入些文字,让右边有滚动条,然后按下鼠标中键,怎样?效果很棒吧?而且滚动条还会自动下拉。
怎样模拟这个过程呢?请高手指教。
我查到了一个函数,应该有用:ScrollWindow,还有一个ScrollWindowEx;还请大家讨论一下;
如果你的鼠标有滚轮的话,打开一个记事本,多输入些文字,让右边有滚动条,然后按下鼠标中键,怎样?效果很棒吧?而且滚动条还会自动下拉。
怎样模拟这个过程呢?请高手指教。
我查到了一个函数,应该有用:ScrollWindow,还有一个ScrollWindowEx;还请大家讨论一下;
ScrollWindow(RichEdit.handle,0,-1,)就行了,不过会有一些问题。大家作做就知道了!
var DrawInfo: TGridDrawInfo);
var
ScrollArea: TRect;
ScrollFlags: Integer;
begin
with DrawInfo do
begin
ScrollFlags := SW_INVALIDATE;
if not DefaultDrawing then
ScrollFlags := ScrollFlags or SW_ERASE;
{ Scroll the area }
if DY = 0 then
begin
{ Scroll both the column titles and data area at the same time }
if not UseRightToLeftAlignment then
ScrollArea := Rect(Horz.FixedBoundary, 0, Horz.GridExtent, Vert.GridExtent)
else
begin
ScrollArea := Rect(ClientWidth - Horz.GridExtent, 0, ClientWidth - Horz.FixedBoundary, Vert.GridExtent);
DX := -DX;
end;
ScrollWindowEx(Handle, DX, 0, @ScrollArea, @ScrollArea, 0, nil, ScrollFlags);
end
else if DX = 0 then
begin
{ Scroll both the row titles and data area at the same time }
ScrollArea := Rect(0, Vert.FixedBoundary, Horz.GridExtent, Vert.GridExtent);
ScrollWindowEx(Handle, 0, DY, @ScrollArea, @ScrollArea, 0, nil, ScrollFlags);
end
else
begin
{ Scroll titles and data area separately }
{ Column titles }
ScrollArea := Rect(Horz.FixedBoundary, 0, Horz.GridExtent, Vert.FixedBoundary);
ScrollWindowEx(Handle, DX, 0, @ScrollArea, @ScrollArea, 0, nil, ScrollFlags);
{ Row titles }
ScrollArea := Rect(0, Vert.FixedBoundary, Horz.FixedBoundary, Vert.GridExtent);
ScrollWindowEx(Handle, 0, DY, @ScrollArea, @ScrollArea, 0, nil, ScrollFlags);
{ Data area }
ScrollArea := Rect(Horz.FixedBoundary, Vert.FixedBoundary, Horz.GridExtent,
Vert.GridExtent);
ScrollWindowEx(Handle, DX, DY, @ScrollArea, @ScrollArea, 0, nil, ScrollFlags);
end;
end;
if goRowSelect in Options then
InvalidateRect(Selection);
end;
unit uscroll;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Jpeg;type
TForm1 = class(TForm)
Image1: TImage;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
x, tt, l, h: integer;
pic: Trect;
map: Tbitmap;implementation{$R *.dfm}procedure TForm1.Timer1Timer(Sender: TObject);
begin
x := x - 1;
tt := tt - 1;
if x < -160 then
x := image1.height + 20;
tt := x + 80;
image1.Canvas.font.size := 18;
image1.Canvas.font.color := clLime;
image1.Canvas.TextOut(10,x,'OK 字 幕 移 动 演 示');
image1.Canvas.font.size:=12;
image1.Canvas.font.color:= clLime;
image1.Canvas.TextOut(20,x+50,' 字 体 变 色 效 果 演 示');
l:=image1.Canvas.textwidth(' 字 体 变 色 效 果 演 示');
h:=image1.Canvas.textheight(' 字 体 变 色 效 果 演 示');
image1.Canvas.pen.color:=clGreen;
image1.Canvas.moveto(20,h+x+50-2);
image1.Canvas.lineto(20+l,h+x+50-2);
pic.topleft.x:=30;
pic.topleft.y:=tt;
pic.bottomright.x:=pic.topleft.x+100;
pic.bottomright.y:=pic.topleft.y+80;
image1.canvas.stretchdraw(pic,map);
image1.Canvas.pen.color:=clBlack;
image1.Canvas.moveto(0,pic.topleft.y+80);
image1.Canvas.lineto(pic.topleft.x+100,pic.topleft.y+80);
end;
{ 以 下 设 置 动 画 初 值}
procedure TForm1.FormCreate(Sender: TObject);
begin
timer1.enabled:=true;
timer1.Interval:=25;
x:=image1.height+20;
tt:=x+80;
form1.repaint;
image1.Canvas.brush.color:=clBlack;
pic:=Rect(0,0,image1.width,image1.height);
image1.Canvas.FillRect(pic);
pic:=Rect(-1,-1,1,1);
map:=Tbitmap.create;
map.loadfromfile(ExtractFilePath(Application.ExeName) + 'imgs.bmp');
image1.canvas.stretchdraw(pic,map);
end;end.
SendMessage(Richedit1.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
ScrollWindow只是滚动画面,不会帮你刷新控件,除非控件是你自己写的,用ScrollWindow来滚动大部分,再重绘剩下的一小部分。
用内存监测工具看一下。看看是不是滚轮一开始滚动,记事本的内存就增加了,当然不增加也不说明问题。可能这个视图的图片一直存在的,也就说一直有视图的备分图片存在于内存里。。
但是前面说了,大家用的都是把文字转成图片,然后用image显示,再滚动,但我不赞成这种做法,而且很明显,ReadBook用的不是那种方法! 人家说ReadBook用的是DirectX。 但我发现用ScrollWindow函数可以让RichEdit滚动,而且非常平滑,但是用两个缺点:
1。滚动时,没办法让滚动条相应的向下自动移动;
2。会出现RichEdit的内容成为“乱码”;
第一个问题我没办法解决,第二个问题我认为是滚动时刷新的问题,于是我又发现ScrollWindowEx这个函数,查找帮助发现他好象可以指定刷新区域。 但这纯粹是个人瞎猜,所以想请高手给指点!