As a follow up to my last post, I’ve written a small demo that (rather pointlessly of course) enables custom drawing in the main form’s title bar only to reinstate the standard elements. It does this across changes to the form’s BorderIcons, BorderStyle, Caption and Icon properties, and has a check box to allow easily comparing to the ‘real thing’:
The substantive code is essentially the same as what I presented last time, though one small but important thing it adds is a couple of lines to combat the problem of changed client coordinates.
If you recall, this was the issue of how in enabling custom drawing on a form’s title bar, you must extend its client area onto it, messing up the position of child controls in the process. While merely taking away the top part of the non-client area was better than the MSDN-suggested solution of zapping the non-client area entirely, the problem did still remain.
A good way to counteract it, though, is to do two things: (1) move all non-aligned controls over to a frame, which is then top-aligned to the form; and (2) override the form’s AdjustClientArea method as appropriate. This method is a purely VCL-level thing that allows a parent control to force aligned children to be within a bounds less than the actual client area — of the standard controls, it’s used by TGroupBox to make sure a top aligned child (for example) will be below the group box caption rather than over it.
Given this, my demo simply overrides AdjustClientRect as thus:
procedure TfrmMain.AdjustClientRect(var Rect: TRect); begin inherited; if FUseCustomFrame then Inc(Rect.Top, GlassFrame.Top); end;
One thing the demo more unfortunately demonstrates too, though, is the issue I blogged about recently: unless you mark the EXE to require the Vista sub-system or later, the custom frame will not work properly with non-sizeable border styles.
Anyhow, if you’re interested, I’ve put the demo up on CodeCentral here.
[Edit, in response to comments: by design, the pre-compiled EXE won’t work on XP or earlier! Read what I wrote here for why. Not by design, I intially hacked away at the precompiled EXE too much. I’ve taken the EXE out of the ZIP for now.]
[Edit 2: check out the comment by Torbins below for a potentially much simpler alternative to taking out the non-client area. That said, I can't get this to work properly when compiling with D2007 -- it causes 'ghost' buttons in use, amongst artifacts.]
[Edit 3 (Jan 2011): I finally got round to fixing the demo. There’s also an additional fix for the ghost buttons that appeared on Windows 7 64 bit (these were the same buttons that plagued the alternative solution on all platforms), plus the source to a small console application I wrote to do the patching mentioned above. Download location is as before.]