Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Question regarding behavior of Radiogroup component 1

Status
Not open for further replies.

CHeighlund

Programmer
Jun 11, 2007
163
US
I'm working on a form where there are several sets of radio button options, each of which has a related question and the options 'Yes', 'No', and 'N/A'. I figured it would be easiest to use radiogroup components for these (caption gives me the question for free), and so far it's working well except for one thing.

In one part, I have ten questions. On four of them, clicking 'Yes' is supposed to bring up a list of options to choose from. I've got a panel off to the side, invisible, with the four option sets in listbox components. Clicking 'Yes' in one of the four relevant radiogroup components is supposed to bring the appropriate list box up - it renders the panel and appropriate box visible (normally the panel and all four boxes are all invisible), and the listbox gets aligned to alClient, filling the panel. All of these are to be rendered invisible if the 'No' or 'N/A' answer to one of the four relevant questions is given, or if the user clicks on one of the other six questions. (The four relevant questions also hide everything [including their own boxes] before revealing their information on a yes.)

Currently, if I click on one of the four relevant questions with a yes, it brings the box up. (On-click event) Clicking on another, non-relevant question hides the box. But clicking on the 'Yes' in the first question after this doesn't bring the box back. The only way to get it back is to click on 'No' or 'N/A' (items 1 and 2 in the radiogroup) then back on 'Yes' (item 0). The code doesn't even seem to be running under these circumstances, as I put a breakpoint inside the if (rdgrpX.itemIndex = 0) block, and it never triggered unless I went through the screen gymnastics described above.

Does anyone have any suggestions for how to get the box to respond under these circumstances? Is there any way to make it do so, or will I need to swap out my radiogroups for something else (groupbox + buttons, maybe) that can do the job?
 
If you don't hide the panel for the first cbx when you select another, as far as the DWM is concerned, the panel is still being displayed (even if it is completely behind another panel), so a new show event will have no noticeable effect.

Does this help?
 
Single panel. Four boxes.

Every 'on click' for any radio group reads like one of these:

1. Relevant (4) -
Code:
if (Relevant radiogroup.itemindex = 0) then
begin
  ListBox1.Visible := False;
  ListBox2.Visible := False;
  ListBox3.Visible := False;
  ListBox4.Visible := False;
  Panel1.Visible := False;

  Relevant Listbox.Visible := True;
  Relevant Listbox.align := alClient;
  Panel1.Visible := True
end
else
begin
  ListBox1.Visible := False;
  ListBox2.Visible := False;
  ListBox3.Visible := False;
  ListBox4.Visible := False;
  Panel1.Visible := False;
end;

2. Other (6) -
Code:
ListBox1.Visible := False;
ListBox2.Visible := False;
ListBox3.Visible := False;
ListBox4.Visible := False;
Panel1.Visible := False;

And again, it's not just the show/hide that's not occuring; clicking on the 'Yes'(index 0) radiobutton in a group, when that has already been previously selected, does not appear to fire the code off whatsoever. Changing the group's itemindex value does appear to have this effect.
 
Oh, I understand what is happening to you.

Yes, the OnClick event will not fire, because the selected radio button did not change.

In the Designer, select your radio group box.
In the Object Inspector switch to the Events tab.
Click the OnEnter event slot.

Make the method look something like the following
Code:
procedure Form1.RadioGroup1Enter( Sender: TObject );
  begin
  if not Panel1.Visible
    then RadioGroup1Click( Sender )
  end;

Now whenever you click anything in the box it will check to see if its associated panel is showing or not, and fix it if it isn't.

Hope this helps.
 
Helps a great deal, but I've got one last micro-whining complaint on it. The OnEnter event only triggers when the actual radio buttons get tagged - is there any way I can set it to run whenever any portion of the box is clicked on, not just the buttons? If not, then so be it - your advice gave me most of what I needed; I freely admit that I'm just being picky now.

Thanks again.
 
The only way to do that (neatly, at least) is to derive your own custom TRadioGroup component:
Code:
type
  TMyRadioGroup = class( TRadioGroup )
    private
      procedure WMLButtonUp( var msg: TMessage ); message WM_LBUTTONDOWN;
    end;

...

procedure TMyRadioGroup.WMLButtonUp( var msg: TMessage );
  var control: TControl;
  begin
  // check to see if the mouse is over a TRadioButton control
  control := ControlAtPos(
               point( LoWord( msg.LParam ), HiWord( msg.LParam ) ), 
               False
               );
  is (control is TRadioButton)
  and not (control as TRadioButton).Checked
    then inherited
    else if Assigned( OnClick )
           then OnClick( self )
  end;
This, BTW, will solve your other problem too...
It always causes one OnClick event if the radio box is clicked. If the item under the pointer is not checked, then it uses the default processing, otherwise it just jumps straight to the OnClick event, if defined.

You will need to replace all your TRadioGroup controls with the derived control. You can do this one of three ways:

1. Simply create the controls yourself in your FormCreate procedure. This bypasses the form designer entirely.

2. Compile your derived control into a little component to install on the component palette. This isn't too difficult. Look up "custom components" in the Delphi documentation.

3. You can simply replace the existing TRadioGroup controls from the form's constructor. A little routine to do it is handy:
Code:
procedure ReplaceRadioGroups( form: TForm );
  var
    i:  integer;
    c:  TComponent;
    rg: TMyRadioGroup;
    ls: TStringList;
  begin
  // Duplicate all TRadioGroup components with TMyRadioGroup
  for i := 0 to form.ComponentCount -1 do
    if form.Components[ i ] is TRadioGroup do
      begin
      rg := TMyRadioGroup.Create( form );
      ls.AddObject( Name, rg );

      rg.Action     := Action;
      rg.Align      := Align;
      rg.Anchors    := Anchors;
      rg.BoundsRect := BoundsRect;
      rg.Caption    := Caption;
      rg.Columns    := Columns;
      ...
      // and so on. Don't set the Name property here.
      end;

  // Remove all the old TRadioGroups
  for i := form.ComponentCount -1 downto 0 do
    if form.Components[ i ] is TRadioGroup
      then begin
           c := form.Components[ i ];
           form.RemoveComponent( c );
           c.Free
           end;

  // Rename our new TMyRadioGroups to take
  // the place of the old TRadioGroups
  for i := 0 to ls.Count() do
    with ls.Objects[ i ] as TMyRadioGroup do
      Name := ls[ i ]

  // All done
  end;
Phew. Well, I hope that helps (and that I didn't make any really dumb mistakes). Enjoy!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top