2009. november 6., péntek
Manipulating a TRadioGroup's Individual Buttons
Problem/Question/Abstract:
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.
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
RadioGroup1: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
private
{Private declarations}
OldItemIndex: Integer;
public
{Public declarations}
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
OldItemIndex := -1;
end;
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
with RadioGroup1 do
begin
{if there was a previously set item, change it back to the default
appearance first}
if (OldItemIndex > -1) then
with (Components[OldItemIndex] as TRadioButton) do
begin
Color := clBtnFace;
Font.Color := clBtnFace;
Font.Style := [];
end;
{Now with the currently selected item, change its appearance}
with (Components[ItemIndex] as TRadioButton) do
begin
Color := clBlue;
Font.Color := clWhite;
Font.Style := [fsBold];
OldItemIndex := ItemIndex;
end;
end;
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.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése