Board index » cppbuilder » TRadioButton and OnClick

TRadioButton and OnClick


2008-05-07 03:49:34 AM
cppbuilder37
Any Ideas ?
-----------
I have three types of controls:
Grid is a TStringGrid
Shapes is an array of TShape
Buttons is an array of TRadioButton
Each radio button has the same function OnRadioButtonClick defined and
assigned to the OnClick event.
Grid has a function OnSelectCell assigned to the OnSelectCell event.
Each Shape has the same function OnColorChipClick assigned to the
OnMouseDown event.
There are as many Shapes and Buttons as there are visible rows in Grid.
The intent is that a click on a row of Grid will do the same thing as
selecting the corresponding radio button.
Also, a click on a shape will accomplish the same thing.
The functions OnSelectCell and OnColorChipClick both set the Checked
property of the appropriate radio button to true.
This works fine.
---->UNLESS:
I include a call to ShowMessage() in the OnRadioButtonClick.
I wanted to do this just to check that everything was working right.
---->HERE IS WHAT HAPPENS:
Suppose that I have explicitely selected radio button 1 by clicking on it.
ShowMessage gets called once and I'm happy. This shows me that the OnClick
event is working fine.
Suppose that I select a cell in the Grid by clicking in it.
ShowMessage gets called once and I'm happy. This shows me that the
OnSelectCell event is working fine.
Suppose that I select a Shape by clicking in it.
ShowMessage gets called once showing me that the proper radio button
has been activated (Checked).
It then gets called again with the ORIGINAL radio button as the caller.
The original radio button then gets reactivated (Checked).
---->HOWEVER:
If I replace the call to ShowMessage with the setting of the Text in a
TEdit control, EVERYTHING WORKS FINE ! I only make that one change.
Obviously this cost me several hours.
John
 
 

Re:TRadioButton and OnClick

"JohnC" < XXXX@XXXXX.COM >wrote in message
Quote
Suppose that I select a Shape by clicking in it.
ShowMessage gets called once showing me that the
proper radio button has been activated (Checked).
It then gets called again with the ORIGINAL radio button
as the caller. The original radio button then gets reactivated
(Checked).
Then your TShape code is not set up correctly. Please show the actual code.
Gambit
 

Re:TRadioButton and OnClick

(Sorry, I must have replied to the individual instead of the group.)
Not much to see:
(The array controls have been given names consisting of one alpha followed
by an index.)
//---------------------------------------------------------------------------
//This is the TShape code:
//This function makes the color chip act like the corresponding radio
button.
void __fastcall TJMCClusterTable::OnColorChipClick(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
TShape* Chip;
int SelectedChip; //0-Origin
Chip = (TShape*)Sender;
SelectedChip = StrToInt(Chip->Name.SubString(2,Chip->Name.Length()-1));
FSelectedCluster = Table->TopRow + SelectedChip - 1; //1 row is fixed
RadioButtons[SelectedChip]->Checked = true;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//This function makes a cell selection act like the corresponding radio
button.
void __fastcall TJMCClusterTable::OnSelectCell(TObject *Sender,
int ACol, int ARow, bool &CanSelect)
{
FSelectedCluster = ARow - 1;
RadioButtons[ARow - Table->TopRow]->Checked = true;
if(FOnCellSelect)
FOnCellSelect(ARow,ACol);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TJMCClusterTable::OnRadioButtonClick(TObject *Sender)
{
TRadioButton* Button;
int SelectedButton; //0-Origin
Button = (TRadioButton*)Sender;
if((Button->Checked)&&(!Scrolling))
{
SelectedButton =
StrToInt(Button->Name.SubString(2,Button->Name.Length()-1));
FSelectedCluster = Table->TopRow + SelectedButton - 1; //1 row is
fixed
if(FOnClusterSelect)
FOnClusterSelect(FSelectedCluster);
}
}
//---------------------------------------------------------------------------
As you see, there are no multiple sets of the radio button.
The rest is just a little arithetic to get the correspondence between the
row and the index right.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"JohnC" < XXXX@XXXXX.COM >wrote in message
news:4820b64d$ XXXX@XXXXX.COM ...

>Suppose that I select a Shape by clicking in it.
>ShowMessage gets called once showing me that the
>proper radio button has been activated (Checked).
>It then gets called again with the ORIGINAL radio button
>as the caller. The original radio button then gets reactivated
>(Checked).

Then your TShape code is not set up correctly. Please show the actual
code.


Gambit

 

{smallsort}

Re:TRadioButton and OnClick

"JohnC" < XXXX@XXXXX.COM >wrote in message
Quote
The array controls have been given names consisting of
one alpha followed by an index.
I would suggest using the Tag property of each control for that instead.
You can store array indexes in it. That would clean up your code a bit, ie:
void __fastcall TJMCClusterTable::OnColorChipClick(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
TShape *Chip = (TShape*) Sender;
FSelectedCluster = (Table->TopRow - Table->FixedRows) + Chip->Tag;
RadioButtons[Chip->Tag]->Checked = true;
}
void __fastcall TJMCClusterTable::OnSelectCell(TObject *Sender, int
ACol, int ARow, bool &CanSelect)
{
FSelectedCluster = (ARow - Table->FixedRows);
RadioButtons[ARow - Table->TopRow]->Checked = true;
if( FOnCellSelect )
FOnCellSelect(ARow, ACol);
}
void __fastcall TJMCClusterTable::OnRadioButtonClick(TObject *Sender)
{
TRadioButton *Button = (TRadioButton*) Sender;
if( (Button->Checked) && (!Scrolling) )
{
FSelectedCluster = (Table->TopRow - Table->FixedRows) +
Button->Tag;
if( FOnClusterSelect )
FOnClusterSelect(FSelectedCluster);
}
}
Now, as for your original problem - it is an issue of input focus. When the
TRadioButton.Checked property is set to true programmably, an OnClick event
is triggered. When a TRadioButton receives input focus and it is not
currently Checked, its Checked property is set to true and the OnClick event
is triggered. By calling ShowMessage(), you are moving input focus away
from the UI and then back. When the dialog is closed, input focus is moved
back to the previously active control. TShape is not a windowed control, so
it cannot receive input focus at all. Your previously selected TRadioButton
receives the input focus again, and since it is no longer Checked (since the
TShape changed that), the previous TRadioButton fires its OnClick event
again.
Here is a very simply example to show you what is happening. Create a new
TForm, put two TRadioButtons and a TShape on it, and then run this code:
// assign this OnClick handler to both TRadioButton controls...
void __fastcall TForm1::RadioButtonClick(TObject *Sender)
{
TRadioButton *Button = (TRadioButton*) Sender;
if( ActiveControl )
ShowMessage(Button->Name + " Clicked\nActive Control: " +
ActiveControl->Name);
else
ShowMessage(Button->Name + " Clicked\nActive Control: none");
}
void __fastcall TForm1::Shape1MouseDown(TObject *Sender, TMouseButton
Button, TShiftState Shift, int X, int Y)
{
RadioButton2->Checked = true;
}
Click on RadioButton1, and then click on the TShape over and over. See what
happens?
Clicking on RadioButton1 gives it input focus and then ShowMessage() is
called. When the dialog is closed, RadioButton is given input focus again,
but it is already Checked so nothing further happens.
Clicking on the TShape next sets RadioButton2 to Checked, but RadioButton1
is still focused! TShape cannot accept input focus. RadioButton2's Checked
property is changed, so it triggers an OnClick event, calling ShowMessage().
When closed, input focus moves back to RadioButton1, setting it to Checked
and triggering its OnClick event.
You don't have this problem when clicking on the TStringGrid because it is a
windowed control and thus accepts input focus. Clicking on the grid may
change a RadioButton's Checked property, thus calling ShowMessage(), but
input focus was moved to the grid first, and when ShowMessage() closes then
input focus is moved back to the grid, not any of the RadioButton controls.
You also don't have this problem when you are not calling ShowMessage() at
all (or if you use any other windowed control besides TShape) because input
focus is not being moved around the RadioButton controls in that situation.
If you want to debug your code in real-time without using popup messages,
you can use DebugOutputString() for that. You can send text messages to the
IDE De{*word*81}'s Event Log, or to an external debug logger, such as
SysInternals' DebugView, when not running your app inside the IDE.
Gambit
 

Re:TRadioButton and OnClick

Thank you sir!
It was a beautiful analysis.
John
 

Re:TRadioButton and OnClick

Remy:
Thanks again for your suggestions.
Here's what I ended up with:
//---------------------------------------------------------------------------
void __fastcall TJMCClusterTable::OnRadioButtonClick(TObject *Sender)
{
TRadioButton* Button;
int SelectedButton; //0-Origin
Button = (TRadioButton*)Sender;
if((Button->Checked)&&(!Scrolling))
{
SelectedButton = Button->Tag;
FSelectedCluster = Table->TopRow + SelectedButton - 1; //1 row is
fixed
Button->SetFocus();
if(FOnClusterSelect)
FOnClusterSelect(FSelectedCluster);
}
}
//---------------------------------------------------------------------------
I corrected the focus problem by explicitely setting the focus to the
checked button.
Tags work great. I have never used them before.
Of course, I could have gotten rid of the local variable SelectedButton but
I decided to leave it.
It helps one to understand the code.
John