Give a Delphi TToolBar a Proper Themed Background

A stock Delphi TToolBar will paint with a flat color or with a gradient. This is how a plain TToolBar appears in Windows Vista and Windows 7:

It looks okay, but Windows Vista has been around for a long time now, and this toolbar looks a bit dated. It doesn’t scream "old," but it certainly doesn’t pop out as "shiny."

What we want to do is have the toolbar paint its background with the current operating system theme. This will give us a nice toolbar look that conforms to the current them, looks modern, and is backwards-compatible with Windows XP. Delphi (2007 and 2009) doesn’t offer us a property to do this, so we need to add some code to the toolbar’s OnCustomDraw event.

First, we add Themes to the form’s uses clause. The Themes unit contains Delphi routines for accessing the Windows XP and Vista Theme API.

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ImgList, ToolWin, StdCtrls, Menus, Themes;

Next, add the TToolBar’s OnCustomDraw event handler (double-click it under Events in the Object Inspector). And add the code to paint the background:

procedure TForm1.ToolBar1CustomDraw(Sender: TToolBar; const ARect: TRect;
  var DefaultDraw: Boolean);
var
  ElementDetails: TThemedElementDetails;
begin
  if ThemeServices.ThemesEnabled then
  begin
    ElementDetails := ThemeServices.GetElementDetails(trRebarRoot);
    ThemeServices.DrawElement(Sender.Canvas.Handle, ElementDetails, Sender.ClientRect);
  end;
end;

A little explanation:

ThemeServices.ThemesEnabled lets us know Themes are actually being used, so we don’t try to paint a theme element on a system that isn’t using themes.

The record variable ElementDetails is used to tell Windows what kind of theme object we want painted. In this case, we are using the rebar background, specified with a call to ThemeServices.GetElementDetails(trRebarRoot). We use ThemeServices.DrawElement to paint the rebar background on the TToolBar’s canvas.

This is how our Toolbar looks now:

With just a few lines of code, our application looks like it has had a major face lift.

There is still something left that can be done to improve the appearance of the form a little more. Ideally, the toolbar should be blended a bit with the menu above it. You only need to do this if you are using a standard TMainMenu on the form’s Menu property to display your menu.

Change the OnCustomDraw event handler for the TToolBar so it looks like this:

procedure TForm1.ToolBar1CustomDraw(Sender: TToolBar; const ARect: TRect;
  var DefaultDraw: Boolean);
var
  ElementDetails: TThemedElementDetails;
  NewRect : TRect;
begin
  if ThemeServices.ThemesEnabled then
  begin
    NewRect := Sender.ClientRect;
    NewRect.Top := NewRect.Top - GetSystemMetrics(SM_CYMENU);
    ElementDetails := ThemeServices.GetElementDetails(trRebarRoot);
    ThemeServices.DrawElement(Sender.Canvas.Handle, ElementDetails, NewRect);
  end;
end;

What we’ve done is introduced a new TRect so we can modify where the background painting starts. NewRect is initialized to the toolbar’s client rect coordinates. Then we use a call to GetSystemMetrics to get the height of a menu bar, and subtract that from the top of NewRect, and pass NewRect as the drawing rectangle to DrawElement. This starts the rebar background at the same position of the menu, giving us a more blended look for the toolbar:

Now the toolbar looks more "attached" to the menu bar.

Note that the toolbar paints well under Windows XP, too:

Giving a stock TToolBar a modern-looking background only takes a few lines of code and is an easy way to improve the appearance of your application. Once you’ve done this, you’ll want to start poking around in Themes.pas to see what else you can add some theme magic to.

Implementing a Partial Serial Number Verification System in Delphi

Most micro-ISVs use a serial number/registration code system to allow end users to unlock or activate their purchase.  The problem most of us have run into is that a few days or weeks after our software is released, someone has developed a keygen, a crack, or has leaked a serial number across the internet.

There are several possible solutions to this problem. You could license a system like Armadillo/Software Passport or ASProtect, or you could distribute a separate full version as a download for your paying customers. Each option has advantages and disadvantages. What I am going to show you is a way to keep “rolling your own” license key system while making working cracks harder for crackers to produce, and working keygens a thing of the past.

Continue reading Implementing a Partial Serial Number Verification System in Delphi

Delphi 2007 Update 1: CodeGear Delivers

A while back I blogged about my major disappointments with Delphi 2007. I’m happy to say that the problems D2007 had, which prevented me from using it for project development, seem to have been adequately addressed with CodeGear’s first service pack.

To wit, I’ve just used Delphi 2007 Update 1 to compile what I hope to be the next release of Daily Bible and Prayer — version 2.1, a small update. I was able to do all of the .1 development in D2007 without anything holding me back, and the finished product works as it should. If all goes well, DBAP 2.1 will be released (as a free update) later this week.

Delphi 2007 for Win32: Oops!

Delphi 2007 — Oops!

Earlier this month I blogged about my enthusiasm about Delphi 2007 and CodeGear. I did so before D2007 was shipping based on what I saw in the betas. I meant every word of it.

But.

Hold on a bit. D2007 has shipped, but there exist a couple of serious problems. Suffice it to say I can’t build a production-level application with D2007 due to some nagging open issues — issues that should never have made it into the final release. It appears that CodeGear was so in need of revenue in 1Q 2007 that they simply had to get it out the door this month. Unfortunately, this means that it’s not good for releasing applications until they release a hotfix or two to address two major issues:

1. Task bar button stuff. Applications compiled with D2007 just don’t work right in this respect.

2. Applications compiled with D2007 don’t show up on the Windows task list. Ouch!

Of course, there are workarounds, but this is pretty disappointing. I’m not disclosing anything that comes from beta testing — this is stuff from the released version of D2007.

Why am I writing this? I opened my mouth (er, typed my keys) and said how great D2007 is. I owe it to anyone reading my blog to update them on it just in case it matters to them. D2007 is great, to be sure, but it’s just not done!

This isn’t really new, of course. D2005 wasn’t done when it was released either, and eventually became usable. D2007 is way better than D2005 — it’s just frustrating that some very visible issues still need to be fixed before it can actually be used in a production environment.