想实现ReadBook那样的平滑滚动,听说现在一般的做法是把文字变成图片,然后输出到一个image上,再滚动,但是这样很浪费资源,而且改变窗口大小时,窗口闪的厉害。其实大家可以做一下这个实验
如果你的鼠标有滚轮的话,打开一个记事本,多输入些文字,让右边有滚动条,然后按下鼠标中键,怎样?效果很棒吧?而且滚动条还会自动下拉。
怎样模拟这个过程呢?请高手指教。
我查到了一个函数,应该有用:ScrollWindow,还有一个ScrollWindowEx;还请大家讨论一下;

解决方案 »

  1.   

    哦,忘了说了,比如让一个RichEdit滚动,则用一个计时器,写上
    ScrollWindow(RichEdit.handle,0,-1,)就行了,不过会有一些问题。大家作做就知道了!
      

  2.   

    给你看段代码,也许对你有帮助。procedure TCustomGrid.ScrollDataInfo(DX, DY: Integer;
      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;
      

  3.   

    大哥,给点注释好不?这个东西怎么用?TGridDrawInfo是什么类型,如果想用他来平滑滚动一个RichEdit的话怎么写?解决了立刻给你分!^_^
      

  4.   

    给你一段代码,可以实现:
    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.
      

  5.   

    如果要滚动Richedit1的话,应该这样:
    SendMessage(Richedit1.Handle, WM_VSCROLL, SB_LINEDOWN, 0);
    ScrollWindow只是滚动画面,不会帮你刷新控件,除非控件是你自己写的,用ScrollWindow来滚动大部分,再重绘剩下的一小部分。
      

  6.   

    不是还有个ScrollWindowEx吗?这个可以不??
      

  7.   

    我高度怀疑 这个函数!!!他的实质还是内存贴图。VC++中的CScroolView类就是如此.只不过封装起来了不用贴图,不开辟内存空间的话,难道贴字?把那么多的文字重新输出???这才慢的厉害呢
    用内存监测工具看一下。看看是不是滚轮一开始滚动,记事本的内存就增加了,当然不增加也不说明问题。可能这个视图的图片一直存在的,也就说一直有视图的备分图片存在于内存里。。
      

  8.   

    你到底要滚动什么东西?说清楚点,是滚动RichEdit吗?
      

  9.   

    就是想做一个阅读器,像ReadBook那样!
    但是前面说了,大家用的都是把文字转成图片,然后用image显示,再滚动,但我不赞成这种做法,而且很明显,ReadBook用的不是那种方法! 人家说ReadBook用的是DirectX。  但我发现用ScrollWindow函数可以让RichEdit滚动,而且非常平滑,但是用两个缺点:
    1。滚动时,没办法让滚动条相应的向下自动移动;
    2。会出现RichEdit的内容成为“乱码”;
    第一个问题我没办法解决,第二个问题我认为是滚动时刷新的问题,于是我又发现ScrollWindowEx这个函数,查找帮助发现他好象可以指定刷新区域。 但这纯粹是个人瞎猜,所以想请高手给指点!