📄 trackdraw.pas
字号:
unit TrackDraw;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TDrawState=(dsClear, dsNew);
{
TrackDraw的原理是:在图形数据未改变之前,先与掉(用与模式绘制一次),然后
在图形数据改变后,再绘制一次。这样以来流程就可以理解为:设置绘图模式为与模式->
绘图->改变数据->设置绘图模式为实模式->绘图。
图形数据的改变可能来自于其它方法对属性数据的修改,也可能来源于TTrackDraw内
部的某些方法对属性数据的修改,无论是什么方法改变了图形的属性数据,都将使图形对
象向视图管理者发送消息,要求同步图形的显示。图形对象会向视图管理者发送消息两个
消息,一个是改变前发送的,此时,视图管理者将调用图形对象的ClearShape,将图形擦
除,一个是在改变后发送的,此时,试图管理者调用图形对象的DrawShape,将具有新属
性值的图形绘制出来。图形对象是以SendMessage方式发送这两个消息的,只有这样才能
保证图形即时的被擦除和显示出来。
有的时候,同时改变了多个属性,如果每修改一个属性都更新一次,这样实在是浪
费时间而且还导致图形的闪烁,解决方法是在修改前调用一次擦除,在修改完所有属性
值后调用一次更新一次就可以了。具体的解决办法是:在修改前调用BeginUpdate,它将
使FUpdateCount的记数增加,然后再修改属性值;在内部应用属性值的方法中,将检测
FUpdateCount的值,如果大于0,则证明处于集中Update状态,此时将旧值放到OldValues
缓冲区中并设置此属性为Update状态,并且不发送消息要求清除旧图形,设置完新的属性
值后也不会发送消息要求更新图形;所有属性都设置完毕后,调用EndUpdate,此时将使
FUpdateCount的记数减少,并再次检查FUpdateCount的值,如果为0,则发送消息,擦除
旧图形,应用新图形,同时它还清楚OldValues缓冲区。
使用的方法有:
BeginUpdate: Inc(FUpdateCount)
EndUpdate: if FUpdateCount>0 then begin Dec(FUpdateCount) if FUpdateCount=0 then begin ClearShape;ClearStoreRecords;DrawShape end
CheckAndUpdate: if FUpdateCount=0 then DrawShape
SetXXValue: if FUpdateCount=0 then begin ClearShape; FXXValue=NewValue;DrawShape end else begn if not StorePropValue then StorePropValue;FXXValue=NewValue end
GetPropValue: if FUpdateCount=0 then Result:=FXXValue else begin FindStoreReocrd if <>nil then Result:=FXXStordValue else result:=FXXValue end
ClearShape:Pen.Mode=pmNotXor; CustomDrawShape;
DrawShape:Pen.Mode=pmSolid; CustomDrawShape;
CustomDrawShape:使用的属性值通过GetPropValue获取,如果BeginUpdate后,没有调用EndUpdate,则一直将使用OldValues绘制图形
Paint:直接调用CustomDrawShape,而不管背景是否被清理。在调用CustomDrawShape之前会清空dValues缓冲区。
OldValues缓冲区是一个链表,每个记录的结构如下:
TValueStoreRecord=record
PropID:Integer;
PropName:string;
PropValue:Variant;
ValueType:Integer;
end;
以上讲述的TrackDraw是基于一般(视图可见)情况的。对于视图不可见的情况,保
存OldValues是没有任何意义的,因为视图由
}
TTrackDraw=class(TComponent)
private
FCanvas: TCanvas;
FOnDrawShapes: TNotifyEvent;
FHasTrackShape: Boolean;
protected
{改变图形的数据}
procedure DoChangeShapeData; virtual;
{绘制,当与掉改变数据前的图形时,State为dsClear,当改变数据后重新绘制图形时,
State为dsNew}
procedure DoDrawTrackShapes(State:TDrawState); virtual;
procedure DoMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); virtual;
procedure DoMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer); virtual;
procedure DoMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); virtual;
public
constructor Create(AOwner:TComponent); override;
destructor Destroy;override;
{在图形数据未改变之前调用该函数与掉原来的图形}
procedure ClearOldTrackShapes;
{在图形数据改变之后重新绘制图形时调用该函数}
procedure DrawNewTrackShapes;
property Canvas:TCanvas read FCanvas write FCanvas;
property HasTrackShape:Boolean read FHasTrackShape;
published
property OnDrawShapes:TNotifyEvent read FOnDrawShapes write FOnDrawShapes;
end;
implementation
{ TTrackDraw }
procedure TTrackDraw.ClearOldTrackShapes;
begin
if FHasTrackShape then
begin
DoDrawTrackShapes(dsClear);
FHasTrackShape:=False;
end;
end;
constructor TTrackDraw.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
FCanvas:=nil;
FHasTrackShape:=False;
end;
destructor TTrackDraw.Destroy;
begin
inherited Destroy;
end;
procedure TTrackDraw.DrawNewTrackShapes;
begin
DoDrawTrackShapes(dsNew);
FHasTrackShape:=True;
end;
procedure TTrackDraw.DoDrawTrackShapes;
begin
if Assigned(FOnDrawShapes) then
FOnDrawShapes(Self);
end;
procedure TTrackDraw.DoMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
end;
procedure TTrackDraw.DoMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
end;
procedure TTrackDraw.DoMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
end;
procedure TTrackDraw.DoChangeShapeData;
begin
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -