EventHandler inside a TFrame? - delphi

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'.

Related

Firemonkey TFrame - how to fire ancestor TFrame events?

I created a base TFrame class, eg TBasicFrame
There is one button called btnTest, which do a simple task
showmessage('test');
On another TForm or TFrame, I place this TBasicFrame on it. However, when I click this btnTest on this or TForm/TFrame which has an instance of TBasicFrame on it, the showmessage does not run.
What must I do to ensure that all code in the ancestor frame will execute? That means the showmessage('test') will run even when new instances of TBasicFrame is placed anywhere.
Any advice?
I think, you overrided this event by simple double click on button (on object of your Frame) in IDE. So you dont have original call event.
Check *.fmx files of TBasicFrame and TForm with object TBasicFrame.

How to close an FMX TFrame shown in a TPopup from event handlers inside the TFrame

I use a frame that is shown by calling TPopup.Popup(true); method. If the frame contains a button with the ModalResult property set (to, for example, mrOK) it closes automatically when clicked by the user. But I need to close the frame in an OnClick event of a TListBox in it.
Frame does not have Close method.
I would like to avoid using message posting to the parent form as it might cause future problems when the application is ported to Android as well as I would prefer not to declare the OnClick event handler for the Frame.ListBox in the parent Form because the frame might be shown by several different forms and it will worsen the quality of parent Form code making it heavy and difficult to read.
I would highly appreciate suggestions how to do this.
I found the following way out. I call
(GetParentComponent as TPopup).IsOpen:=false;
When you inherit from TPopUp like explained here (How to make my own dialog component from Firemonkey TPopUp?) then you can call ClosePopup when an event is trigerred in your frame.

How determine that a dragging operation has ended in FireMonkey?

I want to find out if a dragged control has been released outside any target.
One would think that OnDragEnd should be used, but that event doesn't work (they forgot to call the DragEnd procedure in the FMX.Types unit).
As an alternative, I tried OnMouseUp for the dragged control. Doesn't work. Doesn't get triggered when DragMode=dmAutomatic.
As a last resort, I tried to override the MouseUp procedure of the form itself (since all mouse events go through the form before being handed down to the respective control). Surprise: the MouseUp procedure does not get called when the control's DragMode=dmAutomatic.
Amazing how something this very simple is this extremely hard to achieve, but I'm hoping someone might have found a working solution.
It is possible to override the form's DragLeave method. This method is called for all objects that get dropped outside of a target area.

Delphi 6 TListBox OnMeasureItem() and OnDrawItem() never called for lbOwnerDrawVariable() list box

I have a Delphi 6 app with a TListBox control set to lbOwnerDrawVariable. At run-time I add a single string to the list box. I have event handlers for OnMeasureItem() and OnDrawItem() and I set breakpoints on the very first line of code in each event handler. However neither of them are ever called. Not once. Not even if I make an Explicit Refresh or Repaint call on the list box.
This is really basic stuff so what is it that I am doing wrong that could inhibit the calling of those event handlers and subsequently disrupting my owner draw code? The single string does show in the list box properly. I threw in an OnClick() event handler just to see if it worked and did.
The OnMeasureItem and OnDrawItem events are (indirectly) triggered in response to the WM_MEASUREITEM and WM_DRAWITEM messages from Windows. Make sure you do not have any message handlers in your app that are filtering out that message, or the VCL's internal CN_MEASUREITEM and CN_DRAWITEM messages.
It turns out the problem was due to a non-zero value in the Columns property of the TListBox I was using. I had been experimenting with using columns earlier before I converted over to owner-draw and had left the TListBox.Columns property with a non-zero value. Apparently a non-zero Columns property value inhibits the triggering of owner-draw related event triggering. Once I set that property back to zero OnMeasureItem() and OnDrawItem() started firing.
There's really very little that can go wrong here. If you set up a test app to try this out then it functions just as you would expect and the event handlers are called.
The most likely cause of the behaviour you report is if the items are added before the event handlers are assigned. This typically happens if the items are added at design time in the .dfm file. You say you are adding the items at runtime. Perhaps you are adding them too soon, before the event handlers are assigned. What happens if you add items in response to an event, e.g. a button click. Try that out because you can be sure then then the event handlers are assigned by that point.
If that doesn't help then clearly you have some code in your app that is interfering with the VCL code.
I had this same issue: my OnDrawItem event handler was not being called if the Columns property was non-zero. It turned out this was because the Style property was set to lbOwnerDrawVariable. Variable item height is not allowed in conjunction with multiple columns, presumably because the rows would not line up across the columns if the item heights were allowed to be different. Once the Style property was set to lbOwnerDrawFixed the OnDrawItem event handler was called as expected.
I had a similar problem with a csOwnerDrawVariable-style combobox not triggering the OnMeasureItem event. As David Heffernan suggested, the issue was that the items had been added to the list at design time. The work-around I ended up using was to add code to the FormCreate event handler to copy the design-time list to a temporary variable, then clear the list and add the items back. Kludgy but effective.

Delphi: ToolButton & Action - funny

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.

Resources