

Lachlan Gemmell
Members-
Content Count
55 -
Joined
-
Last visited
-
Days Won
2
Lachlan Gemmell last won the day on May 28 2023
Lachlan Gemmell had the most liked content!
Community Reputation
38 ExcellentTechnical Information
-
Delphi-Version
Delphi 12 Athens
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
Delphi 13 FMX applications not responding to mouse clicks on Win10 multimonitor
Lachlan Gemmell replied to Lachlan Gemmell's topic in FMX
@eivindbakkestuen here's the proof as requested. The big monitor is configured as two separate "picture by picture" displays (portrait monitors 3 and 4 from the original image) each plugged into a separate HDMI port. I find this more efficient than using it as a single wide screen. Monitors 5 and 2 at the bottom are USB powered mini touch displays. The bottom right touch screen is running a small utility I wrote that lets me switch between virtual desktops with a single tap. The bottom left touch screen I use for playing various media (though the touch functionality doesn't work on that one). Top right (monitor 1) is just a regular monitor that I usually put the documentation I need on. It's high because it's on a monitor arm sitting on one of those collapsible "standing desk" desk stands that were popular a few years back. I can swivel the monitor 270 degrees, and then walk to the other end of my desk where I have another keyboard and mouse (attached to this same PC) waiting. I can stand at that position and work on this same PC (with just monitor) but pace back and forth while thinking. -
Delphi 13 FMX applications not responding to mouse clicks on Win10 multimonitor
Lachlan Gemmell replied to Lachlan Gemmell's topic in FMX
@Brandon Staggs the RSS is correct but its state is "Ready for Validation" which perhaps means others can't see it yet. I shared it with you personally via JIRA though so perhaps you will be able to see it now. Like I said, my workaround is pretty rough and very specific to my system but easy for you to adapt if you have Delphi installed on the system to debug the method and discover the correct values to substitute. Inside TDpPxConverter.DefineCellByDP find the if statement inside the nested for loops and make the following modification to a copy of FMX.Platform.Screen.Win.pas that's added to your project. if InRange(APoint.X, Cell.LocationDP.X, Cell.LocationDP.X + Cell.SizeDP.Width) and InRange(APoint.Y, Cell.LocationDP.Y, Cell.LocationDP.Y + Cell.SizeDP.Height) then begin (* WORKAROUND - AColumn and ARow are first correctly set to 0 and 0, but then later incorrectly overwritten with 6 and 2. Abort before that happens *) if (Col = 6) and (Row = 2) and (AColumn = 0) and (ARow = 0) then Break; (* WORKAROUND ENDS *) AColumn := Col; ARow := Row; Break; end; What do you see in Delphi 13? Did the new implementation fix it for you? -
Delphi 13 FMX applications not responding to mouse clicks on Win10 multimonitor
Lachlan Gemmell replied to Lachlan Gemmell's topic in FMX
I've discovered the issue was introduced by a rewrite of the FMX.Platform.Screen.Win.TDpPxConverter.RebuildTable in Delphi 13. That method constructs a two dimensional array TDpPxConverter.FTable of TDpPxConvertor.TCell records representing different regions of your entire display area both onscreen and off. This rewritten method however appears to leave some of those TCell record fields without a value (probably only for those with over the top multimonitor configurations like mine). Specifically it's the TDpPxConvertor.TCell.LocationDP field that appears to contain rubbish in some of the records of that TDpPxConverter.FTable two dimensional array. I'll report the issue to Embarcadero [RSS-4146] but if anyone else encounters the issue and needs a workaround let me know. My workaround is a very rough hack specific to my screen configuration so it's not worth the effort explaining it here unless others are having the same problem. -
Delphi 13 FMX applications not responding to mouse clicks on Win10 multimonitor
Lachlan Gemmell posted a topic in FMX
I have a pretty unique multimonitor screen arrangement on my dev system and FMX applications compiled with Delphi 13 don't respond to mouse movements or clicks if the window is in the top third of monitor 3 (which is my primary monitor). Specifically the client area of the FMX window doesn't respond to mouse movements or clicks while it is within that region. The non-client area responds fine allowing you to move, maximise, close the window as you would normally. Interestingly the Delphi 13 IDE FMX designer suffers the same problem if I place it on monitor 3. Anything in the top third of that monitor I cannot select. I've verified it using both my application and the standard demo found at Samples\Object Pascal\Multi-Device Samples\User Interface\ControlsDesktop\ControlsDemo.dproj If I compile my FMX app or that FMX demo using Delphi 12.3 it works on every monitor no problem. VCL applications also don't have any issue either. I'm guessing for most people you won't have an issue but if there's anyone else out there with a wacky screen arrangement you may be seeing something similar. If you are please post your multimonitor arrangement here. It would be nice to be able to report the issue with a simpler multimonitor arrangement than mine to increase the chances of Embarcadero being able to reproduce the issue. -
compiler C++ compile times: Clang (bcc32c) vs. Borland (bcc32)
Lachlan Gemmell replied to Michaell's topic in General Help
I don't use the Clang compiler but I do remember that Athens 12.3 was supposed to give it a decent speed boost. Might be worth you upgrading from 12.2 when you have some time. -
I've done a lot of website scouring over the past few days and the only third party vendor in the Delphi sphere offering out of the box support for Google Pay and Apple Pay is FGX Native. FGX Native is not an FMX component library though, it's a complete alternative UI paradigm to FMX, and while I find it tempting I don't want to use it due to... reasons.
-
I'm assuming this the process you're referring to. https://docwiki.embarcadero.com/RADStudio/Athens/en/Using_a_Custom_Set_of_Java_Libraries_In_Your_RAD_Studio_Android_Apps OK, so an equivalent to your Apple ID button component in Kastri. Does this mean writing a Delphi wrapper around the Java PaymentsClient class? Can you think of any comparable code in Kastri for this task?
-
I'm doing some early investigation into the feasibility of an FMX application that can use Google Pay and Apple Pay on their respective platforms. The first stumbling block I've found reading their documentation is that they both require you to use a particular specialised native button provided by their respective payment SDKs. PKPaymentButton for Apple Pay https://developer.apple.com/documentation/passkit/pkpaymentbutton PayButton API for Google Pay https://developers.google.com/pay/api/android/guides/resources/pay-button-api FMX has some rudimentary support for native controls so presumably it would be technically possible to make use of these buttons, the question is how much work would be involved. I'm guessing quite a lot but maybe someone here knows more?
-
The most underwhelming release ever was Delphi 7. https://en.wikipedia.org/wiki/History_of_Delphi_(software)#Early_Borland_years_(1995–2003)
-
Problems with Delphi class structure / visibility
Lachlan Gemmell replied to Willicious's topic in Delphi IDE and APIs
So you'll need to find an instance of the TRenderer to access it's internal theme instance (hopefully via a public Theme property on the renderer). Use the same technique. Do a find in files for TRenderer.Create and find where the renderer is created. You may find it's contained by another class, in which case you repeat the same process for that class to find it's instance(s). To get access to the theme LemNames you may end up doing something like SomeGlobalInstanceOfSomeClass.SomePropertyForTheRendererInstance.Theme.LemNames := 'Cats'; Note that none of the parts of that made up line are unit names or class names. They're all instances, a global instance in the case of the first part, then properties within a class representing an instance, and finally the LemNames string property of the TNeoTheme class. To get this fictional line of code to compile I need to add to my uses clause whichever unit contains the declaration for the first instance, in this case the SomeGlobalInstanceOfSomeClass global variable. -
Problems with Delphi class structure / visibility
Lachlan Gemmell replied to Willicious's topic in Delphi IDE and APIs
I watched the rest of the video. A few comments. Firstly if you find yourself typing unit names (e.g. LemNeoTheme) outside of a uses clause, 9 times out of 10 you're doing it wrong. Secondly if you find yourself accessing a property through a class name (e.g. TNeoTheme), 8 times out of 10 you're doing it wrong. Think of a unit and the classes inside it as the paper instructions on how to build a table (a real physical table you sit at). The class procedures and functions are the steps you will need to follow to build that table and the data variables inside that class are just a list of the tools you'll need. Lets call this class TFantasticWoodenTableBuilder and it has public property HammerColour (which is a string). Don't think of that TFantasticWoodenTableBuilder class (or the unit that contains it) as being "alive" in any sense. It is as inanimate as an actual set of paper table building instructions. It can't actually physically do or verbally tell you anything. Next a real person Frank comes along and reads those instructions. Frank commits them to memory, goes away and starts building a table. Frank is now an instance of TFantasticWoodenTableBuilder and his HammerColour happens to be red. John reads the instructions and decides to build a wooden table with them. His hammer is blue. We now have two instances of TFantasticWoodenTableBuilder, Frank and John each with their own separate properties (though both called HammerColour) that stores their own respective hammer colours. If you want to know the colour of somebody's hammer you have to ask them (via an instance variable). There's no point asking the class (TFantasticWoodenTableBuilder), it's just a piece of paper, it's not going to talk back to you. The Frank and John instance variables are declared like this var Frank : TFantasticWoodenTableBuilder; John : TFantaticWoodenTableBuilder; This is how they are created (as in memory allocated to them) John := TFantasticWoodenTableBuilder.Create; Frank := TFantasticWoodenTableBuilder.Create; This is how you get or set their hammer colours if John.HammerColour <> 'blue' then ShowMessage('John has pinched somebody elses hammer'); Frank.HammerColour := 'green'; When you're done with them you free these instances so they release their memory Frank.Free; Frank := nil; { to everyone else, lets not make this line a thing please :-) } John.Free; John := nil; So the above code declared two instances John and Frank, created those instances, interrogated their respective hammer colours, and lastly freed the memory associated with those instance variables. Very important, if you're in another unit and you want to know what Frank's hammer colour is, you need to be able to reference the Frank instance through the Frank variable. Now that Frank variable is probably not declared in the same unit as the TFantasticWoodenTableClass. It's probably declared in some other unit. You have to add that other unit to your uses clause, not the unit that has the TFantasticWoodenTableClass in it. How do you know which other unit? Well you have to go searching for it just like you did at 7:04 in your video. How do you know what to search for? Detective work. Welcome to programming. At the 7:30 mark of the video you're getting close to understanding the problem but the actual solution is going to evade you until you learn more about object oriented programming. I haven't watched it but this video might be a good start. -
Problems with Delphi class structure / visibility
Lachlan Gemmell replied to Willicious's topic in Delphi IDE and APIs
I watched the first third of your video. You don't have an instance of your class TNeoTheme to actually retrieve the property from. A theme sounds like something you only need a single instance of in your whole application (I could be wrong on that, but for now let's say I'm right). Since there's only going to be one of them a global TNeoTheme instance variable will be acceptable for now. Let's declare it in the LemNeoTheme.pas unit unit LemNeoTheme; interface type TNeoTheme = class private FLemNames : string; public property LemNames : string read FLemNames write FLemNames; end; var MyTheme : TNeoTheme; { this variable MyTheme will represent the single instance of the class TLemNeoTheme } { it does not however create that instance here, just declares the variable } implementation { code, code, code, more code } { now at the very bottom of the unit, just before the final end. statement } initialization MyTheme := TNeoTheme.Create; { this is where the memory for the instance of TLemNeoTheme is allocated } { and assigned to the MyTheme variable. It will occur when the program starts } finalization MyTheme.Free; { this is where the memory for the instance is released. It will occur when the program shuts down } MyTheme := nil; end. Now over in TGamePreviewScreen.GetTextLineInfoArray you access the LemNames property via the MyTheme instance variable Result[2].Line := Result[2].Line + IntToStr(zombies + lemmings) + MyTheme.LemNames; Please be aware that we're only scratching the surface with the code above. It's probably appropriate for your TNeoTheme class but most other class instances will not be global variables like this and will require other techniques. Actually surely there is already a TNeoTheme instance somewhere in this code already. Do a Find in Files search for "TNeoTheme.Create". Ignore the actual constructor implementation but you'll likely find something like: AnotherThemeInstanceVariable := TNeoTheme.Create; That variable AnotherThemeInstanceVariable is probably the one you should be using rather than the MyTheme variable I declared and created above. I hope you'll take this in the spirit that it's intended in but a quick look at the project on that video makes me think you've picked a pretty big mountain to climb for your first outing. Maybe go find a few gentle hills to train on first before attempting something as large and complex in scale as game development. -
Cost benefit analysis of moving project from Classic compiler to Clang
Lachlan Gemmell replied to Lachlan Gemmell's topic in General Help
Thanks for the heads up. We're in a controlled environment with high DPI screens for the users being a distant reality but it's good to know about the issues before they happen. -
Cost benefit analysis of moving project from Classic compiler to Clang
Lachlan Gemmell replied to Lachlan Gemmell's topic in General Help
Thanks for the feedback gents, it sounds like this particular project is best suited to stay with the classic compiler for the foreseeable future. As Delphi programmers we've worked with similarly sized and structured Delphi projects that take around 20 seconds to do a full build. With a current build time of around 10 minutes for this C++ project I can't even conceive of doing anything that would increase the build times even further. QuickReport no longer being supported isn't an issue as it was shipped with full source so we can move it to the later IDEs as we need to. As to why TwineCompile and the pre-compiled header wizards fail on this project, my guess is that the "uniqueness" of how the code has been structured in some places may be defeating them. We're gradually replacing that "uniqueness" with some more straightforward code and perhaps one day in the future those tools will run successfully. -
Cost benefit analysis of moving project from Classic compiler to Clang
Lachlan Gemmell posted a topic in General Help
We're a Delphi development company but we've inherited a C++ Builder project that we're now responsible for maintaining. The rough stats of the main application project are Rad Studio Berlin, classic compiler approx 500K C++ lines, 200+ forms, 100+ QuickReports, Quite a lot of very long files 10K+ lines Lots of very long functions 1K to 5K lines Compile and link time is about 10 minutes The precompiled header wizard fails on the project Twine compile fails on the project There's also a bunch of support BPLs (largest about 60K lines) and the application is built with runtime packages. We can't get it to link with runtime packages turned off but that's a question for another day. As Delphi programmers who haven't really touched C++ in decades this code base is extremely easy to read. It reminds me very much of the C++ I was taught at university in the early 90s. Swap curly brackets for begin/end and there is barely anything in there we don't immediately understand. I'd say it's unlikely that we would want to start using advanced C++ language features until much further down the line. At the moment we're just trying not to upset the apple cart. We will in the near future move from Berlin to Alexandria and then attempt to stay no more than a version behind from then on. We are yet to even give it a try but should we attempt a move to the Clang compiler? I guess the primary thing we're really looking for is a way to improve compile times. Is Clang faster than Classic? Are there other major benefits to Clang that as Delphi programmers we're just not aware of? If you would recommend switching to Clang, how difficult a process is it likely to be give that our C++ knowledge is not all that great.