New version of DUnit (7.2.1)

It’s a minor release, version 7.2.1; nothing too earth-shaking. The biggest new feature, in my mind, is long strings — CheckEquals and the like will now check all of a string, rather than calling it good enough after the first 255 characters. I think the optional explanatory-message parameters were being truncated, too, and aren’t anymore. They also added support for comparing WideStrings, and fixed a couple of bugs.

I had almost forgotten that DUnit only used ShortStrings! The stated reason was so you could compile DUnit into a DLL. If anyone is actually doing that, they need to use ShareMem now. I honestly can’t say I’ve ever even considered putting DUnit into a DLL, but that’s just me.

They’re not using SourceForge’s bug tracker; their SourceForge site does have a text file with a one-line description for each fix, but that really doesn’t tell you anything unless you’re already familiar with all the issues. However, they do have a Web site where you can view the full list of enhancements and bug fixes for this version, along with archived discussions about each item. Oddly, you need to create a username and password before you can even view that Web site. How irritating. A bit silly, too, since they then promptly let you in without even verifying your e-mail address.

Anyway, the long-string support should make this worth the download. (Downloading now…)

Delphi/Win32: Fun with RTTI

In .NET, it’s easy to use Reflection to peek into other objects’ private fields (though it’s considered bad form, and of course it requires full trust). But doing the same thing in Delphi/Win32, as far as I knew, involved using the Disassembler window to find some magic numbers, and then hard-coding those magic numbers, which would be nastily brittle (and is why I never bothered).

Not necessarily so, as it turns out. Hallvard Vassbotn just posted about a Delphi/Win32 hack to write to a read-only property, using nothing but RTTI, a nice twist on inheritance, and of course some pointer arithmetic — but no hard-coded magic numbers, so it’ll still work even if you change ancestors or add more fields. Cool!

Windows Services in .NET (with Indy)

As part of my team’s project at work, we had to create a Windows service in .NET. Originally we built it in Delphi 8 for .NET, which worked fine as long as we could get the compiler to cooperate. But the D8 compiler is so buggy, especially when working with multi-assembly project groups, that we eventually wound up porting the service back to C#. Sigh.

Creating a Windows service in .NET is actually not too hard, though it isn’t well documented. If you have Visual Studio, there’s actually an option in File > New Project to create a Windows service. However, that doesn’t do everything you need; specifically, it doesn’t give you any way to install your service so that Windows will actually run it (or show it in the Services snap-in so you can start and stop it later). And if you have Delphi 8, you don’t have a Windows service wizard. (There was one in D6, but apparently its .NET rewrite didn’t make the D8 release schedule.)

This article on CodeProject was invaluable to us in getting things up and running. It shows how to build a .NET Windows service from the ground up; it doesn’t assume that you have Visual Studio with its Windows service project wizard (which is handy if you’re using Delphi 8, or if you only bought Visual C# instead of the full Studio, or if you’re writing your code in SharpDevelop or Notepad). It also shows how to install (and uninstall) the service using installutil.

Once you’ve walked through the article, and have your service up and running, it’s pretty slick. The service ends up as an EXE that’s intended to run under Windows’ service manager — and the .NET service plumbing will automatically give the user a meaningful error message if they try to run the EXE manually (though there is about a 15-second pause first), which is good. And if your service is starting an HTTP server using the open-source Indy networking libraries (check them out if you’re still using the wussy FTP and HTTP support in System.Net — Indy is better, and it supports just about every Internet protocol known to man, both client- and server-side, and it’s free), then you don’t even need to worry about the fact that there are something like three threads being created and juggled just to manage your service — it just works. Just set the server’s Active property to true in your override of ServiceBase.OnStart, and set it back to false in your override of ServiceBase.OnStop. Indy will even wait for any pending HTTP requests to finish before it returns from the Active = false setter. Very cool.

Merged cells in Xceed Grid

My team recently did a survey of the available WinForms grid controls for .NET, and we pretty unanimously voted for the Xceed Grid. We miss some features from the Delphi world’s TMS grid, like fixed columns and merged cells, but TMS hasn’t shown any signs that they intend to bring their grid forward into the Delphi for .NET world and we needed something.

However, even though fixed columns aren’t natively supported in the Xceed Grid, they can be emulated. Actually, we let their sales folks know that we couldn’t buy their grid if it couldn’t do fixed columns (true), and they supplied a workaround. Which didn’t work in the 2.0 version, but they were kind enough to send us a pre-release version of 2.1 (then about two weeks away from release) and the fixed-column workaround worked again. (2.1 is now available.) It works great; you’d never know it was a workaround.

And they just posted a knowledgebase article on how to emulate merged cells. So at this point (though not having tried the merged-cell workaround), I think we’re not missing any features from the TMS grid, and we sure have a lot more features to play with. Pretty cool.

Charlotte’s Web Search

Allen Bauer just posted about the fate of “Charlotte”. Apparently it hasn’t been developed further as a product, but parts of it have wound up in the CodeDOM system in C#Builder and Delphi for .NET.

So as I read his post, I was scratching my head and wondering what “Charlotte” was.

A brief Google search for borland charlotte found a page on Dr. Bob’s site that briefly mentioned Charlotte as a scripting language for writing Web services. Now I’m really curious… it’s hard to hear about a new language (even one that won’t be released) and not even see any sample code. The sign of a true geek, I guess.

As it happens, that very same Google search also turned up this very interesting page: “If ever a story called for further reporting, this one did.” The fact that the word Charlotte appears in this story is apparently just a coincidence, though an amusingly appropriate one.

This would’ve been easy in Delphi…

I’m writing a FlowLinkLabel WinForms control. It’s a LinkLabel-like control that automatically wordwraps, and changes its height as needed when its width changes. There’s a plain old non-hyperlinked FlowLabel too. Useful for headings and stuff, or explanatory text, or task panes, or anywhere you want flow layout. I wrote it because I’ll be needing it for a project at work, and I wrote it on my own time and will release it open-source, because that way I can use it in my other spare-time projects too. (grin)

Of course, in Delphi this would all be easy. I wouldn’t even need to write my own control. I’d just drop a TLabel, set AutoSize to True and WordWrap to True, and boom, it works. The WinForms Label has an AutoSize property (which defaults to False for some reason), but it’s horizontal only; it doesn’t grok word-wrap, so it’s useless for anything resembling flow layout. There’s nothing suitable for, say, putting a paragraph of explanatory text at the top of a window, and having it re-wrap and all stay visible as the window gets narrower. (There will be all sorts of flow layout in Longhorn, but that’s what, at least two or three years away, and would require all our clients to upgrade to Longhorn when it comes out… so for us, probably at least five or six years away.)

Anyway. So I was hoping to be able to have all the FlowLinkLabels on a form automatically share color settings (link color, hover color, active color, visited color), underline settings, etc. Stylesheet kind of stuff, only for WinForms. That’s why I was looking for the article I mentioned yesterday — I knew it touched on that sort of idea. Creating a service in one part of your app and getting at it from somewhere else.

My general thought was this: Have a non-visual Component (maybe added to the form manually by the application developer, or maybe created automatically the first time you drop a FlowLinkLabel onto a form) that stores the style settings. All the FlowLinkLabels in the form share this same stylesheet component by default (with the ability to override per label if you want some to have different style settings). Everything happens full automatic: you create a new form, you drop a bunch of FlowLinkLabels, and boom, you automatically — with no more effort than that — have a centralized place to set the colors for all of them at once. If I was sneaky enough, I thought, it might even be possible to share these stylesheet settings across multiple forms.

Alas, it looks like it’s not to be. For starters, given a Component, you can find its Container, but there’s no way to get from that Container up to the next Component up the chain (e.g., given an ImageList instance, there’s no way to get a reference to its containing UserControl), which would make it hard for the FlowLinkLabels to automatically discover the shared container that lives up in the form/usercontrol, and hard for the stylesheet to automatically notify the labels when its properties get changed. Second, even though Control descends from Component, it’s not treated like a Component: the designer adds Components to a Container, but Controls are added to a ControlCollection, and the Container and ControlCollection have no way of referencing each other. So again, no addressability between the controls and the components. Third, the ideal way of storing these settings would be by using IServiceContainer, but this only works if someone creates an IServiceContainer for you — which would require manual coding on the part of the application developer. Yuck.

Delphi makes this so much easier. TControl descends from TComponent, and it’s treated the same way. Iterating through all the components (and controls) owned by a form (or frame) is trivial; you just loop through the Components[] array property. WinForms seems bound and determined to make the same thing hard.

So it looks like there’s no good way to make these stylesheets work without forcing the application developer to drop their own stylesheet component onto the form and then manually hook each FlowLinkLabel to it. Which is error-prone (if you add a new label, you have to remember to hook it up), which is exactly what I was hoping to avoid. Feh.