Posts Tagged ‘Delphi’

FireMonkey vs. VCL

Monday, March 26th, 2012

I have finally started re-factoring hcOPF to support FireMonkey and Win64.  Win64 was a breeze, but supporting FMX is proving to be a bit of a challenge.

If I was EMB, I would be trying to make FireMonkey a write once compile on many platforms solution, and it is across Linux, Mac OS/X and Windows AFAIK, if you build an FMX application.  However, I would venture that most customers are looking to port their existing VCL codebase to access more markets, or at least leverage their existing knowledge, and might be a little hesitant to bet it all on a newly released UI framework sold and supported by a single vendor (especially after CLX).

All developers know, changing code tends to break what once worked, especially when you introduce more conditional compilation (check out my QC request 94287 to make conditional compilation easier to use).  To accomplish this end, the API usable to FireMonkey applications needs to have as much in common as possible with even VCL for Windows applications because at some point a developer will use code to manipulate the controls.  If it’s possible to use the same code for both platforms, you’ve saved in not having to maintain functionally duplicate code and in dealing with conditional compilation.

The ideal scenario would be to be able to specify either a FireMonkey or a VCL form DFM in a conditional directive, and have all the UI code shared (or minimal conditional compilation).  Of course, if you want to use the advanced functionality available in FireMonkey, perhaps this approach isn’t viable.  If you just want to target Mac OS/X without having to re-write your VCL application forms, and are using FMX for basic presentation of data, this would be ideal!  You wouldn’t have to invest the same effort to determine the merits of FireMonkey as a UI replacement for the VCL because you wouldn’t need to keep two separate UI source code trees in sync while FireMonkey matures.

So far, with my brief exposure to FireMonkey with XE2 I can see a number of problems in achieving the Write Once Compile for Many Platforms concept.  FireMonkey uses .Text instead of .Caption for some control window captions (ie: TGroupBox).  So while the control class may be the same, even some simple UI code cannot be shared with a VCL application.

Even non-visual code may be a challenge to re-use.  For instance, I use GetTickCount() to time activity in hcOPF.  I want to keep hcOPF compilable for users of D7 and above.  I personally feel that my coding productivity was higher in D7 with CodeRush than the Delphi XE with GExperts and CnPack.  Part of the reason for this is the code parsing the IDE performs in the main thread.  Type in Begin incorrectly, and you can be waiting for 10 seconds while the IDE tries to figure out what is going on.  That’s pretty sad on a 6 core system…but I digress.

GetTickCount() is implemented as an inline function in the implementation section in the System unit for MacOS and Linux, and the Windows implementation is in Windows.WinAPI.  Not a big deal to add a few {$ifdefs} to handle that, but GetTickCount() as defined in System is not accessible to other units.  So in order to use it, you will have to copy the implementation from System, and expose it.

From what I have seen of XE2 Update 4, FireMonkey is still not usable from a performance standpoint for replacing a normal VCL form. On my 6 core system with a Radeon 4250 the main form appears and you can visibly see the contents of the form background and content being rendered.  In this case, the form is just 4 edit controls in 2 separate group boxes using hcOPF Object Binding to populate the controls.

I think FireMonkey is a great concept, but adoption would be faster with an API more consistent with the VCL, and I think FMX has a long way to go before it becomes a viable replacement for the VCL and X platform Delphi becomes a true reality for more than the most trivial application written from the ground up for FireMonkey.

Embarcadero Licensing Limit

Sunday, March 18th, 2012

This weekend I went to install Delphi XE2 with Update 4 on my new development machine.  I had previously installed XE2 on my dev machine at work and in a couple VMs.  I upgraded my dev machine @ work to Update 4 on Friday, and then today, attempted to load XE2 Update 4 on my new dev machine at home, only to be told that I have exceeded the licensing limit.  In order to get the limit increased I have to email support.  It’s the weekend, so now I cannot install XE2 and do any work.

I called the support line for Canada, and of course the office was closed so I submitted a web request for technical support (case 00253157).  Fortunately, despite the inability to register XE2 EMB has allowed 14 days usage, so I’m not dead in the water.  It just nags you to register every time you start the product.  I’m sure this is thanks to all the XE2 “updates” that have required us to uninstall the previous version.  I’ve uninstalled and removed the registry settings (perhaps that was my mistake).

This kind of anti-piracy policy to me, is like hand gun registration.  The real criminals don’t register their hand guns, so it doesn’t prevent anything other than to make it more difficult for an enthusiast to own and use one, and definitely more annoying.

TADOStoredProc Parameter Returns wrong Value

Friday, December 9th, 2011

The other day I was trying to make a stored procedure call using hcOPF and kept getting a ‘parameter object is improperly defined’ error.  It has to be the most frustrating ADO error I’ve ever encountered, and I’ve come across a few in my time.  What makes it so frustrating is that the error message gives no indication of what parameter is the source of the problem.

As a developer, I would recommend you be as specific as possible when raising exceptions.  Imagine a stored proc taking 30 parameters, and the time it would take to figure out all the possible reasons why any one of them might cause this error when you have absolutely no idea why an API call you have made a thousand times before without a problem, now fails.

What I ended up doing is making the call manually in SQL Management Studio (SMS) to verify the back end was functioning,  Then I wrote a test application in Delphi that simply made the same call using a TADOStoredProc component with the same parameters I used in SMS.  The call succeeded, but one of the input/output values was not what I expected.  After experimenting at length, and discussing this situation with a co-worker, I discovered that the input/output parameter in question was a string defined as a varchar(max) in SQL Server, and it was being truncated at the length of the string I initially populated it with as an Input.  Once I verified this hypothesis, I filed a QC report (101665).

I probably should also have filed a report to fix the generic exception I encountered initially but I had already spent enough time isolating and filing the first bug report.  At some point you have to actually get some work done instead of helping fix someone else’s bugs ;-)

hcOPF - WYSIWYG with the DevExpress Quantum Grid

Tuesday, November 15th, 2011

When using the DevExpress grid with ObjectLists, there is currently a limitation that you must assign a root object to the hcUIObjectBinder.BoundObject property and this root object needs to expose the ThcParentedObjectList to present in the grid as a child of the root object that exists when the root object is constructed at design-time.  It may be empty, but it must be present, and provide a ListName in order for the object inspector to provide it as a discernible option.  Hopefully sometime in the near future I will have time to make it possible to bind to a standalone object list.  Here is a code snippet that I use in the AfterConstruction override:

  FLoggedInUsers := TftEmployeeList.Create(Self);
  FLoggedInUsers.Name := 'LoggedInUsers';
  AddChild(FLoggedInUsers);

While the ThcObjectDataSource does the majority of the heavy lifting for you in terms of presenting objectlists in the Developer Express Quantum Grid, there are times in which you need to programmatically modify the domain objects and inform the grid to update itself.  This can be achieved by calling:

GridTableView.DataController.CustomDatasource.DataChanged;

or the DataChanged() method of the TcxGridMediator.

In order to ensure the domain objects are updated immediately, I always set the ImmediatePost property of all grid editors to True.

Another thing to look out for are changes that are pending in the grid that have not been committed to the underlying objects.  For this I use the following code on the TAction.OnExecute event handler in my forms:

  if GridTableView.DataController.IsEditing then
    GridTableView.DataController.Post(True);

Of course you still have to persist the data if you’re using ThcParentedObjectLists that use CachedUpdates.  By default lists do not use CachedUpdates, so the grid Posts the data when you scroll to a different row, and the object layer writes the object data to the database.  The code above also results in a database update for for the current object in such lists.

If you use these tips, using hcOPF objects with the DevExpress Quantum Grid can actually be easier in some cases than a dataset.

TcxEdit Validation

Friday, October 21st, 2011

If you assign the Min and Max Value properties of a TcxEdit descendant, the control will call the OnValidate event handler indicating there is no error, but a subsequent attempt to convert the displayvalue into the target datatype and check if the result is within the range specified will result in an exception being raised. If you’re using something like Eurekalog or MadExcept to trap all unhandled exceptions this can be a major pain in the derrier.

There are only two ways I’ve found to deal with this issue:

1) Tell MadExcept or Eurekalog not to process this exception type

2) Do not define the Min and Max values in the control. Instead let the hcOPF validator deal with this, and I populate the OnValidate event with the following code to prevent an earlier exception from being raised (this code is for a cxDateTimeEdit):

if Error then
begin
  MessageDlg('The Date Entered is not Valid!',mtWarning,[mbOk],0);
  DisplayValue := DateTimeToStr(Now);  //reset the display to a valid value
  dtpBirthDate.SetFocus;
  Error := False;  //don't raise an exception since we've handled the error
end;

hcOPF and XE2 Unit Scope Names

Thursday, September 1st, 2011

I just installed the newly released XE2 and attempted to compile my current client’s project in the new IDE so I could start using it on a daily basis.

One of the first things I needed to do was compile hcOPF for XE2.  I expected not to have any issues since I am currently using hcOPF with Delphi XE.  Much to my surprise, the compiler kept complaining that it could not find Windows.dcu - an odd error considering Delphi has been a Windows development tool for over 15 years but understandable once you know that Unit Scope Names were introduced in this release to accommodate X platform development and units were reorganized.

Unfortunately, unit names in Uses clauses have to be fully qualified (winapi.Windows in this case) and this means using a whole bunch of {$ifdefs} for XE2 to provide fully qualified unit names.  It’s certainly an ugly solution, but I am happy to say that hcOPF now compiles under XE2 with the exception of the DevExpress package which must wait for a vendor code update.  The latest changes are in the SVN repo.

Why We Need to have Control over CodeGen

Thursday, August 4th, 2011

Have you ever wished that when you double clicked an event handler that the method generated by the IDE had some comments regarding the arguments passed so you didn’t have to consult the third party vendor’s help?

What about a simple TAction.OnUpdate handler, have you ever wondered why Delphi doesn’t inject the following code?

(Sender as TAction).Enabled := ^

or since it knows the component whose handler it’s creating (in this case let’s assume it’s named actTakeAction):

actTakeAction.Enabled := ^

BTW, the ^ would be the position were the cursor would be left.  The choice as to what code was generated could be a code style preference setting.

It’s this kind of polish you might expect if EMB practices dogfooding, or CANI (Constant and Never Ending Improvement) - QC97158.

The Need for a Smarter SyncEdit

Sunday, July 24th, 2011

When Mike Rozlog was visiting Calgary Alberta during the Rad Studio XE Tour one of the many features he demonstrated was SyncEdit. While SyncEdit is pretty cool from a visual standpoint, I don’t get why Mike was saying it’s such a great feature. First of all you have to select the scope in which to apply SyncEdit. It doesn’t even default to the entire unit, or the method in which the cursor is positioned. Then you have to locate the identifier(s) you wish to change and type in the new names. This isn’t really so different than using Ctrl+R to do a search and replace.  In fact, in most cases Ctrl+R is faster even if it doesn’t have the cool visual feedback.

Now if SyncEdit could be automatically invoked the moment you started modifying a method prototype in either the implementation or interface section that would be cool. It would be even better if the IDE could use that technology to create the prototype in the interface section when you added methods in the implementation section.

BTW, Mike, if you’re reading this, I’m still waiting for the answers to the questions I posed during that meeting, and later followed up with in an email. I know you’re busy, but the Tour was in Calgary on Sept. 9, 2010.

XE Parser causing long delays & Hangs

Sunday, July 24th, 2011

It appears my review of XE should have waited until I’ve had more experience with the IDE.

I just filed a QC issue (96552) because I am having a great deal of problems with XE becoming unresponsive.  It appears that when XE parses code in order to inject event handlers or provide code completion, it takes a long time to “think”, and sometimes if just gives up and decides to chew up all your CPU.  The solution to this specific issue seems to be making sure the unit being edited is present in your project as opposed to simply referenced by one of the units in your project.

I am running a stock version of XE with Update 1 now because I uninstalled IDEFixPack and GExperts thinking they might be contributing to the problem (and who can live without the code navigation capabilities of GExperts?).

If you’ve experienced similar issues I would encourage you to vote for QC 96552 and submit your own reports so EMB will give this issue some attention.  Code parsing in the editor has been a problem since D7 days and it scales poorly, so on bigger projects it apparently renders the IDE almost useless.  I have had to wait 5 seconds for the IDE to catch up on the code I’ve typed in because it was busy parsing (I presume), and I’m not a fast  typist.

Delphi XE - The Good, The Bad and the Ugly

Wednesday, July 20th, 2011

As a long time Delphi 7 user, I finally upgraded to XE.  It always takes a period of continuous use in the real world to get a feel for the environment, so I thought I would publish my experiences as a new user of XE, and my impressions for those contemplating an upgrade to this edition.  Most of my experience with a Galileo based IDE has been with Delphi 2007, so many of my comparisons will be between D7, D2007 and DXE.

The Good

XE is much faster than  any Galileo IDE I have previously used.  It’s form designer rivals D7’s in terms of performance, negating one of the reasons I refused to use Delphi 2007.  It’s compiler also seems to be much faster than D7’s and the code it generates also appears to be significantly faster.

I also love the debugger visualizers for TDateTime values.  Having to constantly create an expression using DateTimeToStr() to have a human readable value was a pain!

Of course, XE also comes with CodeSight Express, FinalBuilder, and BeyondCompare.  It has many incremental enhancements and some new features as well.  For the most part, I think EMB added the additional third party tools to make the upgrade more compelling because the IDE and compiler enhancements were not compelling enough on their own.  Most developers I think are waiting for the next version which to supposed to include X platform and Win64 support.

The Bad

The IDE does not appear to be as stable as Delphi 7.  In my first couple of days using the IDE I experienced multiple AVs in the RTL and VCL, and Eurekalog did not have an option to send an automated bug report, so I had to use the windows QC client and create one manually.  I wonder if EMB actually gets many of these issues reported as a result.

The code parser still blocks a developer from typing code while it parses the changes in the IDE.  IMHO this is an unacceptable limitation for an IDE.  A tool should increase a developer’s productivity, not stifle it by forcing them to wait until the editor is once again available, to accept further input.

Error Insight produces a lot of false positives so I have found it best to simply ignore it.

The F1 help still does not locate identifier help like D7 does.  For instance, pressing F1 with the cursor on IncMinutes doesn’t find DateUtils.

Unfortunately, DXE still suffers from the same problems I found in D2007.  It’s frustrating that functionality I found in CodeRush for Delphi beginning with Delphi 3 back in 1997 has still not found it’s way into the stock IDE.  For anything close, you have to use Castalia, GExperts, or CnPack (or some combination of them).

The Ugly

For some reason, when you launch Rad Studio XE it can take around 5 seconds on my machine before the splash screen appears.  I have found myself on occasion launching a second instance as a result of the delay between invocation and user feedback.  This is admittedly a minor irritation, but as a developer who invests a great deal of time ensuring his applications provide a high degree of responsiveness and user feedback, I think it shows a lack of polish.

I also like CompBar far better than the new palette.

Overall

Overall I would have to say that while DXE is not a leap forward, it is the best galileo based IDE to date, and certainly worth looking at even if you’re using a pre-galileo IDE and are happy with it.  While not a killer IDE, DXE is an improved platform that will form the basis for a lot of potentially exciting changes for Delphi.