TListbox - OnChangeEvent does not fire reliable on multiselect - delphi

I'm using XE7 and FMX.
My problem is that the OnChange-Event for TListbox works not correctly with multiselect (it does not fire everytime when a change occured).
Steps to reproduce:
Create a FMX-application and add a TListbox to his form.
Add items to this listbox.
Set 'MultiSelectStyle' of Listbox to 'default'.
Handle the OnChangeEvent (set a breakpoint or do something ...).
Now run the project and click on the first Item -> OnChange is executed.
But if first item is clicked again the OnChange will not be executed.
Can tell me somebody how I can fix this, so that everytime when a the selection changes I get a event.

From documentation FMX.ListBox.TCustomListBox.OnChange:
Occurs when the selection in the list box changes.
Write an OnChange event handler to take specific action immediately after a new item or items are selected in the list box.
Use the OnClick or OnItemClick event instead to monitor when the user reselects the same selection. And keep the OnChange handler for all new selections.

Related

How to add some buttons to selected ListBox item via style?

Is there a way to add some buttons to the selected ListBoxItem by adding these buttons to a style which is being used for the selected item?
I didn't yet find a suitable style FMX uses to display the selected item.
My goal is to have some buttons on the selected item with context based functionality. While I can do this by reparenting a TButton created in code in the OnPaint event of the ListBox, this works for Android but not for Win32 as it is being overpainted by the selection.
Other solutions like doing this in OnItemClick or OnClick are sluggish or only work properly on Win32 but not on Android and would need to be put into a timer fired on click.

ListBox OnClick event not firing after SpinEdit OnExit event changes ListBox.Font.Size

I have a ListBox on my form with an OnClick event registered to it. This event works as intended, except for one particular situation:
My form contains a SpinEdit (values 8-12), to let the user adjust the ListBox.Font.Size property (I also adjust the ListBox.ItemHeight property is accordingly). These adjustments are done in the SpinEdits OnExit event and also work as intended.
The problem however occurs when the SpinEdit is selected, the value is changed and then the ListBox is clicked. So what should happen is:
SpinEdit OnExit fired: ListBox.Font.Size adjusted.
ListBox OnClick fired: subsequent actions defined in the OnClick event.
But in reality, only the SpinEdits OnExit is fired and the fontsize is adjusted correctly, but the OnClick event of ListBox does not fire. Not that big a deal in itself, but after that point the entire ListBox has become unresponsive to mouseclicks!
Noteworthy observations:
Switching back and forth to another application/window and back to
my application: responsiveness of the ListBox is regained.
After triggering the problem, interacting with a CheckListBox that is on the same form, followed by clicking on the ListBox fires the ListBox Onclick event.
Triggering the SpinEdits OnExit event with the Enter key introduces no problems.
The form contains a few more SpinEdit objects with OnExit events, that do not change properties of the ListBox. Exiting these SpinEdits by clicking the ListBox works just fine, with the OnClick event executed right after the SpinEdits OnExit event.

TToolbar Button with dropdown menu greyed out

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

Combo box - typing selection then clicking out of focus - doesn't select the typed item

I'm having an issue with the combo box. I have an event handler for OnClick which refreshes data based on what item was selected. The problem is when this scenario occurs:
Drop-down the combo box to list the various options
Type on the keyboard to find a matching item
Combo box changes this selection and calls the OnClick event
My screen refreshes due to this selection / event
Click somewhere outside of the combo box to take the focus away from it
Combo box goes back to the previous selection, even though OnClick was already called
Even though Combo box changed back to prior selection, OnClick isn't called again
After this, Combo Box shows different value than what my data actually represents
So when you open a combo box, and type a few letters on the keyboard to find the item in the drop-down list, OnClick is fired which refreshes my screen. But when you click somewhere outside the combo box (thus taking the focus away from it), the combo box changes back to whatever value was previously selected, instead of what I had typed. And at the same time, the OnClick event isn't fired, so the combo box shows the incorrect value compared to what I had loaded on the screen.
How do I make the combo box stay on the selected item in this scenario of typing the item on the keyboard?
In my code, I deal with this using the OnCloseUp event. Well, in fact I'm using a sub-classed combo for my drop-down lists and they override both the Change and CloseUp methods:
procedure TMyDropDownList.Change;
begin
RespondToChange;
inherited;
end;
procedure TMyDropDownList.CloseUp;
begin
RespondToChange;
inherited;
end;
The RespondToChange method reacts to the new ItemIndex value. If it is expensive to react to every single change whilst the combo is dropped down, then you might consider omitting the call to RespondToChange from the Change method.
You could use OnExit to make the entry with the keyboard jive with the Index on the ComboBox; where VarS is assigned OnChange and is the answer you would like to keep:
procedure TForm1.ComboBox1Exit(Sender: TObject);
begin
{ Windows keyboard select bug, force use of selected }
ComboBox1.ItemIndex := ComboBox1.Items.IndexOf(VarS);
end;
I would call this a bug in the ComboBox design.

Show different popup menu depending on what column the mouse is over in a Delphi TListView control?

I have a Delphi 6 application that has a TJvListView control. I have a popup menu tied to that control via the control's PopupMenu property. What I would like to do is show a different popup menu based on which column the user had the mouse over when they right clicked, with the additional option to not show a popup menu at all if the current column does not need one. How can I do this?
Thanks to this detailed sample by Remy Lebeau on in-place editing in a TListView I know what row and column the mouse is over except for one wrinkle. The mouse down event where I determine the current row and column occurs after the popup menu is exited.
I now need to know two things. First, how can I get some event to fire before the popup menu shows after a right mouse click so I can record the current list view row and column and suppress the popup menu if I want to, and second, how I can show a different popup based on the current column. I am hoping to avoid having to write a bunch of mini-forms instead of using the TListView PopupMenu property and supporting code. Is there a simple solution, perhaps some fancy footwork in a sub-class I should create around TJvListView?
You could perform the detection in mousemove instead of mousedown/Click and change the popupmenu depending.
You also could remove any popupmenu and call the wished via p.pupup in mousedown as you desire.

Resources