mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-02 15:42:08 +02:00
LCL-CustomDrawn: Starts implementing the new drawing model with buffered control images
git-svn-id: trunk@35917 -
This commit is contained in:
parent
fb7f52ecb8
commit
221327700f
@ -40,3 +40,8 @@
|
|||||||
//{$define CD_UseNativeText}
|
//{$define CD_UseNativeText}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
|
// Other options
|
||||||
|
|
||||||
|
// This option makes the drawing faster by buffering previous drawing operations
|
||||||
|
{$define CD_BufferControlImages}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
unit customdrawnproc;
|
unit customdrawnproc;
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
{$include customdrawndefines.inc}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -42,8 +43,16 @@ type
|
|||||||
ScrollX, ScrollY: Integer;
|
ScrollX, ScrollY: Integer;
|
||||||
LastMousePos: TPoint;
|
LastMousePos: TPoint;
|
||||||
IsScrolling: Boolean;
|
IsScrolling: Boolean;
|
||||||
|
// Counter to keep track of when we requested Invalidate
|
||||||
|
// Some systems like X11 and Win32 will keep sending unnecessary paint messages
|
||||||
|
// so for them we just throw the previously painted image
|
||||||
|
InvalidateCount: Integer;
|
||||||
|
// painting objects
|
||||||
|
ControlImage: TLazIntfImage;
|
||||||
|
ControlCanvas: TLazCanvas;
|
||||||
constructor Create; virtual;
|
constructor Create; virtual;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
procedure IncInvalidateCount;
|
||||||
function AdjustCoordinatesForScrolling(AX, AY: Integer): TPoint;
|
function AdjustCoordinatesForScrolling(AX, AY: Integer): TPoint;
|
||||||
property Props[AnIndex:String]:pointer read GetProps write SetProps;
|
property Props[AnIndex:String]:pointer read GetProps write SetProps;
|
||||||
end;
|
end;
|
||||||
@ -56,6 +65,7 @@ type
|
|||||||
WinControl: TWinControl;
|
WinControl: TWinControl;
|
||||||
CDControl: TCDControl;
|
CDControl: TCDControl;
|
||||||
CDControlInjected: Boolean;
|
CDControlInjected: Boolean;
|
||||||
|
procedure UpdateImageAndCanvas;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TCDForm }
|
{ TCDForm }
|
||||||
@ -69,15 +79,10 @@ type
|
|||||||
FocusedControl: TWinControl; // The control focused in the form
|
FocusedControl: TWinControl; // The control focused in the form
|
||||||
FocusedIntfControl: TWinControl; // The intf control focused in the form
|
FocusedIntfControl: TWinControl; // The intf control focused in the form
|
||||||
LayoutAutoAdjusted: Boolean; // Indicates if the form layout was already auto-adjusted once
|
LayoutAutoAdjusted: Boolean; // Indicates if the form layout was already auto-adjusted once
|
||||||
// Counter to keep track of when we requested Invalidate
|
// painting objects which represent the composed form image, don't confuse with ControlImage/ControlCanvas
|
||||||
// Some systems like X11 and Win32 will keep sending unnecessary paint messages
|
|
||||||
// so for them we just throw the previously painted image
|
|
||||||
InvalidateCount: Integer;
|
|
||||||
// painting objects
|
|
||||||
Image: TLazIntfImage;
|
Image: TLazIntfImage;
|
||||||
Canvas: TLazCanvas;
|
Canvas: TLazCanvas;
|
||||||
constructor Create; virtual;
|
constructor Create; virtual;
|
||||||
procedure IncInvalidateCount;
|
|
||||||
function GetFocusedControl: TWinControl;
|
function GetFocusedControl: TWinControl;
|
||||||
function GetFormVirtualHeight(AScreenHeight: Integer): Integer;
|
function GetFormVirtualHeight(AScreenHeight: Integer): Integer;
|
||||||
procedure SanityCheckScrollPos();
|
procedure SanityCheckScrollPos();
|
||||||
@ -447,13 +452,11 @@ var
|
|||||||
lWinControl, lParentControl: TWinControl;
|
lWinControl, lParentControl: TWinControl;
|
||||||
struct : TPaintStruct;
|
struct : TPaintStruct;
|
||||||
lCanvas: TCanvas;
|
lCanvas: TCanvas;
|
||||||
|
lControlCanvas: TLazCanvas;
|
||||||
lBaseWindowOrg: TPoint;
|
lBaseWindowOrg: TPoint;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
||||||
FillChar(struct, SizeOf(TPaintStruct), 0);
|
|
||||||
struct.hdc := HDC(ACanvas);
|
|
||||||
|
|
||||||
lWinControl := ACDWinControl.WinControl;
|
lWinControl := ACDWinControl.WinControl;
|
||||||
|
|
||||||
{$ifdef VerboseCDWinControl}
|
{$ifdef VerboseCDWinControl}
|
||||||
@ -480,24 +483,42 @@ begin
|
|||||||
lWinControl.Width, lWinControl.Height);
|
lWinControl.Width, lWinControl.Height);
|
||||||
ACanvas.ClipRegion := ACDWinControl.Region;
|
ACanvas.ClipRegion := ACDWinControl.Region;
|
||||||
|
|
||||||
// Special drawing for some native controls
|
lControlCanvas := ACanvas;
|
||||||
if lWinControl is TCustomPanel then
|
{$ifdef CD_BufferControlImages}
|
||||||
|
if ACDWinControl.InvalidateCount > 0 then
|
||||||
begin
|
begin
|
||||||
// Erase the background of TPanel controls, since it can draw it's own border, but fails to draw it's own background
|
ACDWinControl.UpdateImageAndCanvas();
|
||||||
ACanvas.SaveState;
|
lControlCanvas := ACDWinControl.ControlCanvas;
|
||||||
ACanvas.Brush.FPColor := TColorToFPColor((lWinControl as TCustomPanel).GetRGBColorResolvingParent());
|
ACDWinControl.InvalidateCount := 0;
|
||||||
ACanvas.Pen.FPColor := ACanvas.Brush.FPColor;
|
{$endif}
|
||||||
ACanvas.Rectangle(Bounds(0, 0, lWinControl.Width, lWinControl.Height));
|
|
||||||
ACanvas.RestoreState(-1);
|
// Special drawing for some native controls
|
||||||
|
if lWinControl is TCustomPanel then
|
||||||
|
begin
|
||||||
|
// Erase the background of TPanel controls, since it can draw it's own border, but fails to draw it's own background
|
||||||
|
lControlCanvas.SaveState;
|
||||||
|
lControlCanvas.Brush.FPColor := TColorToFPColor((lWinControl as TCustomPanel).GetRGBColorResolvingParent());
|
||||||
|
lControlCanvas.Pen.FPColor := lControlCanvas.Brush.FPColor;
|
||||||
|
lControlCanvas.Rectangle(Bounds(0, 0, lWinControl.Width, lWinControl.Height));
|
||||||
|
lControlCanvas.RestoreState(-1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Send the drawing message
|
||||||
|
{$ifdef VerboseCDWinControl}
|
||||||
|
DebugLn('[RenderWinControl] before LCLSendPaintMsg');
|
||||||
|
{$endif}
|
||||||
|
FillChar(struct, SizeOf(TPaintStruct), 0);
|
||||||
|
struct.hdc := HDC(lControlCanvas);
|
||||||
|
LCLSendPaintMsg(lWinControl, struct.hdc, @struct);
|
||||||
|
{$ifdef VerboseCDWinControl}
|
||||||
|
DebugLn('[RenderWinControl] after LCLSendPaintMsg');
|
||||||
|
{$endif}
|
||||||
|
{$ifdef CD_BufferControlImages}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Send the drawing message
|
// Here we actually blit the control to the form canvas
|
||||||
{$ifdef VerboseCDWinControl}
|
ACanvas.CanvasCopyRect(ACDWinControl.ControlCanvas, 0, 0, 0, 0,
|
||||||
DebugLn('[RenderWinControl] before LCLSendPaintMsg');
|
lWinControl.Width, lWinControl.Height);
|
||||||
{$endif}
|
|
||||||
LCLSendPaintMsg(lWinControl, struct.hdc, @struct);
|
|
||||||
{$ifdef VerboseCDWinControl}
|
|
||||||
DebugLn('[RenderWinControl] after LCLSendPaintMsg');
|
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
// Now restore it
|
// Now restore it
|
||||||
@ -865,6 +886,15 @@ begin
|
|||||||
if (not DirFound) and (not DirEmpty) then
|
if (not DirFound) and (not DirEmpty) then
|
||||||
AFontPaths.Add(APath);
|
AFontPaths.Add(APath);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TCDWinControl }
|
||||||
|
|
||||||
|
procedure TCDWinControl.UpdateImageAndCanvas;
|
||||||
|
begin
|
||||||
|
UpdateControlLazImageAndCanvas(ControlImage, ControlCanvas,
|
||||||
|
WinControl.Width, WinControl.Height, clfARGB32);
|
||||||
|
end;
|
||||||
|
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{ TCDBitmap }
|
{ TCDBitmap }
|
||||||
@ -906,14 +936,26 @@ begin
|
|||||||
FProps := TStringList.Create;
|
FProps := TStringList.Create;
|
||||||
//FProps.CaseSensitive:=false; commented as in the qt widgetset
|
//FProps.CaseSensitive:=false; commented as in the qt widgetset
|
||||||
FProps.Sorted:=true;
|
FProps.Sorted:=true;
|
||||||
|
IncInvalidateCount(); // Always starts needing an invalidate
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TCDBaseControl.Destroy;
|
destructor TCDBaseControl.Destroy;
|
||||||
begin
|
begin
|
||||||
FProps.Free;
|
FProps.Free;
|
||||||
|
|
||||||
|
// Free the Canvas and Image if required
|
||||||
|
// Dont free for the Form because elsewhere this is taken care of
|
||||||
|
if ControlCanvas <> nil then ControlCanvas.Free;
|
||||||
|
if ControlImage <> nil then ControlImage.Free;
|
||||||
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCDBaseControl.IncInvalidateCount;
|
||||||
|
begin
|
||||||
|
Inc(InvalidateCount);
|
||||||
|
end;
|
||||||
|
|
||||||
function TCDBaseControl.AdjustCoordinatesForScrolling(AX, AY: Integer): TPoint;
|
function TCDBaseControl.AdjustCoordinatesForScrolling(AX, AY: Integer): TPoint;
|
||||||
begin
|
begin
|
||||||
DebugLn(Format('AX=%d AY=%d ScrollX=%d ScrollY=%d', [AX, AY, ScrollX, ScrollY]));
|
DebugLn(Format('AX=%d AY=%d ScrollX=%d ScrollY=%d', [AX, AY, ScrollX, ScrollY]));
|
||||||
@ -928,11 +970,6 @@ begin
|
|||||||
InvalidateCount := 1;
|
InvalidateCount := 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCDForm.IncInvalidateCount;
|
|
||||||
begin
|
|
||||||
Inc(InvalidateCount);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TCDForm.GetFocusedControl: TWinControl;
|
function TCDForm.GetFocusedControl: TWinControl;
|
||||||
begin
|
begin
|
||||||
if FocusedIntfControl <> nil then Result := FocusedIntfControl
|
if FocusedIntfControl <> nil then Result := FocusedIntfControl
|
||||||
|
@ -4681,6 +4681,7 @@ begin
|
|||||||
if lHandle is TCDWinControl then
|
if lHandle is TCDWinControl then
|
||||||
begin
|
begin
|
||||||
lControlHandle := TCDWinControl(lHandle);
|
lControlHandle := TCDWinControl(lHandle);
|
||||||
|
lControlHandle.IncInvalidateCount();
|
||||||
lControl := lControlHandle.WinControl;
|
lControl := lControlHandle.WinControl;
|
||||||
lControl := Forms.GetParentForm(lControl);
|
lControl := Forms.GetParentForm(lControl);
|
||||||
Result := BackendInvalidateRect(lControl.Handle, Rect, BErase);
|
Result := BackendInvalidateRect(lControl.Handle, Rect, BErase);
|
||||||
|
Loading…
Reference in New Issue
Block a user