再讨论:图象拖动&抖动问题 (100分)

  • 主题发起人 主题发起人 majorsoft
  • 开始时间 开始时间
M

majorsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
我为了避免直接拖动Image导致的重画,我使用了ScrollBox做为它的容器,
其中一个背景image充满Scrollbox整个客户区,在ScrollBox中还有很多其他的小Image,和Tshape
现在要求在容器中拖动时,使所有的图片一起移动,相对位置不能变,并且能有象ACDSee中的拖动效果。
我实现了下,发现还是有点抖动。请大家指点。
unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, jpeg, ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
ScrollBox1: TScrollBox;
Image1: TImage;
Button1: TButton;
Button2: TButton;
Edt_x: TEdit;
Edt_y: TEdit;
Shape2: TShape;
Shape3: TShape;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button3Click(Sender: TObject);
private
originPos:Tpoint;
originScrbarPos:Tpoint;
canDrag:boolean;
public
{ Public declarations }
end;
var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
image1.Picture.LoadFromFile(ExtractFilePath(Application.ExeName)+'map.wmf');
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
originPos.X:=x;
OriginPos.Y:=y;
originScrbarPos.X:=scrollbox1.HorzScrollBar.Position;
originScrBarPos.Y:=ScrollBox1.VertScrollBar.Position;
CanDrag:=true;
edt_x.Text:=inttostr(x);
edt_y.Text:=inttostr(y);
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
MovX,MovY:integer;
begin
if canDrag then
begin
screen.Cursor:=crHandPoint;
MovX:=originPos.x-x;
MovY:=originPos.y-y;
if (originScrbarPos.X+Movx)>0 then
Scrollbox1.HorzScrollBar.Position:=originScrbarPos.X+MovX
else
Scrollbox1.HorzScrollBar.Position:=0;

if (originScrbarPos.Y+MovY)>0 then
Scrollbox1.VertScrollBar.Position:=originScrbarPos.Y+MovY
else
Scrollbox1.VertScrollBar.Position:=0;
end;
edt_x.Text:=inttostr(x);
edt_y.Text:=inttostr(y);
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
canDrag:=false;
screen.Cursor:=crDefault;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
showmessage(inttostr(scrollbox1.HorzScrollBar.Position)+':'
+inttostr(scrollbox1.VertScrollBar.Position));
end;

end.
 
用ScrollBox还是会有点抖动,
我建议的做法是用paintBox,在其旁边加上ScrollBar,然后在PaintBox的OnPaint里加代码。
例如:
procedure TForm1.FormCreate(Sender: TObject);
begin
Bmp := TBitmap.Create;
Bmp.LoadFromFile('c:/tmp.bmp');
end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
PaintBox1Paint(nil);
end;

procedure TForm1.ScrollBar2Change(Sender: TObject);
begin
PaintBox1Paint(nil);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
with PaintBox1 do
begin
Canvas.Draw(-ScrollBar1.Position,-ScrollBar2.Position,bmp);
end;
end;
bmp是一个起缓冲功能的TBitmap对象
 
当然还是要加上你原有的处理鼠标事件的过程
 
TO WFSMoon,
你这个方法可能对BMP图象有用,我现在图片是.WMF格式的,
而且scrollbox中放入了很多Image和shape
 
jobsXY说把
Scrollbox1.HorzScrollBar.Position:=originScrbarPos.X+MovX
改为:
Scrollbox1.HorzScrollBar.Position:=Scrollbox1.HorzScrollBar.Position.X+MovX
。。
之后就可以了,当图片不是很大的时候,效果和ACDSee差不多了
不过。我搞不懂呀:
为什么我用OriginScrPos.x不行,反而用
Scrollbox1.HorzScrollBar.Position可以。
我觉得要用 mousedown时的Scrollbox1.HorzScrollBar.Position即OriginScrPos.x,因为OriginScrPos.x也是那时的呀。大家讨论一下吧。

 
用paintBox
 
paintBox我怎么找不到?
在那里有下载?
 
把父一级的TWinControl控件的自动DoubleBuffer打开,保你不闪!
比如都放在Panel1里,就OnCreate时Panel1.DoubleBuffer := True;
怎么都不闪的,我用Pentium200拖图都不闪,
 
防止闪烁有两种方法:
(1)将Image放在TWinControl上,将TWinControl.DoubleBuffer :=True;
但这样一来对速度影响较大。
(2)自己做双缓冲,用一个临时Bitmap,将图像先画在临时Bitmap上,然后拷贝到你要显示的画布上。
 
多人接受答案了。
 

Similar threads

I
回复
0
查看
588
import
I
I
回复
0
查看
733
import
I
I
回复
0
查看
746
import
I
后退
顶部