I‘ve not written a while about programming, let alone anything about that mailing program, RoundAbout. Today’s subject is the Windows TreeView control and its data section, the TreeNodes. As you probably know, a TreeView shows data in an hierarchical way, allowing users to ‘expand’ or ‘close’ so-called TreeNodes, so to expose or hide data they do and don’t want to see. TreeNodes in the Windows world can have user-data attached to it and often, developers will use this to store program specific information. I believe in .Net, this data propery is called ‘Tag': in the Delphi world, it was called plainly ‘Data’. So code-wise this could look like this:
var Node: TTreeNode;
/* FolderData is a pointer to a record */
Node := TreeView.Items.AddChild(Node, FolderData^.Name);
/* Attach the FolderData to the current node */
Node.Data := FolderData;
Early in the process of development, it was noticed that any font or even layout changes caused severe crashes in the TreeView: The TreeView in RoundAbout holds account and message/mail folder information via each TreeNode’s Data member. After a long investigation, I noticed that this was caused by the Delphi TreeView control itself: whenever a window anywhere was refreshed, Windows would send a message to the TreeView control to refresh and recreate itself. Let me say that again: whenever a font was changed in RoundAbout, this would trigger any TreeView to recreate itself. I think this issue was resolved in later versions of Delphi, but I decided to create my own control (PMTreeView, code here) to preserve the data with the following premises:
- Override CreateWnd and DestroyWnd
- Upon destruction of the treeview window, save the data for the nodes to a memorystream.
- Upon creation of the treeview window, (if available) load the node data from the memorystream.
- Trigger an event to notify the developer that the Data structure has changed for further activities.
As I mentioned earlier, I believe in subsequent Delphi versions, Borland fixed this in their own TreeView controls. However, for a piece of code that I debugged and coded in a night or so, my own PMTreeView control wasn’t too bad of an implementation.
One of my biggest pet peeves is ‘AutoComplete': the functionality of a text box to suggest (and complete) previously entered data. I’ve seen many bad implementations and the one fresh out of memory I can remember is Opera’s URL box, which I’ve mentioned a many times.
For RoundAbout, I implemented the AutoComplete in the ‘MailProperties’ box (see image above and video right here): The code can be found around this url, look for the method Memo3KeyUp). If I look at the code now (and to be honest, I’m hardly a Delphi programmer these days), I have no idea what I was doing: I recall that in some conditions the Autocomplete should stop doing its thing most notably when the user uses the navigational keys. Additionally, the partial matching was troublesome at one time also. What surprised me most was that everything could be implemented in one event (The KeyUP event of that particular memo box). Messy.
Eventually, I grew up and when there was a request to make an autocompleting editable combobox, I was smart enough to clean up the code and section it off in several methods (KeyUp/KeyDown and OnChange). This code end up living in its own component (PMComboBox): the code is so clean that I’m certain you should be able to take this code and rewrite it in other Windows-based programming languages.
I get cranky when I see people use regular expressions or simple substring routines when extracting strings from, for example, e-mail addresses. The first method, while powerful, is memory hungry, the second method is plain childish. You should only use substring/copy methods if you’re hundred percent certain that the data is formatted and well-formed (that is, it comes through exactly as you expect it to. In the case of e-mail addresses, this is of course, not true. After all, e-mail addresses can come in any format. The following samples are all legal: “email@example.com”, “firstname.lastname@example.org (Hey You)”, “ Hey You”, “Hey, You “. Your simple substring copy function would most likely have troubles resolving all of these e-mail variants.
During my Roundabout tenure, we ran into issues where extraction of names/e-mail from e-mail headers didn’t work out as originally planned. I was not surprised to find those evil substring routines in the code and literally rewrote that into a state machine (look for HeaderAddressToStringList). Extremely elegant and very effective.
Why use a state machine then? Because with string operations like this, looping through a string is a lot faster than trying hundreds of “if conditions” to cover all these e-mail cases. Keep in mind that simplicity is the key though: the more states you define, the complexer the code.
Last weekend, I decided to pick up my Delphi compiler and work a bit on Fandro: in real life, I found out that I wanted to be able to launch Fandro from Explorer’s context-sensitive menu and henceforth, I worked on adding support for this.
I always thought doing Win32 was fairly simple in Delphi. Additionally, Borland used to have excellent demos and sample apps with full sources. However during this short coding stint, I admit, programming in Delphi ended up being sort of a pain, mainly because I’ve been by Visual Studio. And I always thought the language’s assignment statement was silly. There’s another thing of Pascal that has bothered me for ages: the fact that to return values from functions you can use the special ‘result’ variable or the function’s name. As in:
function MyOperation(a, b : integer) : boolean;
result := (Ord(a > b) = Ord( b < a))
function MyOperation(a, b : integer) : boolean;
MyOperation := (Ord(a > b) = Ord( b < a))
I don't consider myself a Delphi programmer anymore: however, don't you just love the part where compiling code actually means generating a stand-alone Win32 application?
Note: I believe that Delphi statement above holds the answer of life and it's this year's Valentine's present to you.
Everytime a Wix script (Windows Installer XML) fails to compile, it logs ICE errors. For some kind of reason, whenever these errors or warnings pop up, I keep humming the tune of Vanilla Ice’s “Ice Ice Baby” (Youtube, if you’re so obliged).
I have always been a fan of NSIS (@sourceforge), the Nullsoft Installer System, but I hear that NSIS’s installers don’t run 100% flawless on Vista systems. Wix then, and that’s not because it’s the best system: it’s slow, clunky and the errors are highly Vanilla Ice, Baby.
A couple of years ago, I used to use InnoSetup, but nowadays, I find it too tied to the Delphi language: There’s no doubt in my mind that Embarcadero has great plans for Delphi, but their “reasons why you should buy Delphi” remind too much of the old ‘slogan’ days. You know: “RAD”, “productive”, “rich” and “ease”. I don’t want that: I want Push-Button Spreadsheet Power.
And shit, yo.
Some stuff I ran into earlier.
I read that Windows 7 (Microsoft much-touted successor of Windows Vista) is positioned as the ‘Linux Killer’ (original article at Computer World). From that article:
The threat to Windows comes entirely from “netbooks” — lightweight, inexpensive laptops that typically use Intel’s low-powered Atom processor and don’t come with substantial amounts of RAM or powerful graphics processors
The last time I checked, was that Linux’s was actually taking out more bytes (ha-ha) out of the Windows Server market, which is basically because the open-source operating system is so easy to install on older hardware and that. Well, that is if you use Debian, of course.
A NASA team announced the discovery of cosmic radio noise six times louder than normal. Apparently, this noise happened in 2006 and after plenty of peer reviews, it appears that this (yet unknown) noise was not related to anything that humans do on earth. However, the researchers are still not sure what created this noise.
You thought we suffered economic hardship? In Zimbabwe, the government just introduced a $50 billion note, which (apparently) just buys you a loaf of bread in that same country. I am curious who’s portrait is prominently showing on that note, but on preview, I don’t think too many politicians (except for the dictator kind of types) would want to have his (or her’s) face on a bill that’s probably only usable for wiping one’s nose.
And the best is for the last: If you’re into fractals (sure you do), here’s an open-source Fractal Flame Editor (Windows only: for other OSes look here). Surprisingly, it’s written in Delphi 5.
Staying on the programming topic: One of the best parts of Roundabout (previously) was the filtering mechanism: before mail was downloaded, the user could (if needed) invoke the Filter dialog box and mark which mails were going to be downloaded (or left/deleted on the server). This happened all in a thread, where connections to SMTP and POP servers were made and commands were issued, synchronously (“blocking”, so you will). The threading class that took care of this was (appropriately) named ‘TOnlineThread’ and resided in a file called TDOnline.pas.
Many times I’ve cursed the existing threading code: I spent plenty of hours fixing up the code, or rather making the code thread-safe, as in, wrapping code that calls the main-thread (the UI thread) in so-called ‘Synchronizers’. Looking through the current code, there were plenty of changes done to this unit (the CVS history only spans a short time and doesn’t count the changes made prior to January of 2005). Anyway, if memory serves well, there were issues during the sending of mail (which happened in that thread) and the update (count of left-over messages) in a mailbox (which resided on the main UI thread) and I ended up correcting the issue, soberly stating:
- FIX (Arthur): Threadsafe RefreshNodes in TDOnline + additional processing…
Which was followed by a more cryptic:
- FIX (Arthur): Sharpened the RefreshNodes/Tree traversal.
Before you click the ‘Continue’ link, you may want to have this link at your disposal, which may explain the whole gimmick below.
I was looking for older code through some older projects and I ended up looking at the code of RoundAbout, a Delphi project I headed with a German (Roland), an American (Marcos) and plenty of other contributors. I thought, I might just as well make this an opportunity to breathe new life into this specific category: There is some exciting and funny code in the project and I wouldn’t do the project good by not showing the effort to collectively create something good out of nothing.
But first: In the early 2000s I ended up looking for an e-mail client for Windows. For years I had been using Eudora, but, I got a bit tired of looking at the ads that Qualcomm pushed upon users. I initially looked at Phoenix Mail, an e-mailer initially programmed by Michael Haller which in turn was passed on to American Delphi developers. Via that mailing-list I discovered Roland’s excellent modernized branch and, as any good open-source branch, I ended up branching his version into RoundAbout because we couldn’t agree on many issues: I believed in going more in-depth (technically speaking) while Roland was more or less adopting a wait-and-see, conservative approach. Both approaches had their successes, and both our branches had attracted a variety of Delphi luminaries and dignitaries (I’m looking at you Duntemann), including offers of help from the original Phoenix Mail branch. In 2004, RoundAbout was left for what it was and like many open-source projects, it died a silent dead. However, without doubt, its code continues to live on in the original branch(es) or is probably floating around on the Internets. I wouldn’t recommend people to try the e-mailer nowadays: it works fine but might look odd on Windows XP and higher.
This brings me to the first piece of code I’d like to point at, which is the ability of adding or dynamically creating toolbars and toolbar buttons: It was heavily pushed by Marcos and it required so many code changes, that I ended up taking the challenge, provided that:
It is possible to create new toolbars and buttons: however, the maximum of toolbars should be 255, the maximum of total buttons (application wide) are 65,5xxx (the number that fits in a word).
I mean, 65 thousand and some buttons should be enough for everybody, right?
I thought Mark’s posting about the new Adobe Acrobat 9 was the hilarious. If you’re into more snark, try the Adobe Acrobat 9 installation guide as done by the MicroPledge site.
I was doing some Delphi coding earlier this week and was reminded of the fact that the
Borland Inprise Borland Codegear… OK, let me try that again. I was doing some Delphi coding earlier this week and I had noticed (before) that the former Borland tools were bought up by Embarcadero Technologies. I could say this nicely, but lets keep it friendly for now1: at least the designer of Delphi (and earlier Pascal compilers) ended up designing the C# language and .Net Framework (see also The Borland Conspiracy Theory). I only wished that the Pascal language designers had done away with the silly ‘assignment’ syntax (:=): you know, with this emerging emoticons craze on these Internets I could say it slightly resembles a guy growing a thick beard. Oh wait, this just came through my earpiece: the emoticons craze is so early 90s.
1 Though, programming in Delphi taught me to write solid leak-free code, I guess. Oh the joys of freeing up objects yourself
Meh: Earlier I found out OWL is a web ontology language and that it has nothing to do with the OWL that was wrapped in a box of Borland compilers (Wikipedia on Object Windows Library). Alfons should know more about OWL, unless he hand-coded all his Pascal and C++ code the WinAPI way. I can’t remember. What I do remember was the shock in the developer world when Borland decided to drop OWL in favour of VCL. The rest is history. Of course (with all things legacy), OWL has been picked up by enthusiasts. Slightly related: why do I still use the T-prefix in every other program language I program in? Where did that come from? I presume it was always part of OOP world.
I saw a picture of a person I went to school with and I exclaimed something like ‘Hey, that’s that guy that had all the girls in class swoon’. Afterwards, I thought that wasn’t appropriate, but then, maybe this is what happens after many years. Think of all these thoughts people have when they remember me (‘Oh god, those were the guys with the straight 9s or 10′). It wasn’t my fault. Having Alfons as a formidable competitor was just way too tempting. This also reminds me of the first years of secondary school [which is more or less comparable to the first years of highschool]: for straight A’s students we were actually loosely managed by our parents. The secret of studying is to take things seriously when you’re twelve years old. The other secret is that you obviously need parents who are not too overly involved and give kids the freedom to experiment.
One point with which I want to close off for today: Ownerdraw stuff in C#. Yesterday, I was comparing code to create owner-draw listboxes and comboboxes in both Delphi and C# and noticed how remarkably easy it’s to switch from Delphi to C#: if you did this in Delphi before, the procedure is almost the same in C# (once again this is not surprising if you know who designed C#, earlier at xsamplex)
In Delphi for example, most VCL components have an ‘ownerdraw’ property: switching this one to either true (or to a specific enumerated value like ‘Ownerdrawfixed’), you generally capture two events to draw (and colour) individual items. The same is true for C#: you set the DrawMode property either to ‘OwnerDrawFixed’ or ‘OwnerDrawVariable’. Which one you choose depends on what you plan to do with the listbox.
As mentioned earlier, code to actually draw an item is done in an event: for this C# has the DrawItem event. I’m not going to explain the code, because it should speak for itself.
private void cboDataSources_DrawItem(object sender, DrawItemEventArgs e)
if (e.Index > -1)
TDataSourceType nt =
(cboDataSources.Items[e.Index] as TDataSource).SourceType;
// Background first!
if (nt == TDataSourceType.System)
// Draw image from image list...
imlSources.Draw(e.Graphics, e.Bounds.X, e.Bounds.Y + 1, 0);
e.Font, Brushes.Black, e.Bounds.X + 18, e.Bounds.Y + 2);
// ... other code removed...
// and then draw the focus rectangle...
What do you mean, it smells like Delphi?
Yesterday, I received an e-mail from CodeGear that the new Delphi platform has been released (or here for fancy images). A bit expensive and I fear for the future of the Delphi environment: notice how the environment now closely seems to mimic the Visual Studio IDE. If you need to create genuine (native) Win32 applications, I guess there are only 2 viable languages left: Object Pascal and C++.
Back in the days, Alfons and I (and many others) wondered why the makers of Turbo Pascal never considered standardizing the language: At that point, Alfons turned to C++ while I decided to focus on Delphi. Later on, on a professional level, I made the decision to leave Delphi and go on the SQL, C and Uniface route. That was the best decision I ever made in my career: first of all I was seriously thrown in the deep. Secondly, I learned to love VMS, and (from then on) other Unices.
But going back to CodeGear: I see that they released their PHP for Delphi product, which appears to be the Delphi IDE geared to create PHP websites (it doesn’t generate executables, no). It includes the (so called) PHP VCL. Right, the point of that is?1.
And maybe that’s the problem I have with older Borland products: They are generally good products and obviously, Delphi is one of them. But, the main question is, where is the roadmap (Missing roadmap from the CEO’s notes)?
While doing some ownerdraw stuff in regular Windows stuff (stuff is my favourite word, as you can see), I noticed something weird: I was forced to ‘refresh’ regions by code, instead of relying on the tools of the specific programming language. For a single moment I was thinking I was seeing ghosts, but apparently, I wasn’t hence the use of a refresh in a specific piece of code that allowed me to merge a couple of cells in grid.
Now for the gifted among us, how do I make that ellipse look 3D (and don’t tell me to shift the ellipse a couple of pixels up or down, drawn in a different colour).