Archive for August, 2009

Better than you’ve been told…

Strangely, the Delphi 2010 hype machine have slowed down somewhat as we got closer to release date. But I just had my first full day with the new IDE and it’s good.

The installer, I have to say, deflated me somewhat. It was slow, and it kept prompting me for the various bits that needed to be installed – DBPack, Boost and Rave. Unfortunate that they managed to regress in that regard, because the new black look of the installer looks really sharp. Quite unlike 2007/2009’s dove-gray slug.

But i wasn’t let down by the actual product.

All the much-hyped bits are there, and they all seem to work. As noted elsewhere, IDE Insight can do with some synonyms and other little tweaks. But it pops up in under a second and it found everything I went looking for. In time, I’m sure it will become even more handy.

I really wish I had some place to use the new touch features, but that is simply not what my day-job entails. I decided to give it a whack in any case. Literally under a minute’s worth of work to get it going.

I even tried designing a gesture of my own. Not only was it dead simple and intuitive, but the gesture editor even gave me let me know when my gesture was too close to another one. Real slick. Useless to my day-to-day work, but really slick.

What also pleased me are the little gems I found as I went along – Microsoft’s one stated aim with Windows 7 was to delight “early and often” and Delphi 2010 certainly emulated that second bit. Here are the little bits I stumbled upon that I didn’t see mentioned often or at all:

  1. Tab indents a block of code, Shift-Tab unindents. How obvious is that? I use lots of editors (Notepad++ and Visual Studio 2008 both very often) and it’s nice to see Delphi adopt something that’s become a convention.
  2. DBGrid is themed! Fine, they are a little late on this one but a simple recompile of your app can give it an instant UI update.
  3. Class constructors. I know Alan mentioned them after Delphi Live but I didn’t see any mention about them in the recent flurry of information. These are really cool, and I can think of a few places that will receive immediate attention.
  4. Various different views and new icons in Project Manager. Much more intuitive now, and they have even put in some effort to reduce that ridiculously long context menu. The one in the editor though, still sucks.
  5. Find in files now support file groups. So Delphi source folders go into one group, my project source go into another and all the Delphi demos and my own test/play projects go into another. Or something like that. This looks real handy.
  6. New icons for the IDE and applications. This sounds silly, but I presently have icons for Delphi 2006, 2007, 2009 and 2010 on my quick launch bar. Guess which is the only one to look distinctive. And I think the new icon is very cool.
  7. Windows 7 ITaskbarList3. You know, for all the cool jump lists, progress bars and thumbnail toolbars.

The real winner for me though, is the new RTTI library. I know all the rave reviews have been about attribute support – and I’m sure that rocks – but I was already blown away before I got to it. Just querying objects for their characteristics has now become so rich that it is bound to change the way many things are done.

I have a particular example in mind that I’ll show in a few days.

Comments (6)

Delphi’s broken bookmarks

Delphi 2009’s blue chip features were Unicode support, generics and anonymous methods. Most developers expected Unicode support to be the one to introduce the bulk of the migration headaches. But as with most Delphi versions, Delphi 2009 also saw a number of changes that didn’t quite make it into the marketing material.

Perhaps I’ll get into some of the beneficial ones in a later post – possibly just in time to follow it up with a Delphi 2010 version. But for now I’d like to look at one of the more perplexing ones.

Delphi’s TDataSet class has for the longest times supported bookmarks. If you still waste your time with TDBGrid, you’ll use these whenever you allow the user to multi-select.

Myself, I use these extensively with TVirtualStringTree – one free control worth a serious look if you don’t use it already – to display TDataSet records as rows in a grid.

So on Delphi 2007 and before, you used bookmarks like so:

Bookmark := CDS.GetBookmark;

and a little later:

CDS.GotoBookmark(Bookmark);

where CDS is a TDataSet – in my case usually a TClientDataSet. And Bookmark is a Pointer.

On Delphi 2009 this doesn’t quite work as expected. You see, in Delphi 2007 GetBookmark returned a Pointer and you would declare Bookmark as a Pointer.

In Delphi 2009, GetBookmark returns a TBookmark, which is an alias for TBytes. And TBytes is a dynamic array of Byte. If it hasn’t sunk in yet, read it again.

That’s right. In Delphi 2007, GetBookmark returned a regular, unmanaged pointer. In Delphi 2009, it returns a managed dynamic array pointer.

So what? Well, in the past you would get the bookmark and do with it as you please until you were done with it. And you could still do the same, providing that you declare my Bookmark variable from above as TBookmark.

If you don’t, the bookmark gets freed at the end of the method that you called GetBookmark from. Which makes it impossible to return to the bookmarked record from another record.

In case you don’t know Virtual Treeview, here’s the rundown: You add nodes and attach data to those nodes. Instead of storing strings, the tree would store only the data you give it. And the text displayed in the grid gets picked up in event handlers and not stored anywhere.

So if you simply used to store the pointer to the bookmark (like me) you’d suddenly keep getting annoying “Record not found” exceptions.

I can think of two possible solutions. The first is obvious – declare your bookmark as TBookmark. But that doesn’t work in my Virtual Treeview scenario and there are possibly many other people who stored bookmarks as untyped pointers in TList or something similar. In that case, you should simply cast when you do the assignment:

TBookmark(Bookmark) := CDS.GetBookmark;

or in Virtual Treeview:

Bookmark := nil;// Required so your assignment doesn't attempt to free a non-existent array
TBookmark(Bookmark) := CDS.GetBookmark;
Tree.AddChild(<strong>nil</strong>, Bookmark);

It’s a simple fix, but one that you will need to make at every place where you store a bookmark. Either that, or changing the bookmark declaration.

I can’t even begin to guess what possessed our friends at Embarcadero to do this. In fact, I don’t quite see what they intended to fix by making the change. If the idea was to replace the untyped pointer, then PByte – an unmanaged type – would be a far better alternative to TBytes.

But it’s an undocumented caveat. Or it was – until now.

Comments (8)