📄 gr32_image.pas
字号:
FBufferValid := True;
end;
procedure TCustomImage32.DoPaintGDIOverlay;
var
I: Integer;
begin
for I := 0 to Layers.Count - 1 do
if (Layers[I].LayerOptions and LOB_GDI_OVERLAY) <> 0 then
TLayerAccess(Layers[I]).PaintGDI(Canvas);
inherited;
end;
procedure TCustomImage32.DoScaleChange;
begin
if Assigned(FOnScaleChange) then FOnScaleChange(Self);
end;
procedure TCustomImage32.EndUpdate;
begin
// re-enable OnChange & OnChanging generation
Dec(FUpdateCount);
Assert(FUpdateCount >= 0, 'Unpaired EndUpdate call');
end;
procedure TCustomImage32.ExecBitmapFrame(Dest: TBitmap32; StageNum: Integer);
begin
Dest.Canvas.DrawFocusRect(CachedBitmapRect);
end;
procedure TCustomImage32.ExecClearBackgnd(Dest: TBitmap32; StageNum: Integer);
var
C: TColor32;
I: Integer;
begin
C := Color32(Color);
if FInvalidRects.Count > 0 then
begin
for I := 0 to FInvalidRects.Count - 1 do
with FInvalidRects[I]^ do
Dest.FillRectS(Left, Top, Right, Bottom, C);
end
else
begin
if (Bitmap.Empty) or (Bitmap.DrawMode <> dmOpaque) then
Dest.Clear(C)
else
with CachedBitmapRect do
begin
if (Left > 0) or (Right < Width) or (Top > 0) or (Bottom < Height) and
not (BitmapAlign = baTile) then
begin
// clean only the part of the buffer lying around image edges
Dest.FillRectS(0, 0, Width, Top, C); // top
Dest.FillRectS(0, Bottom, Width, Height, C); // bottom
Dest.FillRectS(0, Top, Left, Bottom, C); // left
Dest.FillRectS(Right, Top, Width, Bottom, C); // right
end;
end;
end;
end;
procedure TCustomImage32.ExecClearBuffer(Dest: TBitmap32; StageNum: Integer);
begin
Dest.Clear(Color32(Color));
end;
procedure TCustomImage32.ExecControlFrame(Dest: TBitmap32; StageNum: Integer);
begin
{$IFDEF CLX}
Dest.Canvas.DrawFocusRect(Rect(0, 0, Width, Height));
{$ELSE}
DrawFocusRect(Dest.Handle, Rect(0, 0, Width, Height));
{$ENDIF}
end;
procedure TCustomImage32.ExecCustom(Dest: TBitmap32; StageNum: Integer);
begin
if Assigned(FOnPaintStage) then FOnPaintStage(Self, Dest, StageNum);
end;
procedure TCustomImage32.ExecDrawBitmap(Dest: TBitmap32; StageNum: Integer);
var
I, J, Tx, Ty: Integer;
R: TRect;
begin
if Bitmap.Empty or IsRectEmpty(CachedBitmapRect) then Exit;
Bitmap.Lock;
try
if BitmapAlign <> baTile then Bitmap.DrawTo(Dest, CachedBitmapRect)
else with CachedBitmapRect do
begin
Tx := Dest.Width div Right;
Ty := Dest.Height div Bottom;
for J := 0 to Ty do
for I := 0 to Tx do
begin
R := CachedBitmapRect;
OffsetRect(R, Right * I, Bottom * J);
Bitmap.DrawTo(Dest, R);
end;
end;
finally
Bitmap.Unlock;
end;
end;
procedure TCustomImage32.ExecDrawLayers(Dest: TBitmap32; StageNum: Integer);
var
I: Integer;
Mask: Cardinal;
begin
Mask := PaintStages[StageNum]^.Parameter;
for I := 0 to Layers.Count - 1 do
if (Layers.Items[I].LayerOptions and Mask) <> 0 then
TLayerAccess(Layers.Items[I]).DoPaint(Dest);
end;
function TCustomImage32.GetBitmapRect: TRect;
var
Size: TSize;
begin
if Bitmap.Empty then
with Result do
begin
Left := 0;
Right := 0;
Top := 0;
Bottom := 0;
end
else
begin
Size := GetBitmapSize;
with Size do
begin
Result := Rect(0, 0, Cx, Cy);
if BitmapAlign = baCenter then
OffsetRect(Result, (Width - Cx) div 2, (Height - Cy) div 2)
else if BitmapAlign = baCustom then
OffsetRect(Result, Round(OffsetHorz), Round(OffsetVert));
end;
end;
end;
function TCustomImage32.GetBitmapSize: TSize;
var
Mode: TScaleMode;
ViewportWidth, ViewportHeight: Integer;
RScaleX, RScaleY: Single;
begin
with Result do
begin
if Bitmap.Empty or (Width = 0) or (Height = 0) then
begin
Cx := 0;
Cy := 0;
Exit;
end;
with GetViewportRect do
begin
ViewportWidth := Right - Left;
ViewportHeight := Bottom - Top;
end;
// check for optimal modes as these are compounds of the other modes.
case ScaleMode of
smOptimal:
if (Bitmap.Width > ViewportWidth) or (Bitmap.Height > ViewportHeight) then
Mode := smResize
else
Mode := smNormal;
smOptimalScaled:
if (Round(Bitmap.Width * ScaleX) > ViewportWidth) or
(Round(Bitmap.Height * ScaleY) > ViewportHeight) then
Mode := smResize
else
Mode := smScale;
else
Mode := ScaleMode;
end;
case Mode of
smNormal:
begin
Cx := Bitmap.Width;
Cy := Bitmap.Height;
end;
smStretch:
begin
Cx := ViewportWidth;
Cy := ViewportHeight;
end;
smResize:
begin
Cx := Bitmap.Width;
Cy := Bitmap.Height;
RScaleX := ViewportWidth / Cx;
RScaleY := ViewportHeight / Cy;
if RScaleX >= RScaleY then
begin
Cx := Round(Cx * RScaleY);
Cy := ViewportHeight;
end
else
begin
Cx := ViewportWidth;
Cy := Round(Cy * RScaleX);
end;
end;
else // smScale
begin
Cx := Round(Bitmap.Width * ScaleX);
Cy := Round(Bitmap.Height * ScaleY);
end;
end;
if Cx <= 0 then Cx := 0;
if Cy <= 0 then Cy := 0;
end;
end;
function TCustomImage32.GetOnPixelCombine: TPixelCombineEvent;
begin
Result := FBitmap.OnPixelCombine;
end;
procedure TCustomImage32.InitDefaultStages;
begin
// background
with PaintStages.Add^ do
begin
DsgnTime := True;
RunTime := True;
Stage := PST_CLEAR_BACKGND;
end;
// control frame
with PaintStages.Add^ do
begin
DsgnTime := True;
RunTime := False;
Stage := PST_CONTROL_FRAME;
end;
// bitmap
with PaintStages.Add^ do
begin
DsgnTime := True;
RunTime := True;
Stage := PST_DRAW_BITMAP;
end;
// bitmap frame
with PaintStages.Add^ do
begin
DsgnTime := True;
RunTime := False;
Stage := PST_BITMAP_FRAME;
end;
// layers
with PaintStages.Add^ do
begin
DsgnTime := True;
RunTime := True;
Stage := PST_DRAW_LAYERS;
Parameter := $80000000;
end;
end;
procedure TCustomImage32.Invalidate;
begin
BufferValid := False;
CacheValid := False;
inherited;
end;
procedure TCustomImage32.InvalidateCache;
begin
if FRepaintOptimizer.Enabled then FRepaintOptimizer.Reset;
CacheValid := False;
end;
procedure TCustomImage32.Loaded;
begin
inherited;
DoInitStages;
end;
procedure TCustomImage32.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Layer: TCustomLayer;
begin
inherited;
if TabStop and CanFocus then SetFocus;
if Layers.MouseEvents then
Layer := TLayerCollectionAccess(Layers).MouseDown(Button, Shift, X, Y)
else
Layer := nil;
// lock the capture only if mbLeft was pushed or any mouse listener was activated
if (Button = mbLeft) or (TLayerCollectionAccess(Layers).MouseListener <> nil) then
MouseCapture := True;
MouseDown(Button, Shift, X, Y, Layer);
end;
procedure TCustomImage32.MouseMove(Shift: TShiftState; X, Y: Integer);
var
Layer: TCustomLayer;
begin
inherited;
if Layers.MouseEvents then
Layer := TLayerCollectionAccess(Layers).MouseMove(Shift, X, Y)
else
Layer := nil;
MouseMove(Shift, X, Y, Layer);
end;
procedure TCustomImage32.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Layer: TCustomLayer;
begin
if Layers.MouseEvents then
Layer := TLayerCollectionAccess(Layers).MouseUp(Button, Shift, X, Y)
else
Layer := nil;
// unlock the capture only if mbLeft was raised and there is no active mouse listeners
if (Button = mbLeft) and (TLayerCollectionAccess(Layers).MouseListener = nil) then
MouseCapture := False;
MouseUp(Button, Shift, X, Y, Layer);
end;
procedure TCustomImage32.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
begin
if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y, Layer);
end;
procedure TCustomImage32.MouseMove(Shift: TShiftState; X, Y: Integer;
Layer: TCustomLayer);
begin
if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y, Layer);
end;
procedure TCustomImage32.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer; Layer: TCustomLayer);
begin
if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y, Layer);
end;
{$IFDEF CLX}
procedure TCustomImage32.MouseLeave(AControl: TControl);
begin
if (Layers.MouseEvents) and (Layers.MouseListener = nil) then
Screen.Cursor := crDefault;
inherited;
end;
{$ELSE}
procedure TCustomImage32.MouseLeave;
begin
if (Layers.MouseEvents) and (Layers.MouseListener = nil) then
Screen.Cursor := crDefault;
inherited;
end;
{$ENDIF}
procedure TCustomImage32.PaintTo(Dest: TBitmap32; DestRect: TRect);
var
OldRepaintMode: TRepaintMode;
I: Integer;
begin
OldRepaintMode := RepaintMode;
RepaintMode := rmFull;
CachedBitmapRect := DestRect;
with CachedBitmapRect, CachedXForm do
begin
if (Right - Left <= 0) or (Bottom - Top <= 0) or Bitmap.Empty then
CachedXForm := UnitXForm
else
begin
ShiftX := Left;
ShiftY := Top;
ScaleX := MulDiv(Right - Left, $10000, Bitmap.Width);
ScaleY := MulDiv(Bottom - Top, $10000, Bitmap.Height);
RevScaleX := MulDiv(Bitmap.Width, $10000, Right - Left);
RevScaleY := MulDiv(Bitmap.Height, $10000, Bottom - Top);
end;
end;
CacheValid := True;
PaintToMode := True;
try
for I := 0 to FPaintStages.Count - 1 do
with FPaintStages[I]^ do
if RunTime then
case Stage of
PST_CUSTOM: ExecCustom(Dest, I);
PST_CLEAR_BUFFER: ExecClearBuffer(Dest, I);
PST_CLEAR_BACKGND: ExecClearBackgnd(Dest, I);
PST_DRAW_BITMAP: ExecDrawBitmap(Dest, I);
PST_DRAW_LAYERS: ExecDrawLayers(Dest, I);
PST_CONTROL_FRAME: ExecControlFrame(Dest, I);
PST_BITMAP_FRAME: ExecBitmapFrame(Dest, I);
end;
finally
PaintToMode := False;
end;
CacheValid := False;
RepaintMode := OldRepaintMode;
end;
procedure TCustomImage32.Resize;
begin
InvalidateCache;
inherited;
end;
procedure TCustomImage32.SetBitmap(Value: TBitmap32);
begin
InvalidateCache;
FBitmap.Assign(Value);
end;
procedure TCustomImage32.SetBitmapAlign(Value: TBitmapAlign);
begin
InvalidateCache;
FBitmapAlign := Value;
Changed;
end;
procedure TCustomImage32.SetLayers(Value: TLayerCollection);
begin
FLayers.Assign(Value);
end;
procedure TCustomImage32.SetOffsetHorz(Value: Single);
begin
if Value <> FOffsetHorz then
begin
InvalidateCache;
FOffsetHorz := Value;
Changed;
end;
end;
procedure TCustomImage32.SetOffsetVert(Value: Single);
begin
if Value <> FOffsetVert then
begin
FOffsetVert := Value;
InvalidateCache;
Changed;
end;
end;
procedure TCustomImage32.SetOnPixelCombine(Value: TPixelCombineEvent);
begin
FBitmap.OnPixelCombine := Value;
Changed;
end;
procedure TCustomImage32.SetScale(Value: Single);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -