Discussion:
TToolButton without function if Style=tbsDropDown and Action is set at runtime
(too old to reply)
Johannes Weinert
2008-07-16 12:38:45 UTC
Permalink
Hello,

In C++Builder 2007 with all patches applied I did the following:

- create a new VCL application
- drop a TToolBar, drop a TToolButton
- drop TActionList, drop TPopupMenu
- create Action1, Action2, Action3
- define OnExecute event functions for all Actions
- add Action2, Action3 to popup menu
- set TToolButton1.Style=tbsDropDown
- set TToolButton1.DropDownMenu=PopupMenu1
- set TToolButton1.Action = Action1

When the application is run the behavior is as desired, the tool button
fires Action1, I get a drop-down menu if I click on the down-arrow of
the tool button.

Now just one little change: In the constructor of the form set
ToolButton1->Action = Action3;

When the application is now run the tool button itself has no function
at all, only the drop-down menu is working.

I will post an example project into the attachment group.

Is this a bug or am I missing something? It seems the behavior is the
same in C++Builder 2006.

Thanks for an answer in advance,

Hans
Mark Jacobs
2008-07-16 12:48:10 UTC
Permalink
Post by Johannes Weinert
- create a new VCL application
- drop a TToolBar, drop a TToolButton
- drop TActionList, drop TPopupMenu
- create Action1, Action2, Action3
- define OnExecute event functions for all Actions
- add Action2, Action3 to popup menu
- set TToolButton1.Style=tbsDropDown
- set TToolButton1.DropDownMenu=PopupMenu1
- set TToolButton1.Action = Action1
When the application is run the behavior is as desired, the tool button fires Action1, I
get a drop-down menu if I click on the down-arrow of the tool button.
Now just one little change: In the constructor of the form set
ToolButton1->Action = Action3;
When the application is now run the tool button itself has no function at all, only the
drop-down menu is working.
It is possible that the form's constructor is the wrong place to try to assign actions
that have not yet been created themselves! Remember the form is only just being created
when the constructor is called - usually you can set form variables, but not form control
properties at that stage. Move this code into OnFormPaint instead, and prevent it from
being called more than once by using a static bool. Here is an example :-

//----------------------------------------------------------------------------
void __fastcall TMainForm::FormPaint(TObject *Sender)
{
static bool clld=false;
if (clld) return;
clld=true; ToolButton1->Action=Action3;
}
//----------------------------------------------------------------------------

HTH,
--
Mark Jacobs
http://www.dkcomputing.co.uk
Johannes Weinert
2008-07-16 13:25:45 UTC
Permalink
Post by Mark Jacobs
Post by Johannes Weinert
- create a new VCL application
- drop a TToolBar, drop a TToolButton
- drop TActionList, drop TPopupMenu
- create Action1, Action2, Action3
- define OnExecute event functions for all Actions
- add Action2, Action3 to popup menu
- set TToolButton1.Style=tbsDropDown
- set TToolButton1.DropDownMenu=PopupMenu1
- set TToolButton1.Action = Action1
When the application is run the behavior is as desired, the tool button fires Action1, I
get a drop-down menu if I click on the down-arrow of the tool button.
Now just one little change: In the constructor of the form set
ToolButton1->Action = Action3;
When the application is now run the tool button itself has no function at all, only the
drop-down menu is working.
It is possible that the form's constructor is the wrong place to try to assign actions
that have not yet been created themselves! Remember the form is only just being created
when the constructor is called - usually you can set form variables, but not form control
properties at that stage. Move this code into OnFormPaint instead, and prevent it from
being called more than once by using a static bool. Here is an example :-
//----------------------------------------------------------------------------
void __fastcall TMainForm::FormPaint(TObject *Sender)
{
static bool clld=false;
if (clld) return;
clld=true; ToolButton1->Action=Action3;
}
//----------------------------------------------------------------------------
Thanks for the answer. I thought all components of a form have already
been constructed when the constructor is called. However, in the given
example it works indeed to move the code to OnFormPaint.

But in my real application I'm doing the following: I have a form with a
toolbar and a page control. For each sheet another form is created and
the contents is docked to the sheet. The action assignment is done in
TabSheet.OnTabShow(). So at least when I switch between the tabs all
actions are already created. But it does not work anyway. The action
assignment is working for all tool buttons with Style=tbsButton and all
menu items. It just fails for the tool buttons with Style=tbsDropDown.

Any idea what else could cause the problem?

TIA,

Hans
Johannes Weinert
2008-07-16 14:28:12 UTC
Permalink
Post by Johannes Weinert
[...]
But in my real application I'm doing the following: I have a form with a
toolbar and a page control. For each sheet another form is created and
the contents is docked to the sheet. The action assignment is done in
TabSheet.OnTabShow(). So at least when I switch between the tabs all
actions are already created. But it does not work anyway. The action
assignment is working for all tool buttons with Style=tbsButton and all
menu items. It just fails for the tool buttons with Style=tbsDropDown.
Ok, I now found out that the button is working if I click near the left
border of the button (some pixels). If I click in the middle or near the
right border of the button nothing happens. Weird.

I'll investigate further...

Regards

Hans
Johannes Weinert
2008-07-16 14:54:43 UTC
Permalink
Post by Johannes Weinert
Hello,
- create a new VCL application
- drop a TToolBar, drop a TToolButton
- drop TActionList, drop TPopupMenu
- create Action1, Action2, Action3
- define OnExecute event functions for all Actions
- add Action2, Action3 to popup menu
- set TToolButton1.Style=tbsDropDown
- set TToolButton1.DropDownMenu=PopupMenu1
- set TToolButton1.Action = Action1
When the application is run the behavior is as desired, the tool button
fires Action1, I get a drop-down menu if I click on the down-arrow of
the tool button.
Now just one little change: In the constructor of the form set
ToolButton1->Action = Action3;
When the application is now run the tool button itself has no function
at all, only the drop-down menu is working.
This is not quite true. I now found out that the button is working if I
click near the left border of the button (some pixels). If I click in
the middle or near the right border of the button nothing happens. Weird.

As this is just a small example to reproduce the behavior and my real
application is much more complicated I do not have the solution "assign
the action in OnFormPaint".

However, the question remains: Is this a bug?

Regards

Hans

Loading...