Sunday, January 24, 2016

Delphi Developer Days Postponed

The annual spring Delphi seminar known as Delphi Developer Days has been postponed due to circumstances beyond our control.

Loy Anderson (the DDD event manager), Bob (Dr.Bob) Swart, and I have been working to put together this year's Delphi Developer Days, and we were getting close to announcing our dates when Loy and I suffered the tragic and sudden loss of a close family member. The circumstances of this event are going to require that Loy and I spend a significant amount of time helping out our family. Unfortunately, it is not possible to provide this help and at the same time invest the time required to make Delphi Developer Days a success.

We will make an announcement once we have re-scheduled the Delphi Developer Days dates. If you would like to be informed once new dates have been chosen, you can visit and click the link labeled Notify Me. I will also blog and tweet once we know when the next DDD event will be offered, as well as post this information to the official Delphi Developer Days site and the Delphi Developer Days Facebook page (

Thank you for your understanding, and we look forward to seeing you at the next Delphi Developer Days...


Friday, February 13, 2015

Using Trim in ClientDataSet Filters

I announced in my last blog post that an updated version of Delphi in Depth: ClientDataSets is now available, both in printed and in eBook formats. In response, a reader posted this question as a comment:

I used TClientDataSet.Filter. CDS's Filter support "Trim" statement in Delphi help doc. It support "Trim(Name, '.')". But, how to used the statement?

Here is the answer. Imagine that your ClientDataSet includes a Company field, and that you have set the ClientDataSet's Filtered property to True, and have entered a Trim statement in the Filter property.

When you call Trim you can pass either one or two parameters. If you pass one parameter, you pass the name of a field. In response, Trim will remove any leading and trailing white spaces (please see the first comment below). For example, the filter Trim(Company) = 'Unisco' will trim white space, and the filtered data will include records whose Company field includes 'Unisco ', '    Unisco', '  Unisco  ', and 'Unisco'.

If you include the second, optional parameter, Trim will return the value of that field after removing that leading and/or trailing character. As a result, Trim(Company, 'o') = 'Unisc' will match on 'Unisco', 'oUnisc', and 'oUnisco. Likewise, Trim(Company, '.') = 'Unisco' will match on 'Unisco', '.Unisco', 'Unisco....', and '...Unisco.'.

There are two variations on Trim. These are TrimLeft and TrimRight. Like Trim, these functions can also take one or two parameters. If you call TrimLeft or TrimRight with only one parameter, those functions will remove white space from the beginning or the ending of the specified field, respectively. If you pass a second parameter, TrimLeft or TrimRight will remove that character from the beginning or ending of the specified field, respectively.

For example, TrimLeft(Company, 'U') = 'nisco' will match on a record whose Company field contains 'Unisco' and 'nisco'. Likewise, TrimRight(Company, 'o') = 'Unisc' will match on a record whose company field contains 'Unisc', 'Unisco', and even 'Uniscooo'.

Monday, January 12, 2015

Now Available: Delphi in Depth: ClientDataSets 2nd Edition

I published the original Delphi in Depth: ClientDataSets book back in March of 2011. At the time I believe it was my 24th book on computer software, though I must admit that I've lost count. Nonetheless, I greatly appreciated the many kind comments I've received from readers since its publication, even though it is a Delphi book "about one component."

I decided to update the code samples following the release of Delphi XE7. My original code samples made use of the Borland Database Engine and the sample Paradox tables that shipped with Delphi, which permitted those code samples to be compiled and run without any additional configuration, something that I felt was important.

Things changed with the release of Delphi XE7. The BDE is no longer installed by default. In addition, Delphi Professional (and higher) now ships with an alternative database solution that can be used without any additional configuration. This solution, which makes use of FireDAC and InterBase, did not exist when the first edition of this book was published.

Once I started updating the code samples to use FireDAC and InterBase, I realized that there were also a few additions that I could make to the original book. For example, the new FieldOptions property introduced to TDataSet in Delphi XE6 gave developers additional flexibility in their use of persistent fields, such as calculated and internal calc fields. A nod to LiveBindings would also be warranted.

It didn't take long before I concluded that it was time to give the book a good once over, tweaking the odd description here and there, adding material where appropriate, and correcting a few missed typos. And, of course, using the new FireDAC/InterBase examples in the book's code listings. I also updated all of the figures in the book to show the latest version of Delphi at the time of my writing (XE7). The original BDE/Paradox examples are still available for download, which is necessary in order to support older versions of Delphi, those prior to XE5. XE5 was the first version of FireDAC to use the new FD prefix in component names, as well as the new FireDAC unit names.

Permit me now to anticipate a question that is sure to come up. "What if I bought the original edition of Delphi in Depth: ClientDataSets? Should I buy the 2nd edition?" Well, you probably don't need to buy the 2nd edition unless you want to have the most current version on your bookshelf. In updating the 2nd edition I re-read, for the purpose of correcting and editing, every page of the original manuscript many times. And, for the most part, I was very happy with what I had written. As a result, there are large segments from the original text that are unchanged, or have inconsequential changes in the wording. Yes, I did add sections on FieldOptions, LiveBindings, and special filter operations. There are also a few additional examples and extended discussions.

I should also note that you can use the new FireDAC/InterBase samples with the original book. Visit the book's download site, listed in Appendix A of the original publication. There you will find the FireDAC/InterBase code sample download, along side the BDE/Paradox code download. Again, these FireDAC examples only work with Delphi XE5 and later, so the BDE-based examples are still available for use with earlier versions of Delphi.

I should also note that I removed three chapters that appeared at the end of the original book from the 2nd edition. Those chapters covered DataSnap, with a mix of COM-based DataSnap and the newer DataSnap introduced in Delphi 2009. While ClientDataSets played a central role in the COM-based DataSnap (the obsolete version), they are one of many options in the new DataSnap. In the end, I concluded that the DataSnap chapters were out of place.

I am releasing two versions of Delphi in Depth: ClientDataSets 2nd Edition. The printed version is available on CreateSpace and Amazon. And, in response to popular request, I am releasing a PDF version on FastSpring. You can find links to these releases from the book's web site at http://www.JensenDataSystems/cdsbook2.

I am very happy with how Delphi in Depth: ClientDataSets 2nd Edition turned out. I hope that you are too.

Publication Date: Jan 07 2015
ISBN/EAN13: 150584018X / 9781505840186
Page Count: 358 pages, 7.44" x 9.69"

Web Site: http://www.JensenDataSystems/cdsbook2

Tuesday, January 6, 2015

Delphi Developer Days 2015 Agenda Announced

Ray Konopka and I worked over the holidays to prepare the agenda for Delphi Developer Days 2015, and I am very happy with the content we have planned for this year's tour.

As usual, we have created a balanced program that offers something for every Delphi developer. We have sessions covering the VCL (Visual Component Library) as well as sessions on mobile/FireMonkey development. Some sessions cover some of Delphi's newest features, while others apply to nearly every version of Delphi. In the database realm, we have client/server sessions as well as sessions covering distributed (DataSnap and REST) topics. We even have sessions covering some of the third party tools that ships with Delphi, including CodeSite and Fast Report.

Ray Konopka is the world's leading expert on Delphi component creation, and is also an expert on user interface design, and we've ensured that these topics are represented in the agenda. Best of all, all of the topics that I've mentioned will be covered in the Delphi Developer Days book that all attendees receive. Ray and I are now turning our attention to writing that book, and it is a creative process to which I am looking forward.

Delphi Developer Days 2015 is visiting four cities in the United States, Europe, and Scandinavia between 13 April and 11 May. And, we are currently in our very early registration period, and you will save even more if you register and make payment by 23 January, 2015.

For complete information on Delphi Developer Days 2015 locations, the agenda, session descriptions, and discounts, please visit

Space is limited. Register today to save your seat.

Thursday, December 18, 2014

Delphi Developer Days 2015 with Ray Konopka and Cary Jensen

In case you missed the official press release on Tuesday, let me be the first to share with you that Ray Konopka is going to join me in presenting this year's Delphi Developer Days 2015 tour. We will be visiting four cities in the United States, Europe, and Scandinavia this spring, and it is promising to be one of the best Delphi Developer Days tours so far.

Before I go any further, I want to assure you that my co-presenter for the past two years, Bob (Dr.Bob) Swart is still part of Delphi Developer Days. Bob is taking a sabbatical from traveling in the first part of 2015, and his humor and profound knowledge of Delphi will be sorely missed. But he will be back next year, and I am certain that he will have a wealth of new information to share at that time.

In the meantime, I have the supreme pleasure to have another of the world's great Delphi gurus joining me for this annual seminar tour. Ray Konopka is an Embarcadero MVP, winner of the coveted Spirit of Delphi award, and owner and founder of Raize Software, one of the first providers of third-party Delphi components. Another of his products, CodeSite Express, ships with Delphi.

I first met Ray when we served together on the annual Borland International Conference advisory board. That was more than 20 years ago. And I have to say that he is one of the hardest working and most focused people I've ever met. More importantly, he is an articulate speaker with a gift for communication. Whatever the topic, he understands the essential points, and presents them with clarity. You can't ask for more from a presenter.

But there's more, and it's particularly important when it comes to Delphi Developer Days. As everyone who has attended in the past knows, one of the hallmarks of Delphi Developer Days is the book that every attendee receives. Packed with hundreds of packages of material, it ensures that you take home more than an experience — you take home information.

This is why Delphi Developer Days presenters also have to be skilled writers. My first Delphi Developer Days co-presenter, Marco Cantù, is an excellent example of this. Marco has published more books on Delphi than anyone else, and I don't know anyone working with Delphi who doesn't own several of them. Bob, likewise, has published a number of books, countless tutorials, and many magazine articles. Who hasn't found the answer to some impenetrable problem from Bob's posts? I know I have.

Ray, likewise, is an author. He wrote the Blazing Pascal column for PC Techniques, and the column Delphi by Design for Visual Developer Magazine. Furthermore, his book, Developing Custom Delphi Components was groundbreaking (as was the follow-up, Developing Customer Delphi 3 Components), and it deserves a place on every Delphi developer's shelf.

Ray and I are still working on the agenda for this year's topics, but I can assure you that there will be lots of great information. I will blog and tweet again once we've posted the topics. In the meantime, you can read the press release at

For more information, visit And, I'd be remiss if I didn't mention that we're currently in the very early registration period, and you can save 25% if you sign up soon.

Let me finish by now returning to my main point. This year's Delphi Developer Days tour will be one to remember. Ray and I are looking forward to it, and I hope you are, too.

Thursday, June 19, 2014

Ode to Code

Ode to Code:
Reflections on Software Development in Iambic Heptameter
by Cary Jensen

While true, it's said, there's work to do, and now it's time to start
This is my task, so plain and clear, it's science, love, and art

My slate starts clean, a screen pure white, no logic bears my will
Upon this page, through thought and might, it's my intent to fill

I make my plan, each step designed, my spec is well thought out
It matters much, oh yes it does, there can't be any doubt

My fingers fly, the logic pours, a waterfall sublime
I see my goal, I type and click, I lose all sense of time

My words are key, my syntax right, and subtly reserved
I own this world, I'm in control, though humble, numb, and nerved

It's getting close, the tension firms, anticipation's high
I hit F9, compile and run, I feel success is nigh

But wait! It fails! How can this be, catastrophe I feel
I've lost my touch, my senses fail, my mortal soul revealed

Oh, damn the Gods! This logic broke, a bug I cannot find
I check the source. I check each line. I think I'll lose my mind

But what is this, a misplaced test, can this thing truly be
Compile again, and it just works, I'm now in ecstasy

I document the change I made, my comment explains why
I always try to take this step, to prevent a future cry

Relaxed, I am, my goal achieved, a conquest satisfied
It's what I do, a job compelled, a source of joy and pride

You beauty mine, my cherished child, the product of my soul
From white blank slate to final code, a void has morphed to whole

No eye will see this gold I've spun, no heart with feel its beat
It lies beneath the interface, resplendent and complete

I scratch one item off my list, but I cannot pretend
With this task done, there will be more, my work will never end;

Copyright © 2014 Cary Jensen. All Rights Reserved

Tuesday, May 13, 2014

Simplifying LiveBindings Configuration in Mobile Apps Using Frames

Unless you have been sleeping under a rock, you already know that Delphi can create native executables for both iOS and Android mobile devices. These applications must be created using FireMonkey, since FireMonkey is Delphi's cross-platform component library. When using FireMonkey, most developers make use of LiveBindings and the LiveBindings Designer to enable data awareness in the visual controls.

Unfortunately, the evolving best practices for mobile application design in Delphi has relied on applications based on a single form, where a TabControl containing two or more TabItems defines the various screens (pages) of the application.

This design avoids some of the issues associated with having multiple forms in a mobile application. For example, Android applications do not support the concept of non-modal forms, and although iOS does, the active form always occupies the entire screen.

Another issue related to having more than one form in a modal application is related to mobile device orientation. Specifically, many applications will re-orient themselves when a user rotates their device 90 degrees, switching from a portrait view to a landscape view and back. The problem here is that the OnResize event is received only by the form with focus. No other forms in memory receive this event, and therefore may not be aware that orientation has changed.

If a mobile application needs two or more pages (or views or forms or whatever you want to call them), this can be achieved by including a single form on which a TabControl appears. You then create one TabItem for each page of the application, and provide user interface elements such as menus, tabs, or buttons to navigate between the available TabItems. In fact, this is the model used by all of Delphi's multi-page wizards in the Object Repository, which you can select from when you select File | New | FireMonkey Mobile Application from Delphi's main menu.

While the TabControl/TabItem configuration works, it introduces an unwanted side effect. Specifically, if you use the LiveBindings Designer to visually bind your controls to BindSourceDB components, every control appears on the default layer, and the designer quickly becomes cluttered, making it difficult to create and manage your LiveBindings. And even though the LiveBindings Designer permits you to define layers on which to display select controls, the clutter remains a challenging issue. And, the clutter increases in direct proportion with the overall number of controls on your one form. This can be seen in the following view of the LiveBindings Designer for a somewhat simple two TabItem TabControl.

Unfortunately, a two-page mobile application is uncommon. Most mobile applications will have many more pages (TabItems), and the problem of clutter in the LiveBindings Designer can get completely out of hand.

There is another solution, however, and it can be found in FireMonkey frames, which were added to FireMonkey in Delphi XE3 (the VCL introduced frames in Delphi 5, and I have found them to be invaluable in my Windows applications).

Here's the deal. A frame is a design surface, and each design surface in Delphi has its own LiveBindings Designer. As a result, only those controls that appear on the frame automatically appear when you view the frame's LiveBindings Designer.

Here is what you can do. In the simplest case, you create one frame for each TabItem that you will include in your single form application. You then place each frame into its corresponding TabItem, and then align the frame to alClient. If you want to get really clever, you might even place two or more frames into a single TabItem, but that is a design issue.

For each frame, you include in its uses clause only those data modules whose TDataSets you want to bind using LiveBindings. The result is that each LiveBindings Designer includes only a subset of controls that appear in the single form. This can be seen in the following view, which shows a frame that replaces the controls that appear on the first TabItem of the form whose LiveBinding Designer was shown earlier in this post.

The problem is not entirely solved. Specifically, the one form of your application on which the TabControl appears will display all of the objects from all of the frames placed on the individual TabItems within the LiveBindings Designer when the form itself is selected in the designer, so the clutter still exists. But you will not really care. As long as you can configure LiveBindings at the Frame level, you will use the LiveBindings Designer only with individual frames, in which case only the components on the selected frame will be visible. Furthermore, the benefits of this frame-by-frame configuration will increase in direct proportion to the number of TabItems on your form.

This is just one of the tips, along with many other fun and useful Delphi techniques, that I will be covering along with Bob Swart (Dr.Bob) at this years Delphi Developer Days 2014 tour. We have completed our first two cities in the United States, and the response was excellent. We now continue on to Frankfurt, Germany on May 26th and 27, Amsterdam, The Netherlands on June 12th and 13th, and London, Great Britain on June 18th and 19th. For more information and to register, please visit

Copyright (2014) Cary Jensen. All Rights Reserved