📄 gr32_image.pas
字号:
property Color;
property Constraints;
property Cursor;
{$IFNDEF CLX}
property DragCursor;
{$ENDIF}
property ParentColor;
property ParentShowHint;
property PopupMenu;
property RepaintMode;
property Scale;
property ScrollBars;
property ShowHint;
property SizeGrip;
property OverSize;
property TabOrder;
property TabStop;
property Visible;
property OnBitmapResize;
{$IFNDEF CLX}
property OnCanResize;
{$ENDIF}
property OnClick;
property OnChange;
{$IFDEF DELPHI5}
property OnContextPopup;
{$ENDIF}
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnGDIOverlay;
property OnInitStages;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnPaintStage;
property OnResize;
property OnScroll;
property OnStartDrag;
end;
{ TBitmap32Item }
{ A bitmap container designed to be inserted into TBitmap32Collection }
TBitmap32Item = class(TCollectionItem)
private
FBitmap: TBitmap32;
procedure SetBitmap(ABitmap: TBitmap32);
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
published
property Bitmap: TBitmap32 read FBitmap write SetBitmap;
end;
TBitmap32ItemClass = class of TBitmap32Item;
{ TBitmap32Collection }
{ A collection of TBitmap32Item objects }
TBitmap32Collection = class(TCollection)
private
FOwner: TPersistent;
function GetItem(Index: Integer): TBitmap32Item;
procedure SetItem(Index: Integer; Value: TBitmap32Item);
protected
function GetOwner: TPersistent; override;
public
constructor Create(AOwner: TPersistent; ItemClass: TBitmap32ItemClass);
function Add: TBitmap32Item;
property Items[Index: Integer]: TBitmap32Item read GetItem write SetItem; default;
end;
{ TBitmap32List }
{ A component that stores TBitmap32Collection }
TBitmap32List = class(TComponent)
private
FBitmap32Collection: TBitmap32Collection;
procedure SetBitmap(Index: Integer; Value: TBitmap32);
function GetBitmap(Index: Integer): TBitmap32;
procedure SetBitmap32Collection(Value: TBitmap32Collection);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Bitmap[Index: Integer]: TBitmap32 read GetBitmap write SetBitmap; default;
published
property Bitmaps: TBitmap32Collection read FBitmap32Collection write SetBitmap32Collection;
end;
implementation
uses
Math, TypInfo, GR32_MicroTiles;
type
TBitmap32Access = class(TBitmap32);
TLayerAccess = class(TCustomLayer);
TLayerCollectionAccess = class(TLayerCollection);
TRangeBarAccess = class(TRangeBar);
const
DefaultRepaintOptimizerClass: TCustomRepaintOptimizerClass = TMicroTilesRepaintOptimizer;
UnitXForm: TCoordXForm = (
ScaleX: $10000;
ScaleY: $10000;
ShiftX: 0;
ShiftY: 0;
RevScaleX: 65536;
RevScaleY: 65536);
{ TPaintStages }
function TPaintStages.Add: PPaintStage;
var
L: Integer;
begin
L := Length(FItems);
SetLength(FItems, L + 1);
Result := @FItems[L];
with Result^ do
begin
DsgnTime := False;
RunTime := True;
Stage := 0;
Parameter := 0;
end;
end;
procedure TPaintStages.Clear;
begin
FItems := nil;
end;
function TPaintStages.Count: Integer;
begin
Result := Length(FItems);
end;
procedure TPaintStages.Delete(Index: Integer);
var
Count: Integer;
begin
if (Index < 0) or (Index > High(FItems)) then
raise EListError.Create('Invalid stage index');
Count := Length(FItems) - Index - 1;
if Count > 0 then
Move(FItems[Index + 1], FItems[Index], Count * SizeOf(TPaintStage));
SetLength(FItems, High(FItems));
end;
destructor TPaintStages.Destroy;
begin
Clear;
inherited;
end;
function TPaintStages.GetItem(Index: Integer): PPaintStage;
begin
Result := @FItems[Index];
end;
function TPaintStages.Insert(Index: Integer): PPaintStage;
var
Count: Integer;
begin
if Index < 0 then Index := 0
else if Index > Length(FItems) then Index := Length(FItems);
Count := Length(FItems) - Index;
SetLength(FItems, Length(FItems) + 1);
if Count > 0 then
Move(FItems[Index], FItems[Index + 1], Count * SizeOf(TPaintStage));
Result := @FItems[Index];
with Result^ do
begin
DsgnTime := False;
RunTime := True;
Stage := 0;
Parameter := 0;
end;
end;
{ TCustomPaintBox32 }
{$IFNDEF CLX}
procedure TCustomPaintBox32.CMInvalidate(var Message: TMessage);
begin
if CustomRepaint and HandleAllocated then
// we might have invalid rects, so just go ahead without invalidating
// the whole client area...
PostMessage(Handle, WM_PAINT, 0, 0)
else
// no invalid rects, so just invalidate the whole client area...
inherited;
end;
procedure TCustomPaintBox32.CMMouseEnter(var Message: TMessage);
begin
inherited;
MouseEnter;
end;
procedure TCustomPaintBox32.CMMouseLeave(var Message: TMessage);
begin
MouseLeave;
inherited;
end;
{$ENDIF}
constructor TCustomPaintBox32.Create(AOwner: TComponent);
begin
inherited;
FBuffer := TBitmap32.Create;
FBufferOversize := 40;
FForceFullRepaint := True;
FInvalidRects := TRectList.Create;
FRepaintOptimizer := DefaultRepaintOptimizerClass.Create(Buffer, InvalidRects);
Height := 192;
Width := 192;
end;
destructor TCustomPaintBox32.Destroy;
begin
FRepaintOptimizer.Free;
FInvalidRects.Free;
FBuffer.Free;
inherited;
end;
procedure TCustomPaintBox32.DoBufferResized(const OldWidth, OldHeight: Integer);
begin
if FRepaintOptimizer.Enabled then
FRepaintOptimizer.BufferResizedHandler(FBuffer.Width, FBuffer.Height);
end;
function TCustomPaintBox32.CustomRepaint: Boolean;
begin
Result := FRepaintOptimizer.Enabled and not FForceFullRepaint and
FRepaintOptimizer.UpdatesAvailable;
end;
procedure TCustomPaintBox32.DoPrepareInvalidRects;
begin
if FRepaintOptimizer.Enabled and not FForceFullRepaint then
FRepaintOptimizer.PerformOptimization;
end;
function TCustomPaintBox32.InvalidRectsAvailable: Boolean;
begin
Result := True;
end;
procedure TCustomPaintBox32.DoPaintBuffer;
begin
// force full repaint, this is necessary when Buffer is invalid and was never painted
// This will omit calculating the invalid rects, thus we paint everything.
if FForceFullRepaint then
begin
FForceFullRepaint := False;
FInvalidRects.Clear;
end
else
DoPrepareInvalidRects;
// descendants should override this method for painting operations,
// not the Paint method!!!
FBufferValid := True;
end;
procedure TCustomPaintBox32.DoPaintGDIOverlay;
begin
if Assigned(FOnGDIOverlay) then FOnGDIOverlay(Self);
end;
procedure TCustomPaintBox32.Flush;
begin
{$IFDEF CLX}
if Assigned(Canvas.Handle) and Assigned(FBuffer.Handle) then
{$ELSE}
if (Canvas.Handle <> 0) and (FBuffer.Handle <> 0) then
{$ENDIF}
begin
Canvas.Lock;
try
FBuffer.Lock;
try
with GetViewportRect do
{$IFDEF CLX}
begin
if not QPainter_isActive(FBuffer.Handle) then
if not QPainter_begin(FBuffer.Handle, FBuffer.Pixmap) then
raise EInvalidGraphicOperation.CreateRes(@SInvalidCanvasState);
QPainter_drawPixmap(Canvas.Handle, Top, Left, FBuffer.Pixmap, 0, 0, Right - Left, Bottom - Top);
QPainter_end(FBuffer.Handle);
TBitmap32Access(FBuffer).CheckPixmap; // try to avoid QPixmap -> QImage conversion, since we don't need that.
end;
{$ELSE}
BitBlt(Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
FBuffer.Handle, 0, 0, SRCCOPY);
{$ENDIF}
finally
FBuffer.Unlock;
end;
finally
Canvas.Unlock;
end;
end;
end;
procedure TCustomPaintBox32.Flush(const SrcRect: TRect);
var
R: TRect;
begin
{$IFDEF CLX}
if Assigned(Canvas.Handle) and Assigned(FBuffer.Handle) then
{$ELSE}
if (Canvas.Handle <> 0) and (FBuffer.Handle <> 0) then
{$ENDIF}
begin
Canvas.Lock;
try
FBuffer.Lock;
try
R := GetViewPortRect;
with SrcRect do
{$IFDEF CLX}
begin
if not QPainter_isActive(FBuffer.Handle) then
if not QPainter_begin(FBuffer.Handle, FBuffer.Pixmap) then
raise EInvalidGraphicOperation.CreateRes(@SInvalidCanvasState);
QPainter_drawPixmap(Canvas.Handle, Top + R.Top, Left + R.Left,
FBuffer.Pixmap, 0, 0, Right - Left, Bottom - Top);
QPainter_end(FBuffer.Handle);
TBitmap32Access(FBuffer).CheckPixmap; // try to avoid QPixmap -> QImage conversion, since we don't need that.
end;
{$ELSE}
BitBlt(Canvas.Handle, Left + R.Left, Top + R.Top, Right - Left, Bottom - Top,
FBuffer.Handle, Left, Top, SRCCOPY);
{$ENDIF}
finally
FBuffer.Unlock;
end;
finally
Canvas.Unlock;
end;
end;
end;
function TCustomPaintBox32.GetViewportRect: TRect;
begin
// returns position of the buffered area within the control bounds
with Result do
begin
// by default, the whole control is buffered
Left := 0;
Top := 0;
Right := Width;
Bottom := Height;
end;
end;
procedure TCustomPaintBox32.Invalidate;
begin
FBufferValid := False;
inherited;
end;
procedure TCustomPaintBox32.ForceFullInvalidate;
begin
if FRepaintOptimizer.Enabled then FRepaintOptimizer.Reset;
FForceFullRepaint := True;
Invalidate;
end;
procedure TCustomPaintBox32.Loaded;
begin
FBufferValid := False;
inherited;
end;
procedure TCustomPaintBox32.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (pboAutoFocus in Options) and CanFocus then SetFocus;
inherited;
end;
{$IFDEF CLX}
procedure TCustomPaintBox32.MouseEnter(AControl: TControl);
begin
FMouseInControl := True;
inherited;
end;
procedure TCustomPaintBox32.MouseLeave(AControl: TControl);
begin
FMouseInControl := False;
inherited;
end;
{$ELSE}
procedure TCustomPaintBox32.MouseEnter;
begin
FMouseInControl := True;
if Assigned(FOnMouseEnter) then
FOnMouseEnter(Self);
end;
procedure TCustomPaintBox32.MouseLeave;
begin
FMouseInControl := False;
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self);
end;
{$ENDIF}
procedure TCustomPaintBox32.Paint;
var
I: Integer;
begin
if FRepaintOptimizer.Enabled then
begin
{$IFDEF CLX}
if CustomRepaint then DoPrepareInvalidRects;
{$ENDIF}
FRepaintOptimizer.BeginPaint;
end;
if not FBufferValid then
begin
{$IFDEF CLX}
TBitmap32Access(FBuffer).ImageNeeded;
{$ENDIF}
DoPaintBuffer;
{$IFDEF CLX}
TBitmap32Access(FBuffer).CheckPixmap;
{$ENDIF}
end;
FBuffer.Lock;
with Canvas do
try
{$IFDEF CLX}
if FInvalidRects.Count > 0 then
for i := 0 to FInvalidRects.Count - 1 do
with FInvalidRects[i]^ do
QPainter_drawImage(Canvas.Handle, Left, Top, FBuffer.Image, Left, Top, Right - Left, Bottom - Top)
else
begin
if not QPainter_isActive(FBuffer.Handle) then
if not QPainter_begin(FBuffer.Handle, FBuffer.Pixmap) then
raise EInvalidGraphicOperation.CreateRes(@SInvalidCanvasState);
with GetViewportRect do
QPainter_drawPixmap(Canvas.Handle, Left, Top, FBuffer.Pixmap, Left, Top, Right - Left, Bottom - Top);
QPainter_end(FBuffer.Handle);
end;
{$ELSE}
if FInvalidRects.Count > 0 then
for i := 0 to FInvalidRects.Count - 1 do
with FInvalidRects[i]^ do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -