Category: Firemonkey

resource not found after subclassing firemonkey form

Please help. I'm working on a longstanding Delphi project with several firemonkey forms that I wanted to make resizable. I put the resizing-relevant code in a new form that descended from TForm, and changed my existing forms to descend from the new form. That seemed to work, but now it fails during compilation with errors like "resource TLessonStudent not found" Alarmingly, putting the code back the way it was before doesn't remove the error. What is happening? Is there some way to create a resource file the compiler will like? Thanks! Art I've tried adding and removing compiler directives such as {$R *.DFM} in various places. I also tried to put the code back the way it was before, with my forms once again descending directly from TForm. Still the same error. Here is how the new top level form is declared: type TFluentTutorForm = class(TForm) protected ... resizableLayout: TScaledLayout; procedure FormCreate(Sender: TObject); private ... function getScreenSize(var retWidth: integer; var retHeight: integer): boolean; public end; //TFluentTutorForm var fluentTutorForm: TFluentTutorForm; implementation {$R *.fmx} Here is one of my old forms, modified to descend from the one above type TLessonStudent = class(TFluentTutorForm) ... procedure FormCreate(Sender: TObject); private unitTester: IftUnitTester; public end; //TStudentForm var studentForm: TLessonStudent; implementation {the formCreate method shown above calls "inherited formCreate" on it's new parent, shown at top} And here is the part of the project code that creates the form: {$R *.res} begin Application.Initialize; Application.FormFactor.Orientations := [TFormOrientation.Portrait];// InvertedPortrait]; Application.CreateForm(TlessonStudent, studentForm); //<here!! Application.CreateForm(TClientModule1, ClientModule1); Application.CreateForm(TDataModule1, DataModule1); Application.CreateForm(TmemTableForm, memTableForm); Application.Run; end.
Read More

Event Handler for Dynamically Created TText array in FMX

I am creating an array of 81 (9x9) TText boxes in an android app. I need to find which box was touched to change the text. I followed the example at Event Handler for Dynamically Created CheckBox (Thanks Remy Lebeau) but I get the following two error msgs in C++ Builder 10.3. The messages are: "MouseUp is a protected member of Fmx::Controls::TControl" and a very long msg [bccaarm Error] MainFm.cpp(106): assigning to 'void (closure *)(System::Uitypes::TMouseButton, System::Classes::TShiftState, float, float) __attribute((pcs("aapcs-vfp")))' from incompatible type 'void (closure *)(__borland_class *System::TObject __strong, System::Uitypes::TMouseButton, TShiftState, float, float) __attribute((pcs("aapcs-vfp")))' Is there something I should do different in the creation of the TText to insure that it is a FMX control vs a ... ? The form is a multi-device form, not VCL. UPDATE: I had a head slap moment. I finally realized that I used the wrong event name. "MouseUp" as used in TextBoxMouseUp is NOT the event handler name; "OnMouseUp" is the correct one. That is, BAD: TextBox[i][j]->MouseUp = FmMain->TextBoxMouseUp; GOOD: TextBox[i][j]->OnMouseUp = FmMain->TextBoxMouseUp; Hope this helps someone else in the future. As always, Remy, your instructions are dead on. We all just have to read every single word.
Read More

When generics and VCL controls bite you: memory overwrites when you show the control usually ending up in access violations

Recently I got bitten by the 2013 reported http://qc.embarcadero.com/wc/qcmain.aspx?d=112101 (too bad the site is gone and the WayBack machine doesn’t have it archived) as a result of [WayBack] delphi – Why do I get access violations when a control’s class name is very, very long? – Stack Overflow. It got reentered as [RSP-18399] Buffer overflow in TWinControl.CreateParams() – Embarcadero Technologies but since that requires logon, it’s not search machine indexed so it’s very hard to find unless you know where to look. So I spent a quite some time to find out what was wrong: Since Delphi 1, the [WayBack] Controls.TCreateParams Record has a 64-byte WinClassName field that’s blindingly copied by the TWinControl.CreateParams without range checking. The structure is used by the [WayBack] TWinControl.CreateWnd Method to call the Windows API [WayBack] RegisterClass function that takes a [WayBack] WNDCLASS structure with a lpszClassName field that supports up to 256 characters and it fails when it’s longer. That overwrite cause spurious other errors depending on the memory that gets overwritten. It took almost a day to figure out the cause of the error was this field, then an hour or to track that down to the long class names created by generic code. To my surprise, I found back [WayBack] This issue caused coworkers and me quite a few hours wasted:Long story short – refactor some forms/frames to class names longer than 64 chars and boom… – Stefan Glienke – Google+. As of Delphi 8 (yes, that version that a lot of people want to forget, but did bring a few good things), the structure was defined as below, and the code intialising also got improved: Params.WinClassName := ClassName; ... Params.WinClassName := Format('%s.%d', [Params.WinClassName, AppDomain.CurrentDomain.GetHashCode]); So there it’s a string that – if it is too long – will get rejected by the Windows API anyway just like the native Delphi VCL implementation should have done 20+ years ago. The sad part for FMX users: that structure and code got blindingly copied to the FMX.Controls.Win unit. {$IF DEFINED(CLR)} TCreateParams = record Caption: string; Style: DWORD; ExStyle: DWORD; X, Y: Integer; Width, Height: Integer; WndParent: HWND; Param: IntPtr; WindowClass: TWndClassInfo; WndProc: TFNWndProc; WinClassName: string; end; {$ELSE} TCreateParams = record Caption: PChar; Style: DWORD; ExStyle: DWORD; X, Y: Integer; Width, Height: Integer; WndParent: HWnd; Param: Pointer; WindowClass: TWndClass; WinClassName: array[0..63] of Char; end; {$ENDIF} –jeroen
Read More

When generics and VCL controls bite you: memory overwrites when you show the control usually ending up in access violations

Recently I got bitten by the 2013 reported http://qc.embarcadero.com/wc/qcmain.aspx?d=112101 (too bad the site is gone and the WayBack machine doesn’t have it archived) as a result of [WayBack] delphi – Why do I get access violations when a control’s class name is very, very long? – Stack Overflow. It got reentered as [RSP-18399] Buffer overflow in TWinControl.CreateParams() – Embarcadero Technologies but since that requires logon, it’s not search machine indexed so it’s very hard to find unless you know where to look. So I spent a quite some time to find out what was wrong: Since Delphi 1, the [WayBack] Controls.TCreateParams Record has a 64-byte WinClassName field that’s blindingly copied by the TWinControl.CreateParams without range checking. The structure is used by the [WayBack] TWinControl.CreateWnd Method to call the Windows API [WayBack] RegisterClass function that takes a [WayBack] WNDCLASS structure with a lpszClassName field that supports up to 256 characters and it fails when it’s longer. That overwrite cause spurious other errors depending on the memory that gets overwritten. It took almost a day to figure out the cause of the error was this field, then an hour or to track that down to the long class names created by generic code. To my surprise, I found back [WayBack] This issue caused coworkers and me quite a few hours wasted:Long story short – refactor some forms/frames to class names longer than 64 chars and boom… – Stefan Glienke – Google+. As of Delphi 8 (yes, that version that a lot of people want to forget, but did bring a few good things), the structure was defined as below, and the code intialising also got improved: Params.WinClassName := ClassName; ... Params.WinClassName := Format('%s.%d', [Params.WinClassName, AppDomain.CurrentDomain.GetHashCode]); So there it’s a string that – if it is too long – will get rejected by the Windows API anyway just like the native Delphi VCL implementation should have done 20+ years ago. The sad part for FMX users: that structure and code got blindingly copied to the FMX.Controls.Win unit. {$IF DEFINED(CLR)} TCreateParams = record Caption: string; Style: DWORD; ExStyle: DWORD; X, Y: Integer; Width, Height: Integer; WndParent: HWND; Param: IntPtr; WindowClass: TWndClassInfo; WndProc: TFNWndProc; WinClassName: string; end; {$ELSE} TCreateParams = record Caption: PChar; Style: DWORD; ExStyle: DWORD; X, Y: Integer; Width, Height: Integer; WndParent: HWnd; Param: Pointer; WindowClass: TWndClass; WinClassName: array[0..63] of Char; end; {$ENDIF} –jeroen
Read More

SaveState exception: Cannot Create file, Operation not permitted

I test SaveState on my iPad, I follow exactly the same logic on the embarcadero SaveState example, but it throws an exception after saving data. However, the same logic tested on iOS Simulator is working fine. I am using Delphi 10.3.1 with an iPad iOS12.2 When I click the home button after the FormSaveState logic executed, the below exception occurred: Cannot create file ....... Operation not permitted The same logic tested on iOS Simulator is working fine. Any idea why this occurred and how to resolve? Thanks for any help!
Read More

ComboEdit – how refresh items on Popup event?

I've got a problem with ComboEdit on Android. I need add item to ComboEdit.Items in OnPopup event, but my item is visible after second shows popup. How refresh Items in OnPopup event? procedure TForm1.ComboEditPopup(Sender: TObject); begin ComboEdit1.Items.Add('MyItem'); // this item will by visible at next popup end; What I want achieve: Items: 'Aaa', 'Bla', 'Ble', 'Dee'. User writes 'Bl'. When he pushes Popup, ComboEdit will show him items: 'Bla', 'Ble' . My currently code: ComboEdit : TComboEdit; Items : TStringList; // around 1000 strings procedure TForm1.ComboEdit1Typing(Sender: TObject); var i : integer; begin ComboEdit.BeginUpdate; ComboEdit.Items.Clear; for i := 0 to Items.Count-1 do if AnsiStartsText(ComboEdit.Text,Items[i]) then ComboEdit.Items.Add(Items[i]); Items.EndUpdate; end;
Read More

How to obtain CFStringRef value from iOS API function in Delphi 10.3 Rio

Cannot obtain CFStringRef value from iOS API function (framework) in Delphi 10.3 Rio // external call bridge function to iOS: function MIDIObjectGetStringProperty(obj: MIDIObjectRef; propertyID: CFStringRef; out str: CFStringRef):OSStatus; cdecl; external libCoreMidi name _PU + 'MIDIObjectGetStringProperty'; Function MIDIObjectGetStringProperty (iOS CoreMIDI function) return in str:CFStringRef name of MIDI ports ... How can I obtain value of CFString variable in Delphi? In this example str:CFStringRef value? I try it in my func.: function getDisplayName(obj: MIDIEndpointRef):string; var EndPointName: CFStringRef; i:integer; begin //EndPointName:= nil; // when I assign nil value, function return i=-50 otherwise raise Access Violation error ... i := MIDIObjectGetStringProperty(obj, kMIDIPropertyDisplayName , EndPointName); --> AV error !!! //in EndPointName should be returned CFStringRef value from iOS getDisplayName := CFToDelphiString(EndPointName); // convert to string end; Probably EndPointName need to be allocated ... else I give AV error. Please got someone solution how obtain ANY CFStringRef value from iOS framework and convert to string? Thanx. Adds: I build crossplatform (iOS, Android, W64) app in Delphi Rio via FireMonkey frameforks api - for CoreMIDI I use this interface https://github.com/FMXExpress/ios-object-pascal-wrapper/blob/master/iOSapi.CoreMIDI.pas So the externall call and constants are defined in iOSapi.CoreMIDI there: function MIDIObjectGetStringProperty (obj: MIDIObjectRef; propertyID: CFStringRef; str: CFStringRef) : OSStatus; cdecl; external libCoreMIDI name _PU + 'MIDIObjectGetStringProperty'; and iOS pointer const: function kMIDIPropertyDisplayName: Pointer; begin Result := CocoaPointerConst(libCoreMIDI, 'kMIDIPropertyDisplayName'); end; Otherwies compiled app work on real iOS (iPad) very well (reading MIDI message from connected MIDI keyboard) based on this solution https://pjstrnad.com/reading-data-midi-keyboard-ios-probably-also-mac/ obj: MIDIObjectRef is source pointer from source:= MIDIGetSource(ci); Problem is calling API function MIDIObjectGetStringProperty. In pointer str: CFStringRef (EndPointName) should be VALUE of MIDIportNAME. I cannot obtain this value and parse to delphi string ... I tried declared this poiter CFStringRef as: var EndPointName: pointer; EndPointName1: array of Byte; EndPointName2: TBytes; EndPointName3: TPtrWrapper; M: TMarshaller; and construction as: SetLength(EndPointName1, 255); GetMem(EndPointName2,255); EndPointName3 := M.AllocMem(255); i := MIDIObjectGetStringProperty(obj, kMIDIPropertyDisplayName , @EndPointNameX); --> nothing works, AV error !!! I thing it must be solution how to obtain CFStringRef and convert to delphi string ...
Read More

Firemonkey: Soft Keyboard pops up when VKAutoShowMode is Never

I have a large firemonkey android application which is designed for use primarily on barcode scanner devices, but must also be usable on e.g. an android phone (for testing). When used on a barcode scanner device, which typically has a physical keyboard, we suppress the virtual keyboard by setting VKAutoShowMode to TVKAutoShowMode.Never. This works just fine for most of the Tedit components. However, for 1 or 2 of these - which are to all intents and purposes "the same" as the others - the virtual keyboard pops up when the key press is received from the physical keyboard. And furthermore, it is not easily dismissed by using the return key with KillFocusByReturn set on the relevant Tedit. I can work around the problem using the Android Language & input settings to effectively disable the virtual keyboard completely, but this is less than ideal as in some fields we do want the soft keyboard for simpler alpha input. I can also achieve a partial workaround by calling up our "HideVirtualKeyboard" routine within an onkeyup event for the problem Tedit(s), but this looks silly as the keyboard flashes up and then disappears. Also, if one then moves to another TTabItem within the application after giving focus to the problem Tedit, a key press on the physical keyboard will pop the virtual keyboard up and special action has to be taken to get rid of it. I would appreciate any suggestions.
Read More

Firemonkey/Isometric at master · tothpaul/Firemonkey

This shows you how to do 2.5D isometric projection in Delphi using Firemonkey: [WayBack] Firemonkey/Isometric at master · tothpaul/Firemonkey. [WayBack] Isometric projection – Wikipedia. Via: [WayBack] I wonder what the best approach would be to use FireMonkey to develop an isometric 2.5D game in the “classic” way… – Fl Ko – Google+ –jeroen
Read More

How to fix, images loaded in multi thread sometimes don’t show up on the form

In my manga viewer i try to load a large number of images (around 200), i try loading these images inside an anonymous thread and when the loading finishes i call a Thread.synchronize, this works fine, but in some cases i keep seeing some images not drawn on the form (I think they are loaded because i can see the information about the image), how can i solve this? This issue only happens in multi thread so i decided to set the image visible to false and then at the end of the loading inside a Thread.synchronize turn the visible to true, i had hoped this would force some kind of refresh or redraw, but the problem i mentioned consists TThread.CreateAnonymousThread(procedure begin for imageIndex := 0 to fileList.count - 1 do begin filePath := fileList[imageIndex] //Please note that mImageList is an array of FMX.Objects.TImage //which was filled when the Form is created (I create 300 TImage //at Form create and later i load the images to the bitmap when //the user clicks on a new directory(Chapter) mImageList[imageIndex].beginUpdate(); try mImageList[imageIndex].loadFromFile(filePath); mImageList[imageIndex].tagString := filePath; mImageList[imageIndex].Scale := mImageScale; mImageList[imageIndex].Visible := false; except mImageList[imageIndex].EmptyBitmaps; end; mImageList[imageIndex].endUpdate(); end; TThread.Synchronize(nil, procedure var I: Integer; begin for I := Low(mImageList) to High(mImageList) do begin mImageList[I].Visible := true; end; end); end).Start; I expect that when i scroll down through the images loaded on the form, i can see them all and they all get drawn on the form properly.
Read More

Changes between GExperts 1.3.12 and 1.3.13

I had to look them up myself, so it took a while but here they are, the changes, bugfixes and improvements between the GExperts 1.3.12 (released 2018-12-22) and 1.3.13 (released yesterday, 2019-03-30): Bugfix (#105): Set Tab Order expert no longer worked with Delphi 6, 7 and 2005 (Remember what I wrote about testing these versions?)Improvements to the Uses Clause Manager:New configuration setting “GExperts caching directory”, used to store the cached identifiers per unitAdditional configuration options for the expert: Caching can now be disabled and the cache can be cleared. (Bug report #104)It is now possible to use the project’s map file rather than the dpr for getting a list of used units. This includes the VCL/RTL and possibly any 3rd party units and makes the Project tab much more useful.Bugfix (#110): Entries in the VCL/RTL list were clipped / overlapped.Bugfix (#109): When loading a form’s position only, Width and Height no longer change every time.Added additional Delphi 10.2 and 10.3 warnings to the Insert Warn Directive editor expertBugfix: The number of entries for the Favourite Files expert in the registry doubled every time the list was saved.Improvements to the Grep expert:Hint about separating multiple directories with semicolon.It can now use the project’s map file rather than the dpr for getting the list of used units. This includes all units compiled in the project not just those explicitly added to it. There is a configuration option for enabling that.Ensure that the RTL and all existing subsystem Paths (VLC, FMX, CLX) are in the drop down menu.Searching DFM files can now handle strings split into multiple lines and containing special characters stored as #<number>. (Note: This is not quite finished. The display in the Results window is broken.) (Bug report #112)Custom beep as a WAV file for the Proof Reader expert (Suggested by Philip Rayment, Patch by Achim Kalwa, Bug report #111).Bugfix (#113): Added another check for duplicate GExperts DLLs being loaded into the same IDE to prevent error message “PrivateGXMenuActionManager is not nil upon creation”Project Dependency expert:Dramatically improved performance for the indirect dependencies tab. The strings and string lists are no longer stored in and read from the UI. Also string lists are now sorted so look ups are much faster.Units in the project (root node of the tree view are now also listed)New configuration option to search for units in the library path and also in the browsing path.Bugfix (#114): Disabled editor experts still blocked the associated keyboard shortcut and could be called with this shortcut.Bugfix (#117): Editor experts could be executed even if not the code editor but the form editor was active. As you can see above, I am looking into bugs reported on Sourceforge and also feature suggestions posted there. That is my preferred way of users to report bugs and request features because it is easy for me to manage them in one place. The other channels (email via the GExperts “Send a Bug Report / Suggestion” button and the GExperts subforum in the international Delphi Praxis forum) work too, but they are much less convenient for me and some reports / requests may get lost. Also, please remember that I am working on this project in my spare time, so any additional work, e.g. creating bug reports on Sourceforge from emails I receive, takes time in which I am not working on the actual software. It’s also boring work which might discourage me from doing it and if it is getting out of hand might even make me stop working on GExperts at all. Let me close this post by thanking all those people who have worked on GExperts before me and on whose work I have been building over the years (and whose work I have also been using as a GExperts user for more than two decades as a professional software developer). And also those who continue to contribute their work and some money to this project. Discussion about this post in the international Delphi Praxis forum.
Read More