Category: Firemonkey

How clone TChart in FMX

How do i clone a TChart at runtime? I found this link but it is Delphi and i can't translate to C++ Builder. Here is what i tried but i get an error at runtime of Class TChart not found: TChart *tmp = new TChart(Chart1->Clone(this)); tmp->Parent = this->Panel2; Also, how can i clone so that i can easily reference the new clones in code - e.g. Chart(2), Chart(3) etc.
Read More

How to use Image1.Bitmap.BitmapChanged;

Bitmap.BitmapChanged; is protected in FMX.Graphics so I cannot use the procedure. Useing a TImage or TImageControler I am drawing a line but the line does not show. I am using this snippet: imgc1.Bitmap.Canvas.BeginScene; imgc1.Bitmap.Canvas.DrawLine(FStartPoint,FEndPoint, 100); imgc1.Bitmap.Canvas.EndScene; imgc1.Bitmap.BitmapChanged; // the original example said that this would redraw the image. In my CE Rio IDE the BitmapChanged is undefind. How can I use it? Draw the line. IDE cannot find BitmapChanged.
Read More

Android – The case of the vanishing file

I’m relatively new to the Android development platform, coming from the Windows desktop. One of the great things about recent editions of Delphi is it’s ability target numerous other platforms. One of the worst things about recent versions of Delphi is it’s ability to target platforms you are not as familiar with. If your use case is atypical, you can quickly find yourself swimming in shark infested waters. You never know what is going to byte you, a bug in the platform, a bug in Delphi RTL or FMX code, a bug in your code, or just your lack of knowledge about the platform. Today I was trying to figure out why files I was saving to the Documents folder on my Android LG5 were visible from the Android File Manager, but not present when I connected the phone to a Windows, or Ubuntu desktop. Turns out there is a long outstanding bug in Android that google has not even acknowledged. In order to see new files when connecting to a device using the MTP protocol, you may need to re-boot the Android device before the files appear. Indeed once I did so, my files appeared and I could copy them off to my PC. You may want to comment on this motion to get the issue re-opened and addressed. Hopefully this helps someone else avoid spending a lot of time scratching their head…
Read More

UWP and Windows App Platform

UWP and Windows App Platform As you have probably seen, over the last month there has been some discussion around UWP (Universal Windows Platform) and the current focus, or change of focus, for Microsoft in terms of how developers should build applications for their mainstream operating system, Windows 10. There have been claims and counterclaims, making the entire debate quite interesting. Needless to say, Microsoft directions for building Windows applications is of critical importance to most of our customers, and also for us as at Embarcadero, given RAD Studio has a strong focus on Windows development. For a summary of Microsoft point of view, you can read this interview by Mary Jo Foley of Microsoft Corporate Vice President of the Windows Developer Platform Kevin Gallo: https://www.zdnet.com/article/microsoft-wants-to-close-the-uwp-win32-divide-with-windows-apps/ But let me start from the beginning and recap Microsoft plans (and how Embarcadero addressed those). UWP Holy Grail and WinRT A few years back, when Microsoft introduced Windows 10 for desktop the company still had high hopes for its twin Windows 10 Phone operating system. We know the phone ended up being a big failure for Microsoft, but at the time they were betting heavily on it. The idea behind UWP was to create a new common API and core operating system infrastructure that would allow the same application to run on all versions of Windows (including also Xbox and HoloLens). Technically, Windows 10 came with a new "core" called WinRT (initially introduced in Windows 8), a subsystem you can target with a specific API. This is not a .NET API, but more of a native, C++ type of API. Side Note: Turns out that WinRT is "invocation compatible" with COM and it can be easily mapped to Delphi interfaces -- which is what Embarcadero did offering direct support for this new platform API. There were other key tenets: increased security (as apps run more in isolation and are safer in their memory management), more stability (with more responsive UIs and async processes), and that could allow Windows become a more stable ecosystem. So why didn't all developers jumped to UWP and WinRT? Microsoft offered a variety of programming languages (C# and .NET, C++, even JavaScript) and they expected large adoption. However, UWP came with its own UI design guidelines (wide spaced controls, full screen mode) and technical specifications (almost all code requiring to be asynchronous) that hampered development. Nice, modern, but quite different from any other API, platform and UX -- and so difficult to adopt by developer, particularly if the target is more than one platform. Basically none of the existing code was ready to run there, regardless of the programming language you picked. And doing a full rewrite is not something developers (and their companies) are keen on doing. Cross the Bridge or Stay on the Trusted Side? After the initial dismal adoption (which allowed developers to publish app on the store -- but a store that wasn't well maintained) Microsoft started promoting a set of "bridges" to allow bringing existing code to the new UWP platform. There was a bridge for Android apps support on Windows Phone, one for Objective-C conversion, and one to allow Win32 native apps to become part of UWP. Now these were non-universal UWP platform apps, given they could run only on one of the versions of Windows 10, desktop or mobile. This ended up only adding to the confusion. Moreover, Microsoft kept indicating these bridges were meant to help converting your applications to the new model, one form and one module at a time -- rather than all at once. But the destination was still supposed to be a complete rewrite of your code. "If you have a million lines of code, you want to move to the new platform over time", Microsoft was officially stating. But it was obvious developers didn't really want to do ANY rewrite of their code for moving it from Windows to Windows 10! Considering all old applications kept running smoothly and the brand new features offered by the operating system were fairly limited. Now again, RAD Studio (as well as Visual Studio) started offering support for the Desktop Bridge, but our goal was only letting developers target new APIs available only on the WinRT side (like notifications or BLE) and be able to deploy applications on the Windows Store -- for easier distribution, taking advantage of low commissions, and additional monetization options (via subscriptions). Is Microsoft Giving Up? This brings us to today and the recent "announcements" by Microsoft. An interesting POV is at: https://mspoweruser.com/uwp-is-dead-because-windows-apps-are-dead/ The company has apparently just come to the realization that no matter their insistence developers are not going to rewrite applications to target the Windows operating system. In fact they keep using WinForms and MFC (on Microsoft developer tools side) or VCL (on the RAD studio one) or other native libraries. These days Microsoft is clearly downplaying UWP as a development model. Notice that there are also reports of the fact XBox apps are now being built with Electron, a JavaScript desktop library: https://www.onmsft.com/news/new-electron-powered-xbox-app-leaks-hours-before-e3 The claim development for the Windows platform has stopped seems fairly exaggerated. There are still a lot of business applications written for Windows, and also real time control systems and games. While a lot of consumer apps moved to the web and mobile, investment on Windows development is still a significant portion of the IT budget -- even though maintenance of existing applications is likely a significant part of it. In any case, this is only one side of the scenario. The APPX model of the desktop bridge implies apps run "partially sand-boxed". They cannot be elevated with admin permission, they can access only their "view" of the registry and operating system. Granted, they can still do damage, but the store vetting procedure should also help filtering out the bad guys. The concept around UWP / APPX is applications can be more easily isolated (and with .NET Core even have each their own copy of any required library). They can be installed with no admin permission and removed leaving a clean (or almost completely clean) operating system, mimicking the experience users have on phones. Now this is not just surviving to the UWP model, but Microsoft has double its effort with the MSIX technology. This sounds and it is being promoted as an "installation" technology, but it is in fact the next interaction of APPX. MSIX apps can be distributed via Windows Store or within an enterprise distribution model, allow for extra security and what Microsoft originally called "virtualization" and now dubs as "containerization" -- to piggyback on a common trend. The idea apps should live more and more in isolation is also backed by changes at the .NET level, with the idea (a key element of .NET Core) that each app should ship with its own version of .NET rather than relying on the version of library the operating system provides -- with the big advantage of reducing dependencies and allowing users to update .NET without fearing to break existing applications on their systems. And What About RAD Studio? This is how I understand the future of the Windows App platform -- a future that allows Delphi and C++Builder VCL applications to play on par with Microsoft own UI libraries and ecosystem, with a much higher degree of compatibility with existing code and investment. Windows 10 as target platform is alive and growing (within the desktop OS total, if not in absolute terms) and the VCL with its support for Windows API, COM, WinRT and APPX model has everything you need to target the platform. Our libraries integrate Windows 10 feature, High DPI support, and compatibility in a way that's unparalleled in the industry -- without forgetting a large ecosystem of great third party controls!
Read More

convert vcl project to fmx Delphi 10.3

I try to use Listview in my fmx project , and grab text from it Like vcl , How can I using it in fmx project not in vcl ? procedure TForm1.Button1Click(Sender: TObject); var item: TListItem; begin item := ListView1.Items.Add; item.Caption := 'Mohamed'; item.SubItems.Add('Akram'); item.SubItems.Add('055002011'); item.ImageIndex := 0; end; procedure TForm1.CaptionclickClick(Sender: TObject); begin Memo1.Lines.Add('caption : ' + ListView1.Items[ListView1.Selected. Index].Caption); end; procedure TForm1.FirstitemclickClick(Sender: TObject); begin Memo1.Lines.Add('First sub item : ' + ListView1.Items[ListView1.Selected. Index].SubItems[0]); end; procedure TForm1.SeconditemclickClick(Sender: TObject); begin Memo1.Lines.Add('Second sub item : ' + ListView1.Items[ListView1.Selected. Index].SubItems[1]); end; https://6.top4top.net/p_1260py56w1.jpg
Read More

How to bring a TreeViewItem in the visible (scroll) area

I'm looking for a way to navigate by code to an item in a tree view. The object should be moved into the visible area. I could not find a method in either TTreeView or TTreeViewItem. The following approach does not work under all circumstances because the item position is not always updated: procedure TfmxMain.MakeItemVisible(Item: TTreeViewItem); begin trvMyTreeView.ViewportPosition := TPointF.Create(min(Item.Position.X - trvSlideGroups.ClientWidth / 2, 0), min(Item.Position.Y - trvSlideGroups.ClientHeight / 2, 0)); end;
Read More

How to refresh TListView LiveBinding with TAdapterBindSource

I am using Delphi 10.3.1 (Firemonkey FMX) to build android and iOS app. I have a TListView, live binding with a AdapterBindSource. My problem is: new records does not appear after Adapter refreshed. ============== I created a TObjectList, added 3 objects to it I created a TBindSourceAdapter by passing a TObjectList to create it. I assign the TBindSourceAdapter to AdapterBindSource1.Adapter. Then I Free the TObjectList and re-create it, add 4 newly created objects (3 of them are old records, with some data modified, 1 is a new record) I do TBindSourceAdapter.Refresh and TAdapterBindSource.Refresh Those 3 old records are refreshed successfully with modified data displayed, but the new record is not showing up in Android and iOS The same logic working fine in Windows platform ============== My logic create TObjectList first I get records from Rest Server and converted into a TObjectList TData : class(TObject) ... // a class stored some data TDataList = class(TObjectList<TData>) // then I get data from Rest Server and created FList, it is a Form private variable FList := TDataList.Create; // a private Form variable // create Tdata objects and add to FList ..... create TBindSourceAdapter, assign to AdapterBindSource var ABindSourceAdapter: TBindSourceAdapter; // .... ABindSourceAdapter := TListBindSourceAdapter<TData>.Create(self, FList, True); AdapterBindSource1.Adapter := ABindSourceAdapter; AdapterBindSource1.Active := true; then the records show on ListView which live bindings with the AdapterBindSource Refresh FList records When click on Refresh button, I trigger to get data from Rest server again, I do free the FList and re-create it FreeAndNil(FList); FList := TDataList.Create; // re-create the list, then create Tdata object and add to it again. refresh the Adapter then I refresh the adapter AdapterBindSource1.Adapter.Refresh; AdapterBindSource1.Refresh; here the 3 old records are refreshed successfully, modified data are displayed correctly, however, new record is not showing, the TListView still showing 3 records only. Notes: I did not re-create TListBindSourceAdapter and assign to AdapterBindSource1.Adapter again during refresh, the records still refreshed successfully. However, even I re-create TListBindSourceAdapter and assign to AdapterBindSource1.Adapter again, new record still does not show up, only caused memory leaking. How can I resolve this? is there something I missing like to refresh the TListView? Or my BindSourceAdapter refresh logic is wrong? Thanks for any help.
Read More

Even perpetual Delphi licenses require an active maintenance support to allow re-install on a fresh machine

Last month, people found out that retroactively, Embarcadero has changed the terms of the license agreements on products sold with a perpetual license: In order to re-install those products, often a bump in license count is needed. That bump now requires an active maintenance subscription which has a substantial yearly cost. This is yet another […] … Read More

Read More

How to stop duplicating child components (Delphi 10.1 Berlin Firemonkey)

I am creating a component with a published "VisibleItems" property. When the property of an item is checked/un-checked an item is either added or removed from the component and stored in the dfm (Which works), however; when the the component is streamed from the dfm into the IDE duplicate items are created. I've overridden the protected "Loaded" procedure of the item (TMyTreeViewItem) and added a "CreateDefaultItem" procedure to the parent component (TDesignTimeTreeView) which appears to work for Windows but not for Android. I tried marking properties in the parent and child components with the "stored False" directive. I've also tried overriding the "Loaded" procedure in the main component. Below is a minimal version of the component. If the TMyTreeViewItem.Loaded and TDesignTimeTreeView.CreateDefaultItem are bypassed the component duplication starts to happen in the IDE when toggling between "View as Text" and "View as Form" (Alt + F12). unit DesignTimeTreeView; interface uses System.SysUtils, System.Classes, System.Types, System.UITypes, FMX.Types, FMX.Controls, FMX.Layouts, FMX.TreeView; type {$SCOPEDENUMS ON} TItemId = (NONE, Default, Custom, One, Two); {$SCOPEDENUMS OFF} TMyTreeViewItem = class(TTreeViewItem) private FId : TItemId; procedure SetFId(const Value: TItemId); protected procedure Loaded; override; published property Id: TItemId read FId write SetFid; end; TVisibleItemsChange = procedure(Id: TItemId; Visible: Boolean) of object; TVisibleItems = class(TPersistent) private FItem1 : Boolean; FItem2 : Boolean; FOnChange : TVisibleItemsChange; procedure SetVisibility(Id: TItemId; Visible: Boolean); procedure SetFItem1(const Visible: Boolean); procedure SetFItem2(const Visible: Boolean); property OnChange: TVisibleItemsChange read FOnChange write FOnChange; published property Item1: Boolean read FItem1 write SetFItem1; property Item2: Boolean read FItem2 write SetFItem2; end; TDesignTimeTreeView = class(TTreeView) private { Private declarations } FVisibleItems : TVisibleItems; FDefaultMyTreeViewItem : TMyTreeViewItem; function GetItemById(Id: TItemId): TMyTreeViewItem; function GetItemName(Id: TItemId): string; procedure AddItem(Id: TItemId); procedure OnVisibilityChange(Id: TItemId; Visible: Boolean); procedure OnItemClick(Sender: TObject); procedure OnItemTap(Sender: TObject; const Point: TPointF); procedure CreateDefaultItem; const PREFIX = 'StandardItem_'; protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; published { Published declarations } property VisibleItems: TVisibleItems read FVisibleItems write FVisibleItems; end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TMyTreeViewItem, TDesignTimeTreeView]); end; { TDesignTimeTreeView } procedure TDesignTimeTreeView.AddItem(Id: TItemId); var Item : TMyTreeViewItem; ItemName : string; i : Integer; Sub : TTreeViewItem; begin ItemName := GetItemName(Id); Item := GetItemById(Id); if Item <> nil then RemoveObject(Item); Item := TMyTreeViewItem.Create(nil); Item.FId := Id; Item.Text := ItemName; Item.Name := ItemName; Item.HitTest := True; Item.OnClick := OnItemClick; Item.OnTap := OnItemTap; Item.Parent := Self; for i := 1 to 10 do begin Sub := TTreeViewItem.Create(nil); Sub.Text := 'Sub Item (' + i.ToString + ')'; Sub.Parent := Item; end; end; constructor TDesignTimeTreeView.Create(AOwner: TComponent); begin inherited Create(AOwner); ItemHeight := 46; CreateDefaultItem; FVisibleItems := TVisibleItems.Create; FVisibleItems.OnChange := OnVisibilityChange; { Set the default values } FVisibleItems.FItem1 := False; FVisibleItems.FItem2 := False; end; procedure TDesignTimeTreeView.CreateDefaultItem; var Item : TMyTreeViewItem; const DEFAULT_ITEM_NAME = 'DEFAULT_MYTREEVIEWITEM'; begin if Owner <> nil then if Owner.FindComponent(DEFAULT_ITEM_NAME) <> nil then begin Item := TMyTreeViewItem(Owner.FindComponent(DEFAULT_ITEM_NAME)); if Item.Id <> TItemId.Default then Item.Free else Exit; end; if Assigned(FDefaultMyTreeViewItem) then FreeAndNil(FDefaultMyTreeViewItem); FDefaultMyTreeViewItem := TMyTreeViewItem.Create(Owner); FDefaultMyTreeViewItem.FId := TItemId.Default; FDefaultMyTreeViewItem.Name := DEFAULT_ITEM_NAME; FDefaultMyTreeViewItem.Text := 'Created by TDesignTimeTreeView. This makes it so you do not have ' + 'to add a TMyTreeViewItem on the form just so this component will ' + 'work.'; FDefaultMyTreeViewItem.Parent := TFmxObject(Owner); FDefaultMyTreeViewItem.Visible := False; end; function TDesignTimeTreeView.GetItemById(Id: TItemId): TMyTreeViewItem; var i : Integer; ItemName : string; begin Result := nil; ItemName := GetItemName(Id); for i := 0 to Count - 1 do if Items[i].Name = ItemName then Result := TMyTreeViewItem(Items[i]); end; function TDesignTimeTreeView.GetItemName(Id: TItemId): string; begin Result := PREFIX + Ord(Id).ToString; end; procedure TDesignTimeTreeView.OnItemClick(Sender: TObject); var Item : TMyTreeViewItem; begin Item := TMyTreeViewItem(Sender); Item.Text := Ord(Item.Id).ToString + ' Clicked (' + FormatDateTime('h:nn:ss.zzzAM/PM', Now) + ')'; end; procedure TDesignTimeTreeView.OnItemTap(Sender: TObject; const Point: TPointF); begin OnItemClick(Sender); end; procedure TDesignTimeTreeView.OnVisibilityChange(Id: TItemId; Visible: Boolean); var Item : TMyTreeViewItem; begin Item := GetItemById(Id); if Item <> nil then RemoveObject(Item); if Visible then AddItem(Id); end; { TVisibleItems } procedure TVisibleItems.SetFItem1(const Visible: Boolean); begin SetVisibility(TItemId.One, Visible); end; procedure TVisibleItems.SetFItem2(const Visible: Boolean); begin SetVisibility(TItemId.Two, Visible); end; procedure TVisibleItems.SetVisibility(Id: TItemId; Visible: Boolean); begin case Id of TItemId.Custom: { Do Nothing }; TItemId.One: FItem1 := Visible; TItemId.Two: FItem2 := Visible; end; if Assigned(FOnChange) then FOnChange(Id, Visible); end; { TMyTreeViewItem } procedure TMyTreeViewItem.Loaded; begin if Id = TItemId.NONE then begin Self.Destroy; Exit; end; if Id = TItemId.Default then Exit; if not (Parent is TDesignTimeTreeView) then Self.Destroy; inherited; end; procedure TMyTreeViewItem.SetFId(const Value: TItemId); begin { Read Only: But we want to see it in the .fmx file of the form } end; end. I expect that when VisibleItems.Item1 is checked a TMyTreeViewItem will be added to the component and stored in the dfm (Which is working). The component also appears to be streaming from the dfm to the IDE correctly. I also expect to see Item1 and Item2 on the form (If they are checked) when the program runs (Which is working for Windows). When I drop this component onto a multi-device-applicaiton form, set VisibleItems.Item1 and Item2 to true, and finally deploy it to an Android device I get the following errors: *.apk raised ececption class EComponentError with message 'A component named DEFAULT_MYTREEVIEWITEM already exists'. *.apk raised exception class Segmentation fault (11). *.apk raised exception class Illegal instruction (4).
Read More