I have a tool button and an assigned to it action. But the action doesn't have an on click event, there is no code for a click. Therefor the button is disabled, how to change it to be enabled?
Thanks!
When an action has no OnExecute handler, the action is always disabled. If you want to assign an action to an object, and have that object be enabled, then you need to provide an OnExecute handler.
The question sounds a little odd though. Why would you have a button which, when pressed, does nothing? Do you perhaps, have an OnClick handler that is defined in the button rather than the action? If so then you should simply move that handler into the action and all will be well.
Update
Ulrich helpfully points out that the DisableIfNoHandler of TAction can be used to change the behaviour described above. Since this has public visibility and is not published, you have to make the change in code which is why I think I forgot about it.
Related
In delphi:
How can you respond to a key press when the current focus is on a radiogroup which does not have an onkeypress event. I was hoping to use the forms onkeypress event but it doesnt see to fire.
You can make this possible by setting the form's KeyPreview property to True.
However, I'm not sure you are actually doing things right, since this is a fairly uncommon problem.
You didn't write what keyboard shortcut you want to respond to. But please remember that
Letters are used to navigate the GUI. For instance, pressing A might select the &All radio button or click the &Add push button. Similarly, Alt+A does the same if the current control allows character input, allows you to open the &Add-ons menu item, etc.
If you want to add a proper shortcut like Ctrl+O, it is much better to use a TActionList with an action having this shortcut. This action can be mapped to menu items, buttons, etc., or simply exist in the background not being attached to any visual control. In very simple applications, you might want to use a stand-alone menu item with such a shortcut instead.
I'm having issues getting a TToolbar Button to appear "enable"
The button has an Action assigned to it - which is fire by the OnClick event
It is also setup with a Drop Down Menu, which has 2 options on it, both of which are enabled, and both of which fire off when clicked.
Despite all this the TToolbar Button steadfastly remains greyed out, but accepts the clicks.
Any suggestions?
You're doing things wrong. :-)
When using actions, you don't use the button's OnClick event - you put the code in the action's OnExecute event instead (because that's what's executing - the action - and not the button). When an action is assigned to the control, the control cannot be enabled until there's a handler for the TAction.OnExecute.
The reason for using actions is so you can put the code in a single place (events related to the action), and then every single control attached to that action uses that common code to perform the same functionality. Editing the code in that single location means all controls attached to that action see the same changes.
If there's nothing attached to the TAction.OnExecute event, the control has nothing to do if it was selected (clicked), and so there's no reason to enable it in the first place.
In case someone else comes across this, I just had this problem (using Delphi 10.2 Tokyo).
For some reason, the "EnableDropdown" property on the TToolButton caused the button to to be greyed out when set to true. Setting this property to false seems to have resolved the problem for me (the dropdown menu remains functional anyway).
I open forms inside tabs of a page control. These forms may contain actions with shortcuts. And I want these shortcuts to be fired only when the tab that contain this form is active.
I tried to override form's IsShortCut but it's not called. Form's OnShortCut is not called either.
I would like to avoid putting code on each action to check this.
I'm using Delphi 2010.
Set the State for the action lists on your hidden tabs to asSuspended. Only the action list on your visible tab should have a state of asNormal. That will prevent the shortcut keys from working. It also prevents those actions from updating, which may or may not be a good thing for your application.
Try setting the form's Enabled to false whan you switch away, and True when you switch onto it's tab. That should disable all the content on the form, including shortcuts.
Put all the shortcuts into actions and those actions into one action list per form. Then you can disable the action lists of the forms that are currently not active. (I don't recall the exact TActionList property to set or method to call or activating/deactivating it, but it is there.)
I have a TForm (TVehicleEditForm) with 3 identical TFrames (TVehicleUnitFrame) inside.
The idea was that every instance of the frame handle own events by a eventhandler inside the frame. The problem is that the eventhandler is not called.
I have tried to assign the eventhandler by code inside the frame by overriding the Create method but the handler is not called in that case either.
But if I assign the eventhandler outside the frame from the form it works fine.
Like this:
fraVehicleUnitFrame1.cmdNewOwner.OnClick := fraVehicleUnitFrame1.cmdNewOwnerClick;
fraVehicleUnitFrame2.cmdNewOwner.OnClick := fraVehicleUnitFrame2.cmdNewOwnerClick;
fraVehicleUnitFrame3.cmdNewOwner.OnClick := fraVehicleUnitFrame3.cmdNewOwnerClick;
And this is only for one button!
As I have many components inside the frame this would result in many assignments...
Quite ugly code when this should be done directly in the object inspector.
I am using D2007. Any idea of the cause ?
Regards Roland
The reason it works when you do it from code, is that you replace the pointer to the event handler, regardless of what was there before.
At design-time, I have two possible places to set the handler. Suppose I have Frame1 in Unit1 and I place it on MyForm in MyUnit, I'll have the opportunity to set the event handler in both places.
In your case you want to set the event handler in the frame itself (Unit1 in my example), as the code it refers to is on the frame itself. If you do that, it should work. If you set the event handler on the place it is used (MyUnit), then the event handler will be assigned there.
Delphi is clever enough to still call the event handler from your frame as long as that event handler was assigned before you added the one in the form. If you first added it on the form and then added the handler on the frame, the last one on the frame is not called.
To make matters worse, if you remove the handler in the form it still won't call the one on the frame.
What you need to do is this:
Right-Click your form and select View as Text. Scroll down to the frame. It should be something like:
inline FrameX: fraVehicleUnitFrame1
Beneath that, look for
inherited cmdNewOwner: TButton
There you should see something like:
OnClick = FormOldClickHandler
or perhaps
OnClick = nil
Delete this OnClick assignment, view as form again and save. All should be well. If you now select the button (or whatever cmdNewOwner is) on the form, the object inspector should show nothing next to that event.
This is old issue but I had the similar problem in Rio 10.3.
On the main form you can click "Revert to inherited" option.
This option is on 'Events' tab in 'Object Inscpector'. Click right mouse on 'OnItemClick' and click option 'Revert to inherited'.
On my main form I have a TPanel containing buttons that act as a toolbar. I want to clone/copy this toolbar and the buttons and their functionality to a second form.
Cloning the menu was simple using newmenu.merge(mainmenu). That was an excellent shortcut to duplicating a Tmainmenu.
But I am at a loss on how to easily duplicate my toolbar without having to manually assign the events and keep a timer to compare and track which buttons are enabled and disabled in comparison to the real mainmenu on the main form. Depending on what the application is doing the main toolbar buttons will be enabled and disabled at various times.
Any ideas here? Thanks for any suggestions or tips to make this easier.
Duplicating the controls
In the Form Designer, select the panel and press Ctrl+C to copy it and all its children to the clipboard. Go to the second form and press Ctrl+V to paste.
If you're still working on the design and want to keep it consistent between both forms, then create a TFrame and design your toolbar layout there. Then put an instance of that frame on both your forms. Changes to the frame design will be reflected in the forms.
See Working with frames in the help.
Making sure both sets of buttons are enabled consistently
Create a data module. Put a TActionList on it. Add an action to it for each button on your main form. Assign event handlers to the actions' OnUpdate events. In them, set the actions' Enabled properties. Finally, assign each button's Action property to refer to the corresponding action object. The buttons will automatically get enabled and disabled with the actions. No timer required.
Furthermore, you can handle the actions' OnExecute events, too. Clear each button's OnClick property, and then move the button's OnClick code into the corresponding action's OnExecute handler. It will automatically get called when you click the button, even though the OnClick property is empty.
When you assign the Caption or Hint property of a TAction, the corresponding properties of any associated controls also change. Likewise for images, if the control supports them. Actions can be assigned to menu items, too.
See Using action lists in the help.
Acting like a toolbar
Just use TToolbar. That's what it's for.
Or, once you're used to actions, put a TActionManager in your project and use it with TActionToolbar and TActionMainMenuBar. See Organizing actions for toolbars and menus in the help.
Are the buttons attached to actions? If so, you can use the OnUpdate event of the TActionList to specify what should and should not be enabled. If not, it isn't too much work to convert to using actions.
If you go this route to convert to using a ActionList, consider putting the ActionList in a datamodule where different units and forms could reference it.
You can Use ClipBoard Object For Copy Your Panel.
Clipboard.SetComponent(Panel1);
Clipboard.GetComponent(Form2,GroupBox1);