Author: Lou Adler
Is there a way to manipulate the appearance of the individual buttons in a
TRadioGroup?
Answer:
This subject falls into the yeah, it's something you could do, but should you
category. In other words, don't do it just because it's possible. Especially
because for what I'll be discussing here, this is pretty much undocumented stuff,
and purposely hidden from obvious access.
The Delphi engineers hid a lot of stuff from the visible interface for a good
reason: Unless you really know what you're doing and understand the workings of
Delphi and the VCL components and its object hierarchy, it's better to leave the
internal stuff alone. In fact, I'd venture that 98% of the time you won't need to
access any of the hidden features of Delphi. But as we all know, it's that
remaining 2% that always kills us. I ran into one of those 2% situations recently.
I had created a form that had a few TRadioGroups with up to 20 items in each on it.
The selections specified some standard query selection criteria, which my users
could then just set with a few clicks of the mouse, press the OK button and the
program would produce a formatted report. No possible mistyping, so no worries
about entering in wrong information for the criteria-matching. However, one of my
users had a problem with the form in that because the radio groups were
side-by-side, it was difficult to immediately tell which selection she had made
from one group to the next. So she asked me if I could change the appearance of the
item she checked.
So what I did was take advantage of the fact that objects that can act as
containers all have an array property called Components, which holds the component
index of a contained component relative to the container. TRadioGroup is nothing
more than a TWinControl descendant (a few levels down) with a collection of
TRadioButtons. And conveniently, the radio buttons in the group are indexed with
the ItemIndex property, which in turn corresponds to the index of the Components
array. So all we have to do to access an individual TRadioButton in a TRadioGroup
is to typecast a Components element as a TRadioButton. What I came up with is
fairly simple, but remember, this is undocumented stuff.
1 unit main;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 StdCtrls, ExtCtrls;
8
9 type
10 TForm1 = class(TForm)
11 RadioGroup1: TRadioGroup;
12 procedure FormCreate(Sender: TObject);
13 procedure RadioGroup1Click(Sender: TObject);
14 private
15 {Private declarations}
16 OldItemIndex: Integer;
17 public
18 {Public declarations}
19 end;
20
21 var
22 Form1: TForm1;
23
24 implementation
25
26 {$R *.DFM}
27
28 procedure TForm1.FormCreate(Sender: TObject);
29 begin
30 OldItemIndex := -1;
31 end;
32
33 procedure TForm1.RadioGroup1Click(Sender: TObject);
34 begin
35 with RadioGroup1 do
36 begin
37 {if there was a previously set item, change it back to the default
38 appearance first}
39 if (OldItemIndex > -1) then
40 with (Components[OldItemIndex] as TRadioButton) do
41 begin
42 Color := clBtnFace;
43 Font.Color := clBtnFace;
44 Font.Style := [];
45 end;
46 {Now with the currently selected item, change its appearance}
47 with (Components[ItemIndex] as TRadioButton) do
48 begin
49 Color := clBlue;
50 Font.Color := clWhite;
51 Font.Style := [fsBold];
52 OldItemIndex := ItemIndex;
53 end;
54 end;
55 end;
The unit code above depicts a simple form with a single TRadioGroup dropped on it.
I filled the group up with about 20 values by hand for testing. Now what goes on is
pretty straightforward. I have defined a private variable called OldItemIndex that
holds the value of a previously selected item. This is a "just in case" thing in
that if users change their mind about a selection, they can go back to the radio
group, change the value, and the old item will revert back to its original
appearance. The code is listed in the OnClick handler for RadioGroup1 above.
Granted, this was pretty simple. You could do more with the TRadioButton if you wish. In fact, all the properties of TRadioButton are available. But as I said before, this is undocumented material, so use at your own risk, even if it's for a purpose as innocuous as this.
|