Watch, Follow, &
Connect with Us

Please visit our new home
community.embarcadero.com.


Welcome, Guest
Guest Settings
Help

Thread: Can anyone help convert Delphi to c++ builder?



Permlink Replies: 10 - Last Post: Feb 14, 2018 12:21 PM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Mark Richards

Posts: 42
Registered: 12/8/99
Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 4:34 AM
The following code is from a TCalendar (firemonkey) sample I found online, but it is written in Delphi

procedure TMainForm.UpdateEvents;
var
Events: TArray<TDateTime>;
Item: string;
I: Integer;
begin
SetLength(Events, LBEvents.Count);
for I := 0 to LBEvents.Count - 1 do
Events[I] := StrToDateTime(LBEvents.Items[I]);

Calendar1.Model.Data['Events'] := TValue.From<TArray<TDateTime>>(Events);
end;

LBEvents is a TListBox control

I really don't understand TArray or TValue
roca robin

Posts: 140
Registered: 9/10/06
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 9:14 AM   in response to: Mark Richards in response to: Mark Richards
Mark Richards wrote:
The following code is from a TCalendar (firemonkey) sample I found online, but it is written in Delphi

procedure TMainForm.UpdateEvents;
var
Events: TArray<TDateTime>;
Item: string;
I: Integer;
begin
SetLength(Events, LBEvents.Count);
for I := 0 to LBEvents.Count - 1 do
Events[I] := StrToDateTime(LBEvents.Items[I]);

Calendar1.Model.Data['Events'] := TValue.From<TArray<TDateTime>>(Events);
end;

LBEvents is a TListBox control

I really don't understand TArray or TValue


I'd like to help if I'm an expert for c++ builder,
but I'm just like you beginning to learn from Old Delphi, take a look of the codes I got.
I hope it helps a little.
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#include <System.SysUtils.hpp> //Important for using dates
#include <DateUtils.hpp>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
//

typedef DynamicArray< TDateTime > TArray;
TArray Events;
Events.set_length(LBEvents->Count);
//or
Events.Length = LBEvents->Count;

for (int I=0; I < LBEvents->Count; I++) {

//StrToDateTime(L"month/day/year hours1to24:minutes1to59:seconds1to59");
Events[I] = StrToDateTime(L"12/25/2018 23:59:59"); //so it's ok to use like this...

String tlbstring;
//tlbstring = L"" + LBEvents->Items[I].Text; //access violation

//ShowMessage(LBEvents->Items[I].Text); //error after

//Events[I] = StrToDateTime(tlbstring); //error after
ListBox1->Items->Add(Events[I]);
}

//Calendar1->Model->Data['Events'] := TValue->From<TArray<TDateTime>>(Events); //not sure, don't know yet...

//
}
//---------------------------------------------------------------------------

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 10:01 AM   in response to: roca robin in response to: roca robin
roca robin wrote:

typedef DynamicArray< TDateTime > TArray;

The RTL already has a TArray type. I would suggest using a more unique
name, such as TDateTimeArray.

Events.set_length(LBEvents->Count);
//or
Events.Length = LBEvents->Count;

set_length() is the setter for the Length property. Use the property,
not the setter directly.

//StrToDateTime(L"month/day/year
hours1to24:minutes1to59:seconds1to59");
Events[I] = StrToDateTime(L"12/25/2018 23:59:59"); //so it's ok to
use like this...

Note that StrToDateTime() has an optional TFormatSettings parameter so
you can specify the order of the various date/time components.

//tlbstring = L"" + LBEvents->Items[I].Text; //access violation

//ShowMessage(LBEvents->Items[I].Text); //error after

The Items property getter returns a TStrings* pointer.

In Delphi, TStrings has a 'default' Strings[] property, so Items[I] is
actually accessing Items.Strings[I].

C++ doesn't have a concept of 'default' properties, so Items[I] is
performing pointer arithmetic on the TStrings* pointer itself, not
accessing the Strings[] property. You would have to access the
Strings[] property explicitly:

LBEvents->Items->Strings[I]


Or, you can dereference the TStrings* pointer to access the underlying
TStrings object, which has a helper operator[] provided by the Delphi
compiler for accessing the 'default' Strings[] property using C++
syntax that is closer to the Delphi syntax:

(*(LBEvents->Items))[I]

//Calendar1->Model->Data['Events'] :=
TValue->From<TArray<TDateTime>>(Events); //not sure, don't know yet...

String literals in Delphi use single quotes, whereas they use double
quotes in C++:

Data["Events"]


TValue::From() is a static method, so use '::' instead of '->' to
access it:

TValue::From<DynamicArray<TDateTime>>(Events);


Or, you can simply let the C++ compiler deduce the template paramter
for you:

TValue::From(Events);

--
Remy Lebeau (TeamB)

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 9:47 AM   in response to: Mark Richards in response to: Mark Richards
Mark Richards wrote:

The following code is from a TCalendar (firemonkey) sample I found
online, but it is written in Delphi

Here is a C++ translation:

#include <System.SysUtils.hpp>
#include <System.Rtti.hpp>
 
void __fastcall TMainForm::UpdateEvents()
{
    DynamicArray<TDateTime> Events;
    String Item;
 
    Events.Length = LBEvents->Count;
    for(int I = 0; I < LBEvents->Count; ++I)
        Events[I] = StrToDateTime(LBEvents->Items->Strings[I]);
 
    Calendar1->Model->Data[_D("Events")] = TValue::From(Events);
}


--
Remy Lebeau (TeamB)
roca robin

Posts: 140
Registered: 9/10/06
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 10:51 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Mark Richards wrote:

The following code is from a TCalendar (firemonkey) sample I found
online, but it is written in Delphi

Here is a C++ translation:

#include <System.SysUtils.hpp>
#include <System.Rtti.hpp>
 
void __fastcall TMainForm::UpdateEvents()
{
    DynamicArray<TDateTime> Events;
    String Item;
 
    Events.Length = LBEvents->Count;
    for(int I = 0; I < LBEvents->Count; ++I)
        Events[I] = StrToDateTime(LBEvents->Items->Strings[I]);
 
    Calendar1->Model->Data[_D("Events")] = TValue::From(Events);
}


--
Remy Lebeau (TeamB)

I mess this:
->Strings[I]

I tried different properties, like .Text .ToString(), failed.
the property is common from Delphi, but it's different when an expert answers here,
so Tough!, lol

p.S
Calendar1->Model->Data[_D("Events")] = TValue::From(Events);
Model is not a member of the Calendar1 it said

just trying...
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 13, 2018 11:29 AM   in response to: roca robin in response to: roca robin
roca robin wrote:

Model is not a member of the Calendar1 it said

It is in 10.0 Seattle and later:

http://docwiki.embarcadero.com/Libraries/en/FMX.Calendar.TCustomCalendar.Model

--
Remy Lebeau (TeamB)
Mark Richards

Posts: 42
Registered: 12/8/99
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 14, 2018 1:27 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Many Thanks Remy and Roca, really appreciate this,

Remy Lebeau (TeamB) wrote:
Mark Richards wrote:

The following code is from a TCalendar (firemonkey) sample I found
online, but it is written in Delphi

Here is a C++ translation:

#include <System.SysUtils.hpp>
#include <System.Rtti.hpp>
 
void __fastcall TMainForm::UpdateEvents()
{
    DynamicArray<TDateTime> Events;
    String Item;
 
    Events.Length = LBEvents->Count;
    for(int I = 0; I < LBEvents->Count; ++I)
        Events[I] = StrToDateTime(LBEvents->Items->Strings[I]);
 
    Calendar1->Model->Data[_D("Events")] = TValue::From(Events);
}


--
Remy Lebeau (TeamB)
Mark Richards

Posts: 42
Registered: 12/8/99
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 14, 2018 8:59 AM   in response to: Mark Richards in response to: Mark Richards
Ok, I implemeted Remy's solution...

DynamicArray<TDateTime> Events;
Events.Length = LBEvents->Count;
for (int I = 0; I < LBEvents->Count; I++)
Events[I] = StrToDateTime(LBEvents->Items->Strings[I]);

Calendar1->Model->Data[_D("Events")] = TValue::From(Events);

It compiles fine, but the control receiving doesn't recognise the type of value passed, the code below is the code which draws the results of the array it recieves, but if I run in debug, the line in BOLD doesn't see the DynamicArray passed

procedure TStyledCalendarWithHolidayDays.PaintEvents;
var
Events: TArray<TDateTime>;
Event: TDateTime;
DayItem: TListBoxItem;
begin
if Model.Data['Events'].IsType<TArray<TDateTime>> then
begin
Events := Model.Data['Events'].AsType<TArray<TDateTime>>;
for Event in Events do
begin
DayItem := TryFindDayItem(Event);
if DayItem <> nil then
CreateBackground(DayItem, Model.EventsColor);
end;
end;
end;
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 14, 2018 10:07 AM   in response to: Mark Richards in response to: Mark Richards
Mark Richards wrote:

It compiles fine, but the control receiving doesn't recognise the
type of value passed, the code below is the code which draws the
results of the array it recieves, but if I run in debug, the line
in BOLD doesn't see the DynamicArray passed

Sounds like the C++ code and the Delphi code are not sharing the same
RTL RTTI. What do Model.Data['Events'].TypeInfo.Name and
Model.Data['Events'].ToString report?

--
Remy Lebeau (TeamB)
Mark Richards

Posts: 42
Registered: 12/8/99
Re: Can anyone help convert Delphi to c++ builder?
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 14, 2018 9:20 AM   in response to: Mark Richards in response to: Mark Richards
Perhaps it would be easier to say why I want a conversion.
I want to use the TCalendar control (FMX) in a windows/android platform project where by I can assign highlighted days to the displayed Calendar. I found a great example wirtten in Delphi, but because it uses a Delphi frm object, and i have already written a massive chunk of C++ code on a single Delphi Form, I simply wanted to drop the TCalendar control on the C++ TForm ansd do the same as Delphi sample porject does. But I am lost with what delphi is actually doing.

The Delphi code is in three sections, a form and two .pas files....

FIle: FMX.Calendar.Helpers.pas


unit FMX.Calendar.Helpers;
 
interface
 
uses
  System.Rtti, FMX.Calendar, System.UITypes;
 
type
  TCalendarModelHelpers = class helper for TCalendarModel
  public const
    DefaultEventsColor = $FFB8E3AB;
    DefaultWeekendsColor = $FFFEB1AF;
  private
    function GetShowEvents: Boolean;
    procedure SetShowEvents(const Value: Boolean);
    function GetShowWeekends: Boolean;
    procedure SetShowWeekends(const Value: Boolean);
    function GetEventsColor: TAlphaColor;
    procedure SetEventsColor(const Value: TAlphaColor);
    function GetWeekendsColor: TAlphaColor;
    procedure SetWeekendsColor(const Value: TAlphaColor);
  public
    property ShowEvents: Boolean read GetShowEvents write SetShowEvents;
    property ShowWeekends: Boolean read GetShowWeekends write SetShowWeekends;
    property EventsColor: TAlphaColor read GetEventsColor write SetEventsColor;
    property WeekendsColor: TAlphaColor read GetWeekendsColor write SetWeekendsColor;
  end;
 
implementation
 
{ TCalendarModelHelpers }
 
function TCalendarModelHelpers.GetEventsColor: TAlphaColor;
var
  Value: TValue;
begin
  Value := Data['EventsColor'];
  if Value.IsEmpty or Value.TryAsType<TAlphaColor>(Result) then
    Result := DefaultEventsColor;
end;
 
function TCalendarModelHelpers.GetShowEvents: Boolean;
begin
  Result := Data['ShowEvents'].AsBoolean;
end;
 
function TCalendarModelHelpers.GetShowWeekends: Boolean;
begin
  Result := Data['ShowWeekends'].AsBoolean;
end;
 
function TCalendarModelHelpers.GetWeekendsColor: TAlphaColor;
var
  Value: TValue;
begin
  Value := Data['WeekendsColor'];
  if Value.IsEmpty or not Value.TryAsType<TAlphaColor>(Result) then
    Result := DefaultWeekendsColor;
end;
 
procedure TCalendarModelHelpers.SetEventsColor(const Value: TAlphaColor);
begin
  Data['EventsColor'] := TValue.From<TAlphaColor>(Value);
end;
 
procedure TCalendarModelHelpers.SetShowEvents(const Value: Boolean);
begin
  Data['ShowEvents'] := Value;
end;
 
procedure TCalendarModelHelpers.SetShowWeekends(const Value: Boolean);
begin
  Data['ShowWeekends'] := Value;
end;
 
procedure TCalendarModelHelpers.SetWeekendsColor(const Value: TAlphaColor);
begin
  Data['WeekendsColor'] := TValue.From<TAlphaColor>(Value);
end;
 
end.
 


File:FMX.CalendarHolidayDays.Style.pas

unit FMX.CalendarHolidayDays.Style;
 
interface
 
uses
  System.UITypes, FMX.Calendar, FMX.Calendar.Style, FMX.Controls.Model, FMX.Presentation.Messages, FMX.Controls.Presentation,
  FMX.ListBox;
 
type
 
  TStyledCalendarWithHolidayDays = class(TStyledCalendar)
  protected
    { Messages from Model }
    /// <summary>Notification about changing value of DataSource of a model of <c>PresentedControl</c> </summary>
    procedure MMDataChanged(var AMessage: TDispatchMessageWithValue<TDataRecord>); message MM_DATA_CHANGED;
  protected
    procedure FillDays; override;
 
    procedure CreateBackground(ADayItem: TListBoxItem; const AColor: TAlphaColor); virtual;
    procedure RemoveDaysBackgrounds;
 
    procedure PaintWeekends; virtual;
    procedure PaintEvents; virtual;
  end;
 
implementation
 
uses
  System.SysUtils, System.DateUtils, System.Math, System.Types, FMX.Presentation.Factory, FMX.Controls, FMX.Presentation.Style, FMX.Types, FMX.Objects, FMX.Graphics, FMX.Calendar.Helpers;
 
{ TStyledCalendarWithHolidayDays }
 
procedure TStyledCalendarWithHolidayDays.CreateBackground(ADayItem: TListBoxItem; const AColor: TAlphaColor);
var
  Hightlight: TCircle;
begin
  Hightlight := TCircle.Create(nil);
  Hightlight.Name := 'HightlightBackground';
  Hightlight.HitTest := False;
  Hightlight.Align := TAlignLayout.Contents;
  Hightlight.Margins.Rect := TRectF.Create(3, 3, 3, 3);
  Hightlight.Stroke.Kind := TBrushKind.None;
  Hightlight.Fill.Color := AColor;
  ADayItem.InsertObject(0, Hightlight);
end;
 
procedure TStyledCalendarWithHolidayDays.FillDays;
begin
  inherited;
  // Paint holidays
  RemoveDaysBackgrounds;
  if Model.ShowWeekends then
    PaintWeekends;
  if Model.ShowEvents then
    PaintEvents;
end;
 
procedure TStyledCalendarWithHolidayDays.MMDataChanged(var AMessage: TDispatchMessageWithValue<TDataRecord>);
begin
  if SameText(AMessage.Value.Key, 'ShowWeekends') or
     SameText(AMessage.Value.Key, 'ShowEvents') or
     SameText(AMessage.Value.Key, 'EventsColor') or
     SameText(AMessage.Value.Key, 'WeekendsColor') or
     SameText(AMessage.Value.Key, 'Events') then
    FillCalendar
  else
    inherited;
end;
 
procedure TStyledCalendarWithHolidayDays.PaintEvents;
var
  Events: TArray<TDateTime>;
  Event: TDateTime;
  DayItem: TListBoxItem;
begin
  if Model.Data['Events'].IsType<TArray<TDateTime>> then
  begin
    Events := Model.Data['Events'].AsType<TArray<TDateTime>>;
    for Event in Events do
    begin
      DayItem := TryFindDayItem(Event);
      if DayItem <> nil then
        CreateBackground(DayItem, Model.EventsColor);
    end;
  end;
end;
 
procedure TStyledCalendarWithHolidayDays.PaintWeekends;
var
  DayItem: TListBoxItem;
  FirstDate: TDateTime;
  FirstDay: Word;
  LWeek: Integer;
  WeekendDate: TDateTime;
  FirstWeekendDay: Integer;
  MonthDaysCount: Word;
  SaturdayDay: Word;
  SundayDay: Word;
begin
  FirstDate := StartOfTheMonth(Self.Date);
  FirstDay := DayOfTheWeek(FirstDate);
  MonthDaysCount := DaysInMonth(FirstDate);
  FirstWeekendDay := DaysPerWeek - FirstDay + 1;
 
  for LWeek := 0 to 4 do
  begin
    // Saturday
    SaturdayDay := FirstWeekendDay - 1 + LWeek * DaysPerWeek;
    if InRange(SaturdayDay, 1, MonthDaysCount) then
    begin
      WeekendDate := RecodeDay(FirstDate, SaturdayDay);
      DayItem := TryFindDayItem(WeekendDate);
      if DayItem <> nil then
        CreateBackground(DayItem, Model.WeekendsColor);
    end;
    // Sunday
    SundayDay := FirstWeekendDay + LWeek * DaysPerWeek;
    if InRange(SundayDay, 1, MonthDaysCount) then
    begin
      WeekendDate := RecodeDay(FirstDate, SundayDay);
      DayItem := TryFindDayItem(WeekendDate);
      if DayItem <> nil then
        CreateBackground(DayItem, Model.WeekendsColor);
    end;
  end;
end;
 
procedure TStyledCalendarWithHolidayDays.RemoveDaysBackgrounds;
 
  procedure RemoveBackground(ADayItem: TListBoxItem);
  var
    I: Integer;
    Background: TControl;
  begin
    for I := ADayItem.ControlsCount - 1 downto 0 do
      if ADayItem.Controls[I].Name = 'HightlightBackground' then
      begin
        Background := ADayItem.Controls[I];
        Background.Parent := nil;
        Background.Free;
      end;
  end;
 
var
  I: Integer;
  DayItem: TListBoxItem;
begin
  if Days <> nil then
    for I := 0 to Days.Count - 1 do
    begin
      DayItem := Days.ListItems[I];
      RemoveBackground(DayItem);
    end;
end;
 
initialization
  TPresentationProxyFactory.Current.Replace(TCalendar, TControlType.Styled, TStyledPresentationProxy<TStyledCalendarWithHolidayDays>);
finalization
  TPresentationProxyFactory.Current.Replace(TCalendar, TControlType.Styled, TStyledPresentationProxy<TStyledCalendar>);
end.
 


File: MainFrm.pas

unit MainFrm;
 
interface
 
uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Calendar, FMX.Controls.Presentation, FMX.MultiView, FMX.DateTimeCtrls, FMX.Layouts, FMX.ListBox;
 
type
  TMainForm = class(TForm)
    MultiView1: TMultiView;
    Calendar1: TCalendar;
    CBDisplayEvents: TCheckBox;
    CBDisplayWeekends: TCheckBox;
    LBEvents: TListBox;
    Layout1: TLayout;
    GroupBox1: TGroupBox;
    DEEvent: TDateEdit;
    BtnAddEvents: TButton;
    BtnDeleteEvents: TButton;
    Layout2: TLayout;
    BtnCheckPresentationName: TButton;
    procedure CBDisplayWeekendsChange(Sender: TObject);
    procedure CBDisplayEventsChange(Sender: TObject);
    procedure BtnAddEventsClick(Sender: TObject);
    procedure BtnDeleteEventsClick(Sender: TObject);
    procedure BtnCheckPresentationNameClick(Sender: TObject);
  private
    procedure UpdateEvents;
  public
    { Public declarations }
  end;
 
var
  MainForm: TMainForm;
 
implementation
 
{$R *.fmx}
 
uses
  FMX.Calendar.Helpers, System.Rtti;
 
procedure TMainForm.BtnAddEventsClick(Sender: TObject);
begin
  LBEvents.Items.Add(DEEvent.Text);
  UpdateEvents;
end;
 
procedure TMainForm.BtnDeleteEventsClick(Sender: TObject);
begin
  if LBEvents.ItemIndex <> -1 then
    LBEvents.Items.Delete(LBEvents.ItemIndex);
  UpdateEvents;
end;
 
procedure TMainForm.BtnCheckPresentationNameClick(Sender: TObject);
begin
  if Calendar1.Presentation <> nil then
    ShowMessage(Calendar1.Presentation.ClassName)
  else
    ShowMessage('TCalendar doesn''t have presentation');
end;
 
procedure TMainForm.CBDisplayEventsChange(Sender: TObject);
begin
  Calendar1.Model.ShowEvents := CBDisplayEvents.IsChecked;
end;
 
procedure TMainForm.CBDisplayWeekendsChange(Sender: TObject);
begin
  Calendar1.Model.ShowWeekends := CBDisplayWeekends.IsChecked;
end;
 
procedure TMainForm.UpdateEvents;
var
  Events: TArray<TDateTime>;
  Item: string;
  I: Integer;
begin
  SetLength(Events, LBEvents.Count);
  for I := 0 to LBEvents.Count - 1 do
    Events[I] := StrToDateTime(LBEvents.Items[I]);
 
  Calendar1.Model.Data['Events'] := TValue.From<TArray<TDateTime>>(Events);
end;
 
end.
 


*File: MainFrm.fmx *


object MainForm: TMainForm
  Left = 0
  Top = 0
  Caption = 'TCalendar: Calendar with highlighting days'
  ClientHeight = 354
  ClientWidth = 554
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object MultiView1: TMultiView
    Mode = Panel
    Padding.Left = 5.000000000000000000
    Padding.Top = 5.000000000000000000
    Padding.Right = 5.000000000000000000
    Padding.Bottom = 5.000000000000000000
    Size.Width = 183.000000000000000000
    Size.Height = 354.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 0
    object Layout1: TLayout
      Align = Top
      Position.Y = 22.000000000000000000
      Size.Width = 172.000000000000000000
      Size.Height = 81.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
      object CBDisplayEvents: TCheckBox
        Position.X = 8.000000000000000000
        Position.Y = 40.000000000000000000
        TabOrder = 0
        Text = 'Display Events'
        OnChange = CBDisplayEventsChange
      end
      object CBDisplayWeekends: TCheckBox
        Position.X = 8.000000000000000000
        Position.Y = 16.000000000000000000
        TabOrder = 1
        Text = 'Display Weekends'
        OnChange = CBDisplayWeekendsChange
      end
    end
    object GroupBox1: TGroupBox
      Align = Client
      Padding.Left = 10.000000000000000000
      Padding.Top = 50.000000000000000000
      Padding.Right = 10.000000000000000000
      Padding.Bottom = 10.000000000000000000
      Size.Width = 172.000000000000000000
      Size.Height = 241.000000000000000000
      Size.PlatformDefault = False
      Text = 'Events'
      TabOrder = 1
      object LBEvents: TListBox
        Align = Client
        Size.Width = 152.000000000000000000
        Size.Height = 181.000000000000000000
        Size.PlatformDefault = False
        TabOrder = 0
        DisableFocusEffect = True
        ItemHeight = 25.000000000000000000
        DefaultItemStyles.ItemStyle = ''
        DefaultItemStyles.GroupHeaderStyle = ''
        DefaultItemStyles.GroupFooterStyle = ''
        Viewport.Width = 148.000000000000000000
        Viewport.Height = 177.000000000000000000
      end
      object DEEvent: TDateEdit
        Date = 42261.000000000000000000
        Position.X = 10.000000000000000000
        Position.Y = 24.000000000000000000
        Size.Width = 87.000000000000000000
        Size.Height = 22.000000000000000000
        Size.PlatformDefault = False
        TabOrder = 1
      end
      object BtnAddEvents: TButton
        Position.X = 96.000000000000000000
        Position.Y = 24.000000000000000000
        Size.Width = 35.000000000000000000
        Size.Height = 22.000000000000000000
        Size.PlatformDefault = False
        StyleLookup = 'additembutton'
        TabOrder = 2
        Text = 'BtnAddEvents'
        OnClick = BtnAddEventsClick
      end
      object BtnDeleteEvents: TButton
        Position.X = 128.000000000000000000
        Position.Y = 24.000000000000000000
        Size.Width = 35.000000000000000000
        Size.Height = 22.000000000000000000
        Size.PlatformDefault = False
        StyleLookup = 'deleteitembutton'
        TabOrder = 3
        Text = 'BtnDeleteEvents'
        OnClick = BtnDeleteEventsClick
      end
    end
    object BtnCheckPresentationName: TButton
      Align = Top
      Size.Width = 172.000000000000000000
      Size.Height = 22.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 2
      Text = 'Check Presentation Name'
      OnClick = BtnCheckPresentationNameClick
    end
  end
  object Layout2: TLayout
    Align = Client
    Size.Width = 371.000000000000000000
    Size.Height = 354.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 1
    object Calendar1: TCalendar
      Align = Center
      Date = 42261.000000000000000000
      Size.Width = 235.000000000000000000
      Size.Height = 194.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
    end
  end
end
 


And the project file...


program CalendarHolidayDaysDemo;
 
uses
  System.StartUpCopy,
  FMX.Forms,
  MainFrm in 'MainFrm.pas' {Form18},
  FMX.CalendarHolidayDays.Style in 'FMX.CalendarHolidayDays.Style.pas',
  FMX.Calendar.Helpers in 'FMX.Calendar.Helpers.pas';
 
{$R *.res}
 
begin
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;
end.
 

I have success fully created a c++ form with the controls on, and it appears to be looking at the .pas FMX files above,but the Calendar1.Model.ShowWeekends property could not be found in C++ so had to be converted like following...

Delphi code


 
procedure TMainForm.CBDisplayWeekendsChange(Sender: TObject);
begin
  Calendar1.Model.ShowWeekends := CBDisplayWeekends.IsChecked;
end;


C++ code conversion

void __fastcall TMainForm::CBDisplayWeekendsChange(TObject *Sender)
{
	Calendar1->Model->Data[_D("ShowWeekends")] = TValue::From(CBDisplayWeekends->IsChecked);
}
 


In my C++ project I can click the Checkbox Display Weekends and the control shows Weekends highlighted, but nothing happens when Display Events is clicked as the DynamicArray just isn't picked up in the Model

Edited by: Mark Richards on Feb 14, 2018 9:38 AM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Can anyone help convert Delphi to c++ builder? [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 14, 2018 12:21 PM   in response to: Mark Richards in response to: Mark Richards
Mark Richards wrote:

Perhaps it would be easier to say why I want a conversion.
...
But I am lost with what delphi is actually doing.

The Delphi code is deriving a custom component from TStyledCalendar,
and then registering it with the Presentation system. It is using a
class helper
(http://docwiki.embarcadero.com/RADStudio/en/Class_and_Record_Helpers_(D
elphi)) to add extra functionality to the default TCalendar Model
without actually modifying the Model class itself or deriving from it.

C++ doesn't support class helpers, but you can do something similar
using an ordinary accessor class instead (as long as you don't need to
access private internal members, that is).

For example, the Delphi code translated to C++ would look something
like this:

#include <System.Rtti.hpp>
#include <FMX.Calendar.hpp>
#include <System.UITypes.hpp>
 
class TCalendarModelHelpers : public TCalendarModel
{
public:
    static const TAlphaColor DefaultEventsColor = 0xFFB8E3AB;
    static const TAlphaColor DefaultWeekendsColor = 0xFFFEB1AF;
private:
    bool __fastcall GetShowEvents();
    void __fastcall SetShowEvents(const bool Value);
    bool __fastcall GetShowWeekends();
    void __fastcall SetShowWeekends(const bool Value);
    TAlphaColor __fastcall GetEventsColor();
    void __fastcall SetEventsColor(const TAlphaColor Value);
    TAlphaColor __fastcall GetWeekendsColor();
    void __fastcall SetWeekendsColor(const TAlphaColor Value);
public:
    __property bool ShowEvents = {read=GetShowEvents,
write=SetShowEvents};
    __property bool ShowWeekends = {read=GetShowWeekends,
write=SetShowWeekends};
    __property TAlphaColor EventsColor = {read=GetEventsColor,
write=SetEventsColor};
    __property TAlphaColor WeekendsColor = {read=GetWeekendsColor,
write=SetWeekendsColor};
};


TAlphaColor __fastcall TCalendarModelHelpers::GetEventsColor()
{
    TAlphaColor Result;
    TValue Value = Data[_D("EventsColor")];
    if (Value.IsEmpty() || !Value.TryAsType<TAlphaColor>(Result))
        Result = DefaultEventsColor;
    return Result;
}
 
bool ___fastcall TCalendarModelHelpers::GetShowEvents()
{
    return Data[_D("ShowEvents")].AsBoolean();
}
 
bool __fastcall TMyCalendarModelHelper::GetShowWeekends()
{
    return Data[_D("ShowWeekends")].AsBoolean();
}
 
TAlphaColor __fastcall TCalendarModelHelpers::GetWeekendsColor()
{
    TAlphaColor Result;
    TValue Value = Data[_D("WeekendsColor")];
    if (Value.IsEmpty() || !Value.TryAsType<TAlphaColor>(Result))
        Result = DefaultWeekendsColor;
    return Result;
}
 
void __fastcall TCalendarModelHelpers::SetEventsColor(const 
TAlphaColor Value)
{
    Data[_D("EventsColor")] = TValue::From<TAlphaColor>(Value);
}
 
void __fastcall TCalendarModelHelpers::SetShowEvents(const bool Value)
{
    Data[_D("ShowEvents")] = Value;
}
 
void __fastcall TCalendarModelHelpers::SetShowWeekends(const bool Value)
{
    Data[_D("ShowWeekends")] = Value;
}
 
void __fastcall TCalendarModelHelpers::SetWeekendsColor(const
TAlphaColor Value)
{
    Data[_D("WeekendsColor")] = TValue::From<TAlphaColor>(Value);
}


#include <System.UITypes.hpp>
#include <FMX.Calendar.hpp>
#include <FMX.Calendar.Style.hpp>
#include <FMX.Controls.Model.hpp>
#include <FMX.Presentation.Messages.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.ListBox.hpp>
 
class TStyledCalendarWithHolidayDays : public TStyledCalendar
{
    typedef TStyledCalendar inherited;
protected:
    // Messages from Model
    void __fastcall
MMDataChanged(TDispatchMessageWithValue<TDataRecord> &AMessage);
protected:
    void __fastcall FillDays();
 
    virtual void __fastcall CreateBackground(TListBoxItem *ADayItem,
const TAlphaColor AColor);
    void __fastcall RemoveDaysBackgrounds();
 
    virtual void __fastcall PaintWeekends();
    virtual void __fascall PaintEvents();
 
public:
    __fastcall TStyledCalendarWithHolidayDays(TComponent* AOwner);
 
    BEGIN_MESSAGE_MAP
        MESSAGE_HANDLER(MM_DATA_CHANGED,
TDispatchMessageWithValue<TDataRecord>, MMDataChanged);
    END_MESSAGE_MAP(TStyledCalendar)
};


#include <System.SysUtils.hpp>
#include <System.DateUtils.hpp>
#include <System.Math.hpp>
#include <System.Types.hpp>
#include <FMX.Presentation.Factory.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Presentation.Style.hpp>
#include <FMX.Types.hpp>
#include <FMX.Objects.hpp>
#include <FMX.Graphics.hpp>
//#include <FMX.Calendar.Helpers.hpp>
 
__fastcall
TStyledCalendarWithHolidayDays::TStyledCalendarWithHolidayDays(TComponen
t* AOwner)
    : TStyledCalendar(AOwner)
{
}
 
void __fastcall
TStyledCalendarWithHolidayDays::CreateBackground(TListBoxItem
*ADayItem, const TAlphaColor AColor)
{
    TCircle *Hightlight = new TCircle(NULL);
    Hightlight->Name = L"HightlightBackground";
    Hightlight->HitTest = false;
    Hightlight->Align = TAlignLayout::Contents;
    Hightlight->Margins->Rect = TRectF(3, 3, 3, 3);
    Hightlight->Stroke->Kind = TBrushKind::None;
    Hightlight->Fill->Color = AColor;
    ADayItem->InsertObject(0, Hightlight);
}
 
void __fastcall TStyledCalendarWithHolidayDays::FillDays()
{
    inherited::FillDays();
    // Paint holidays
    RemoveDaysBackgrounds();
    if (((TCalendarModelHelpers*)Model)->ShowWeekends)
        PaintWeekends();
    if (((TCalendarModelHelpers*)Model)->ShowEvents)
        PaintEvents();
}
 
void __fastcall
TStyledCalendarWithHolidayDays::MMDataChanged(TDispatchMessageWithValue<
TDataRecord> &AMessage)
{
    if (SameText(AMessage.Value.Key, _D("ShowWeekends")) ||
        SameText(AMessage.Value.Key, _D("ShowEvents")) ||
        SameText(AMessage.Value.Key, _D("EventsColor")) ||
        SameText(AMessage.Value.Key, _D("WeekendsColor")) ||
        SameText(AMessage.Value.Key, _D("Events")))
    {
        FillCalendar();
    }
    else
        inherited::Dispatch(&AMessage);
}
 
void __fastcall TStyledCalendarWithHolidayDays::PaintEvents()
{
    TValue Value = Model->Data[_D("Events")];
    if (Value.IsType<DynamicArray<TDateTime>>())
    {
        DynamicArray<TDateTime> Events =
Value.AsType<DynamicArray<TDateTime>>();
        for(TDateTime Event : Events)
        {
            TListBoxItem *DayItem = TryFindDayItem(Event);
            if (DayItem)
                CreateBackground(DayItem,
((TCalendarModelHelpers*)Model)->EventsColor);
        }
    }
}
 
void __fastcall TStyledCalendarWithHolidayDays::PaintWeekends()
{
    TListBoxItem *DayItem;
    TDateTime FirstDate = StartOfTheMonth(this->Date);
    Word FirstDay = DayOfTheWeek(FirstDate);
    TDateTime WeekendDate;
    int FirstWeekendDay = DaysPerWeek - FirstDay + 1;
    Word MonthDaysCount = DaysInMonth(FirstDate);
    Word SaturdayDay;
    Word SundayDay;
 
    for(int LWeek = 0; LWeek <= 4; ++LWeek)
    {
        // Saturday
        SaturdayDay = FirstWeekendDay - 1 + LWeek * DaysPerWeek;
        if (InRange(SaturdayDay, 1, MonthDaysCount))
        {
            WeekendDate = RecodeDay(FirstDate, SaturdayDay);
            DayItem = TryFindDayItem(WeekendDate);
            if (DayItem)
                CreateBackground(DayItem,
((TCalendarModelHelpers*)Model)->WeekendsColor);
        }
        // Sunday
        SundayDay = FirstWeekendDay + LWeek * DaysPerWeek;
        if (InRange(SundayDay, 1, MonthDaysCount))
        {
            WeekendDate = RecodeDay(FirstDate, SundayDay);
            DayItem = TryFindDayItem(WeekendDate);
            if (DayItem)
                CreateBackground(DayItem,
((TCalendarModelHelpers*)Model)->WeekendsColor);
        }
    }
}
 
static void __fastcall RemoveBackground(TListBoxItem *ADayItem)
{
    for(int I = ADayItem->ControlsCount - 1; I >= 0; --i)
    {
        if (ADayItem->Controls[I]->Name == _D("HightlightBackground"))
        {
            TControl *Background = ADayItem->Controls[I];
            Background->Parent = NULL;
            delete Background;
        }
    }
}
 
void __fastcall TStyledCalendarWithHolidayDays::RemoveDaysBackgrounds()
{
    if (Days)
    {
        for(int I = 0; I < Days->Count; ++I)
        {
            TListBoxItem *DayItem = Days->ListItems[I];
            RemoveBackground(DayItem);
        }
    }
}
 
void Init()
{
    TPresentationProxyFactory::Current->Replace(__classid(TCalendar),
TControlType::Styled,
__classid(TStyledPresentationProxy<TStyledCalendarWithHolidayDays>));
}
#pragma startup Init
 
void Cleanup()
{
    TPresentationProxyFactory::Current->Replace(__classid(TCalendar),
TControlType::Styled,
__classid(TStyledPresentationProxy<TStyledCalendar>));
}
#pragma exit Cleanup


#include <System.SysUtils.hpp>
#include <System.Types.hpp>
#include <System.UITypes.hpp>
#include <System.Classes.hpp>
#include <System.Variants.hpp>
#include <FMX.Types.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Graphics.hpp>
#include <FMX.Dialogs.hpp>
#include <FMX.StdCtrls.hpp>
#include <FMX.Calendar.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.MultiView.hpp>
#include <FMX.DateTimeCtrls.hpp>
#include <FMX.Layouts.hpp>
#include <FMX.ListBox.hpp>
 
class TMainForm : public TForm
{
__published:
    TMultiView *MultiView1;
    TCalendar *Calendar1;
    TCheckBox *CBDisplayEvents;
    TCheckBox *CBDisplayWeekends;
    TListBox *LBEvents;
    TLayout *Layout1;
    TGroupBox *GroupBox1;
    TDateEdit *DEEvent;
    TButton *BtnAddEvents;
    TButton *BtnDeleteEvents;
    TLayout *Layout2;
    TButton *BtnCheckPresentationName;
    void __fastcall CBDisplayWeekendsChange(TObject *Sender);
    void __fastcall CBDisplayEventsChange(TObject *Sender);
    void __fastcall BtnAddEventsClick(TObject *Sender);
    void __fastcall BtnDeleteEventsClick(TObject *Sender);
    void __fastcall BtnCheckPresentationNameClick(TObject *Sender);
private:
    void __fastcall UpdateEvents();
public:
    // Public declarations
};
 
extern TMainForm *MainForm;


#pragma resource *.fmx
 
//#include <FMX.Calendar.Helpers.hpp>
#include <System.Rtti.hpp>
 
void __fastcall TMainForm::BtnAddEventsClick(TObject *Sender)
{
    LBEvents->Items->Add(DEEvent->Text);
    UpdateEvents();
}
 
void __fastcall TMainForm::BtnDeleteEventsClick(TObject *Sender)
{
    if (LBEvents->ItemIndex != -1)
        LBEvents->Items->Delete(LBEvents->ItemIndex);
    UpdateEvents();
}
 
void __fastcall TMainForm::BtnCheckPresentationNameClick(TObject
*Sender)
{
    if (Calendar1->Presentation)
        ShowMessage(Calendar1->Presentation->ClassName());
    else
        ShowMessage(_D("TCalendar doesn't have presentation"));
}
 
void __fastcall TMainForm::CBDisplayEventsChange(TObject *Sender)
{
    ((TCalendarModelHelpers*)(Calendar1->Model))->ShowEvents =
CBDisplayEvents->IsChecked;
}
 
void __fastcall TMainForm::CBDisplayWeekendsChange(TObject *Sender)
{
    ((TCalendarModelHelpers*)(Calendar1->Model))->ShowWeekends =
CBDisplayWeekends->IsChecked;
}
 
void __fastcall TMainForm::UpdateEvents()
{
    DynamicArray<TDateTime> Events;
 
    Events.Length = LBEvents->Count;
    for(int I = 0; I < LBEvents->Count; ++I)
        Events[I] = StrToDateTime(LBEvents->Items->Strings[I]);
 
    Calendar1->Model->Data[_D("Events")] = TValue::From(Events);
}


I have success fully created a c++ form with the controls on, and
it appears to be looking at the .pas FMX files above, but the
Calendar1.Model.ShowWeekends property could not be found in C++

Right, TCalendarModel does not have a ShowWeekends property, it is
added by the TCalendarModelHelpers helper class.

so had to be converted like following...

Yes that would be a manual way to do it, if you don't define a helper
class, like shown above.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02