unit umain;{$mode objfpc}{$H+}interfaceuses Classes, SysUtils, FileUtil, BGRAVirtualScreen, Forms, Controls, Graphics, Dialogs, ExtCtrls, BGRABitmap, BGRABitmapTypes, bgrasamples, BGRATextFX, BGRAGradients;type { TForm1 } TForm1 = class(TForm) vsClock: TBGRAVirtualScreen; Timer1: TTimer; procedure FormClose(Sender : TObject; var CloseAction : TCloseAction); procedure FormCreate(Sender : TObject); procedure FormResize(Sender : TObject); procedure Timer1Timer(Sender: TObject); procedure vsClockRedraw(Sender: TObject; Bitmap: TBGRABitmap); private { private declarations } public { public declarations } ClockBody, MovingParts : TBGRABitmap; procedure Initialize; procedure CreateClockBody; procedure CreateMovingParts; end;var Form1: TForm1;implementation{$R *.lfm}{ TForm1 }procedure TForm1.vsClockRedraw(Sender: TObject; Bitmap: TBGRABitmap);begin //Bitmap.PutImage(0, 0, ClockBody, dmDrawWithTransparency); Bitmap.BlendImage(0, 0, ClockBody, boLinearBlend); Bitmap.BlendImage(0, 0, MovingParts, boLinearBlend);end;procedure TForm1.Initialize;beginend;procedure TForm1.CreateClockBody;var img : TBGRABitmap; txt: TBGRACustomBitmap; A : Integer; w, h, r, Xo, Yo, X, Y, Xt, Yt: integer; phong: TPhongShading;begin w := vsClock.Width; h := vsClock.Height; img := TBGRABitmap.Create(w,h); { Set center point } Xo := w div 2; Yo := h div 2; // Determine radius. If canvas is rectangular then r = shortest length w or h r := yo; if xo > yo then r := yo; if xo < yo then r := xo; // Draw Bitmap frame img.FillEllipseAntialias(Xo, Yo, r * 0.99, r * 0.99, BGRA(175, 175, 175)); // Draw Rounded/RIng type border using shading phong := TPhongShading.Create; phong.LightPosition := point(Xo, Yo); phong.DrawSphere(img, rect(round(Xo - r * 0.98), round(Yo - r * 0.98), round(Xo + r * 0.98) + 1, round(Yo + r * 0.98) + 1), 4, BGRA(245, 245, 245)); phong.Free; img.FillEllipseLinearColorAntialias(Xo, Yo, r * 0.88, r * 0.88, BGRA(0, 58, 81), BGRA(2, 94, 131)); // Draw Face frame img.FillEllipseAntialias(Xo, Yo, r * 0.90, r * 0.90, BGRA(175, 175, 175)); // Draw face background img.FillEllipseLinearColorAntialias(Xo, Yo, r * 0.88, r * 0.88, BGRA(0, 58, 81), BGRA(2, 94, 131)); // Draw Bitmap face for A := 1 to 12 do begin X := Xo + Round(r * 0.80 * Sin(30 * A * Pi / 180)); Y := Yo - Round(r * 0.80 * Cos(30 * A * Pi / 180)); Xt := Xo + Round(r * 0.70 * Sin(30 * A * Pi / 180)); Yt := Yo - Round(r * 0.70 * Cos(30 * A * Pi / 180)); img.EllipseAntialias(x, y, (r * 0.02), (r * 0.02), BGRA(255, 255, 255, 200), 2, BGRA(2, 94, 131)); img.FontName := 'Calibri'; img.FontHeight := r div 8; img.FontQuality := fqFineAntialiasing; img.TextOut(Xt, Yt - (img.FontHeight / 1.7), IntToStr(A), BGRA(245, 245, 245), taCenter); end; // Draw text txt := TextShadow(w, h, 'www.Digeotek.com', trunc(r * 0.12), ColorToBGRA(clWhite), BGRABlack, 4, 4, 10, [], 'Calibri'); img.BlendImage(0, 0 - (r div 3), txt, boLinearBlend); txt.Free; ClockBody.Assign(img); img.Free;end;procedure TForm1.CreateMovingParts;var img : TBGRABitmap; w, h, r, Xo, Yo : integer; Xs, Ys, Xm, Ym, Xh, Yh: integer; th, tm, ts, tn: word;begin w := vsClock.Width; h := vsClock.Height; img := TBGRABitmap.Create(w,h); { Set center point } Xo := w div 2; Yo := h div 2; // Determine radius. If canvas is rectangular then r = shortest length w or h r := yo; if xo > yo then r := yo; if xo < yo then r := xo; //// Convert current time to integer values decodetime(Time, th, tm, ts, tn); //{ Set coordinates (length of arm) for seconds } Xs := Xo + Round(r * 0.78 * Sin(ts * 6 * Pi / 180)); Ys := Yo - Round(r * 0.78 * Cos(ts * 6 * Pi / 180)); //{ Set coordinates (length of arm) for minutes } Xm := Xo + Round(r * 0.68 * Sin(tm * 6 * Pi / 180)); Ym := Yo - Round(r * 0.68 * Cos(tm * 6 * Pi / 180)); //{ Set coordinates (length of arm) for hours } Xh := Xo + Round(r * 0.50 * Sin((th * 30 + tm / 2) * Pi / 180)); Yh := Yo - Round(r * 0.50 * Cos((th * 30 + tm / 2) * Pi / 180)); // Draw time hands img.DrawLineAntialias(xo, yo, xs, ys, BGRA(255, 0, 0), r * 0.02); img.DrawLineAntialias(xo, yo, xm, ym, BGRA(245, 245, 245), r * 0.03); img.DrawLineAntialias(xo, yo, xh, yh, BGRA(245, 245, 245), r * 0.07); img.DrawLineAntialias(xo, yo, xh, yh, BGRA(2, 94, 131), r * 0.04); // Draw Bitmap centre dot img.EllipseAntialias(Xo, Yo, r * 0.04, r * 0.04, BGRA(245, 245, 245, 255), r * 0.02, BGRA(210, 210, 210, 255)); MovingParts.Assign(img); img.Free;end;procedure TForm1.Timer1Timer(Sender: TObject);begin CreateMovingParts; vsClock.RedrawBitmap;end;procedure TForm1.FormCreate(Sender : TObject);begin ClockBody := TBGRABitmap.Create; MovingParts := TBGRABitmap.Create; CreateClockBody;end;procedure TForm1.FormClose(Sender : TObject; var CloseAction : TCloseAction);begin ClockBody.Free; MovingParts.Free;end;procedure TForm1.FormResize(Sender : TObject);begin CreateClockBody; CreateMovingParts;end;end.
@digeoI used your clock code as an example to test BGRAcontrols in the raspberrypi. My own BGRA stuff is working on the pi with just a few minor tweaks mostly due to running an older version of the lazarus IDE on the pi. I decided to take your code as a further test and just see if it ported and it did except it ran to slow for the second hand's i sec tick. It was never my intention to ask you to speed it up. I just observed how often things can work fine on desktop multi giga hertz multiprocessor massive ram PC's but crawl on a raspberry pi for example. I wanted to emphasize that the future direction is toward android iphone phone and tablet devices so it could be useful if code is tested on less capacious platforms. Anyway you did take the time and congratulations it is working well on the raspberry pi. The second hand ticks once per sec on the pi. Thanks.
TCustomDemoControl = class(TGraphicControl) private FCaption: string; FDemoProperties: TDemoProperties; FBitmap: TBitmap; procedure SetCaption(AValue: string); procedure SetDemoProperties(AValue: TDemoProperties); { Private declarations } protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Paint; override; procedure DrawTest; published { Published declarations } property DemoProperties : TDemoProperties read FDemoProperties write SetDemoProperties; property Caption : string read FCaption write SetCaption; end; // **************************************************************************//procedure TCustomDemoControl.Paint;begin if (csCreating in FControlState) then exit; DrawTest; inherited Paint;end;procedure TCustomDemoControl.DrawTest;var x, y: integer;begin if FDemoProperties.Enabled then begin // Initializes the Bitmap Size FBitmap.Height := Height; FBitmap.Width := Width; // Draws the background FBitmap.Canvas.Pen.Color := clWhite; FBitmap.Canvas.Rectangle(0, 0, Width, Height); // Draws squares FBitmap.Canvas.Pen.Color := FDemoProperties.Color; for x := 1 to 8 do for y := 1 to 8 do FBitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8), Round(x * Width / 8), Round(y * Height / 8)); Canvas.Draw(0, 0, FBitmap); end;end;
I am in the process of creating a component for the analog clock. This is my first Lazarus component and are stuck at a point.I am using a BGRAGraphicControl to draw the draw clock on. The problem I have is when I change settings in the object inspector, it does not automatically happen on the control. When I click on the form the changes happen. The same goes for when I run the app. When I show/hide the app, the changes occur.I realize this is to do with the paint procedure and I am not sure how to fix this. I have tried invalidate and refresh but then app freezes as the custom control is stuck in paint procedure because of the update.This what I have so far in a small demo using TGraphicControl:Code: [Select] TCustomDemoControl = class(TGraphicControl) private FCaption: string; FDemoProperties: TDemoProperties; FBitmap: TBitmap; procedure SetCaption(AValue: string); procedure SetDemoProperties(AValue: TDemoProperties); { Private declarations } protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Paint; override; procedure DrawTest; published { Published declarations } property DemoProperties : TDemoProperties read FDemoProperties write SetDemoProperties; property Caption : string read FCaption write SetCaption; end; // **************************************************************************//procedure TCustomDemoControl.Paint;begin if (csCreating in FControlState) then exit; DrawTest; inherited Paint;end;procedure TCustomDemoControl.DrawTest;var x, y: integer;begin if FDemoProperties.Enabled then begin // Initializes the Bitmap Size FBitmap.Height := Height; FBitmap.Width := Width; // Draws the background FBitmap.Canvas.Pen.Color := clWhite; FBitmap.Canvas.Rectangle(0, 0, Width, Height); // Draws squares FBitmap.Canvas.Pen.Color := FDemoProperties.Color; for x := 1 to 8 do for y := 1 to 8 do FBitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8), Round(x * Width / 8), Round(y * Height / 8)); Canvas.Draw(0, 0, FBitmap); end;end;
procedure Paint; override; // do not override in descendants! // All descendants should use DrawControl method instead of Paint. // DrawControl is not called between BeginUpdate and EndUpdate procedure DrawControl; virtual; // This method is called when control should be rendered (when some // general action occur which change "body" e.g. resize) procedure RenderControl; virtual;