Knowledge Base Alert December, 2015


VCL

FIREMONKEY

DEVELOPER TOOLS

Best wishes for a happy & prosperous New Year from the TMS team!



TMS software remains open during holiday season and support is standby for your most urgent questions.



TMS Cloud Pack:

Recurring events in Google calendars



The Recurrence and RecurringID properties of the TGCalendarItem are explained in the product manual PDF. Below you can find some extended information about these properties.

New recurring events:
Create a new event and simply assign a recurrence string to the Recurrence property and also fill in the relevant time zone in the TimeZone property. Then add the Event.

Example:

var
  li: TGCalendarItem;
begin
    li := AdvGCalendar1.Items.Add;
    li.Summary := 'Summary';
    li.Description := 'Description';
    li.Location := 'Location';
    li.Recurrence := 'RRULE:FREQ=DAILY;COUNT=5';
    li.TimeZone := 'Europe/Brussels';
    li.StartTime := dtStart;
    li.EndTime := dtEnd;
    li.CalendarID := sCalendarID;
    AdvGCalendar1.Add(li);

Existing recurring events:
A recurrent item consists of two types of events. The first is the parent event which contains the Recurrence string. The second are the instances of the recurrent item. By design, only the instances are retrieved when requesting a list of events. To retrieve the parent item separately you can use the RecurringID property value of one of the instances as the ItemID parameter for the GetItemById call.

TMS Cloud Pack: TAdvGDrive:

How to upload a file to a known folder without using GetDriveInfo



Call "SearchFolder" with the folder name as a parameter. If that returns true, the first item of the "Drive" collection contains the required folder. Then call "Upload" with the folder object and the filename of the file to upload as parameters.

Example:

if AdvGDrive.SearchFolder('FolderName') then
  AdvGDrive.Upload(AdvGDrive.Drive.Items[0], 'FileName.ext');

TAdvTrackBar:

How to draw a custom tickmark at thumb position



To draw a custom tickmark at thumb position, drop a default TAdvTrackBar on the form and add following code:

procedure TForm2.AdvTrackBar1Change(Sender: TObject); begin
  AdvTrackBar1.Invalidate;
end;

procedure TForm2.AdvTrackBar1DrawTick(Sender: TObject; Canvas: TCanvas;
  Location: TPoint; Position: Integer; TickPos: TTickMark; var Length:
Integer;
  var Color, TextColor: TColor; var Text: string; var DefaultDraw: Boolean); begin
  if Position = AdvTrackBar1.Position then
  begin
    DefaultDraw := false;
    Canvas.MoveTo(Location.X, Location.Y);
    Canvas.Pen.Color := cLRed;
    Canvas.Pen.Width := 3;
    Canvas.LineTo(Location.X, Location.Y + 10);
    Canvas.Pen.Width := 1;
    Canvas.Pen.Color := clBlack;
  end;
end;

This will draw at thumb position a think red tickmark:

TPlanner:

Inter Planner drag & drop



This sample project allows to perform direct & easy drag & drop of PlannerItems between two Planner instances



TMS WebGMaps:

How to add a custom JavaScript function with the OnInitHTML event



Below is an example of how you can add a custom JavaScript function with the OnInitHTML event. You can then call the function by using the ExecJScript call.

procedure TForm1.WebGMaps1InitHTML(Sender: TObject; var HTML: string); 
begin
  HTML := HTML + '<script>function sampleFunction(msg){alert(msg);}</script>';
end;

procedure TForm1.Button1Click(Sender: TObject); 
begin
  WebGMaps1.ExecJScript('sampleFunction("Hello World");'); 

end;

TTMSFMXPlanner:

How to have different colored lines between groups



The TTMSFMXPlanner supports custom drawing in various areas such as the group, timeline and grid area. The code below demonstrates how to draw lines to separate groups which cover multiple positions.

procedure TForm1.TMSFMXPlanner1AfterDrawCellVerticalLine(Sender: TObject;
  ACanvas: TCanvas; ARect: TRectF; ACol, ARow: Integer; AStartTime,
  AEndTime: TDateTime; APosition: Integer; AKind: TTMSFMXPlannerCacheItemKind);
begin
  ACanvas.StrokeThickness := 2;
  if ARow = 5 then 
  begin
    ACanvas.Stroke.Color := claRed;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;

  if ARow = 10 then 
  begin
    ACanvas.Stroke.Color := claBlue;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;

  if ARow = 15 then 
  begin
    ACanvas.Stroke.Color := claGreen;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;

  if ARow = 19 then 
  begin
    ACanvas.Stroke.Color := claOrange;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Bottom - 1), PointF(ARect.Right, ARect.Bottom - 1), 1);
  end;
end;

procedure TForm1.TMSFMXPlanner1AfterDrawGroup(Sender: TObject;
  ACanvas: TCanvas; ARect: TRectF; AGroup, AStartPosition,
  AEndPosition: Integer; AKind: TTMSFMXPlannerCacheItemKind);
begin
  ACanvas.StrokeThickness := 2;
  if AGroup in [1, 2, 3] then
  begin
    case AGroup of
      1: ACanvas.Stroke.Color := claRed;  
      2: ACanvas.Stroke.Color := claBlue; 
      3: ACanvas.Stroke.Color := claGreen; 
    end;

    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;
end;

procedure TForm1.TMSFMXPlanner1AfterDrawGroupEmptySpace(Sender: TObject;
  ACanvas: TCanvas; ARect: TRectF; ASpace: TTMSFMXPlannerGroupEmptySpace);
begin
  ACanvas.StrokeThickness := 2;
  if ASpace = pgesTopRight then
  begin
    ACanvas.Stroke.Color := claOrange;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;
end;

procedure TForm1.TMSFMXPlanner1AfterDrawPosition(Sender: TObject;
  ACanvas: TCanvas; ARect: TRectF; APosition: Integer;
  AKind: TTMSFMXPlannerCacheItemKind);
begin
  ACanvas.StrokeThickness := 2;
  if APosition = 5 then 
  begin
    ACanvas.Stroke.Color := claRed;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;

  if APosition = 10 then
  begin
    ACanvas.Stroke.Color := claBlue;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;

  if APosition = 15 then 
  begin
    ACanvas.Stroke.Color := claGreen;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;
end;

procedure TForm1.TMSFMXPlanner1AfterDrawPositionEmptySpace(Sender: TObject;
  ACanvas: TCanvas; ARect: TRectF; ASpace: TTMSFMXPlannerPositionEmptySpace);
begin
  ACanvas.StrokeThickness := 2;
  if ASpace = ppesTopRight then
  begin
    ACanvas.Stroke.Color := claOrange;
    ACanvas.DrawLine(PointF(ARect.Left, ARect.Top), PointF(ARect.Right, ARect.Top), 1);
  end;
end;

procedure TForm1.TMSFMXPlanner1Paint(Sender: TObject; Canvas: TCanvas;=const ARect: TRectF);
var
  r: TRectF;
begin
  Canvas.StrokeThickness := 2;
  r := TMSFMXPlanner1.GetContentClipRect;
  Canvas.Stroke.Color := claOrange;
  Canvas.DrawLine(PointF(0, r.Bottom - 0.5), PointF(r.Right, r.Bottom - 0.5), 1);
end;



TMSFMXSpeedButton:

How to change the Pressed Color



You can use the following code to to change the Pressed Color in TMSFMXSpeedButton:

procedure TForm1.TMSFMXSpeedButton1ApplyStyleLookup(Sender: TObject);
var
  I: Integer;
  c: TFMXObject;
  txt: TText;
  ca: TColorAnimation;
begin
  txt := TMSFMXSpeedButton1.GetText;
  txt.Color := claWhite;

  c := TMSFMXSpeedButton1.GetBackGround;
  for I := 0 to c.ChildrenCount - 1 do
  begin
    if c.Children[I] is TColorAnimation then
    begin
      ca := (c.Children[I] as TColorAnimation);
      if ca.Trigger = 'IsMouseOver=true;IsPressed=true' then
      begin
        ca.StartValue := claBlue;
        ca.StopValue := claGreen;
      end;
      if ca.Trigger = 'IsMouseOver=true;IsPressed=false' then
      begin
        ca.StartValue := claNull;
        ca.StopValue := claRed;
      end;
    end;
  end;
end;




TMSFMXNativeUITableView:

Adding an UIToolBarItem to the toolbar of an UITableView in iCL



The TTMSFMXNativeUITableView has a toolbar property that can be set to True. When adding an item, you can then add it to the TableViewController instead of the NavigationController. Below is the source code that demonstrates this.

unit UDemo;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, iOSApi.Foundation,
  FMX.TMSNativeUIBaseControl, FMX.TMSNativeUIView, FMX.TMSNativeUICore,
  FMX.TMSNativeUIViewController, FMX.TMSNativeUINavigationController, FMX.TMSNativeUIToolBar,
  MacApi.ObjectiveC, TypInfo, MacApi.ObjcRuntime, FMX.TMSNativeUITableView;

type
  IUIToolBarButtonEventHandler = interface(NSObject)
  ['{1ACF3DFA-A90B-4F06-ACF1-8A40076BC9ED}']
    procedure Click(Sender: Pointer); cdecl;
  end;

  TUIToolBarButtonEventHandler = class(TOCLocal)
  protected
    function GetObjectiveCClass: PTypeInfo; override;
  public
    procedure Click(Sender: Pointer); cdecl;
  end;

  TDemoForm = class(TForm)
    TMSFMXNativeUITableView1: TTMSFMXNativeUITableView;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FEventHandler: TUIToolBarButtonEventHandler;
    FHideButton: UIBarButtonItem;
  public
    { Public declarations }
  end;

var
  DemoForm: TDemoForm;

implementation

{$R *.fmx}

procedure TDemoForm.FormCreate(Sender: TObject);
begin
  FEventHandler := TUIToolBarButtonEventHandler.Create;
  FHideButton := TUIBarButtonItem.Wrap(TUIBarButtonItem.Wrap(TUIBarButtonItem.OCClass.alloc).initWithBarButtonSystemItem(integer(siBarButtonSystemItemAdd),
    FEventHandler.GetObjectID, sel_getUid('Click:')));

  TMSFMXNativeUITableView1.Options.ToolBar := True;
  TMSFMXNativeUITableView1.TableViewController.navigationItem.setRightBarButtonItem(FHideButton);
end;

{ TUIToolBarButtonEventHandler }

procedure TUIToolBarButtonEventHandler.Click(Sender: Pointer);
begin
  ShowMessage('clicked');
end;

function TUIToolBarButtonEventHandler.GetObjectiveCClass: PTypeInfo;
begin
  Result := TypeInfo(IUIToolBarButtonEventHandler);
end;

end.




TMS Aurelius:

Executing SQL statements directly with IDBConnection



You might have some situations where you want to execute an SQL statement directly in the database, bypassing the object manager. Of course you could use the database access component directly (FireDac, dbExpress, ADO, etc.). But in case you want to keep the code abstract when it comes to the database access layer, and benefit from existing Aurelius connection, you can use IDBConnection to do so.

Here is how you would do it:

uses {...}, Aurelius.Drivers.Interfaces;

var
  Statement: IDBStatement;

Statement := Manager.Connection.CreateStatement;
Statement.SetSQLCommand(TheSQLStatement);
Statement.Execute;

If the statement is queryable, you can retrieve results using ExecuteQuery method which returns an IDBResultSet interface:

var
  Statement: IDBStatement;
  ResultSet: IDBResultSet;

Statement := Manager.Connection.CreateStatement;
Statement.SetSQLCommand(TheSQLStatement);
ResultSet := Statement.ExecuteQuery;

while ResultSet.Next do
  Value := ResultSet.GetFieldValue(SomeFieldName);

Finally, for both types of commands you can set parameter values:

{...}
Params := TObjectList<TDBParam>.Create;
try
  Statement := Manager.Connection.CreateStatement; 
  Params.Add(TDBParam.Create(‘id', ftInteger, 15));
  Statement.SetSQLCommand(‘Delete from Customer Where Id = :id’);
  Statement.SetParams(Params);
  Statement.Execute;
finally
  Params.Free;
end;




Kind regards,
TMS software team
Email: info@tmssoftware.com
Web: http://www.tmssoftware.com
Support, FAQ & Manuals: http://www.tmssoftware.com/site/support.asp


Follow latest developments at tmssoftware.com


NOTICE: If you wish to unsubscribe from the TMS software Newsletter, please click here.