I want the user to be able to press a button to reset a TCheckListBox to it's initial state (having no boxes checked).
See images below of an example of what I want to happen after clicking the button:
Changed to:
How would I go about doing this? I know there would probably be a loop involved, but I'm unsure where to start. Thanks for the help in advance.
There is nice method - look at official help.
If we open TCheckListBox help page, choose Methods and filter off "inherited" ones, we'll see CheckAll method
CheckListBox1.CheckAll(cbUnchecked);
For individual checkboxes (missed this is a TCheckListBox).
Something along these lines,
Let's assume the checkboxes are on a panel called panel1.
var n: Integer;
begin
for n := 0 to panel1.ComponentCount - 1 do
if panel1.Components[n] is TCheckbox then
Tcheckbox(panel1.components[n]).checked := False;
end;
Note: if there is an event associated with the checkbox, you need to set the event to nil before modifying it, and returning the event after - else, the event will trigger as if you clicked the box.
Related
I have a problem where:
I have a form with just a combobox.
The combobox has focus and mouse is not hovering over the form when item 3 happens.
I trigger the combobox's drop-down list to show on a key-press event.
When the drop-down list is visible and then I move my mouse pointer over the form, the pointer is either invisible, shows that it is busy, or shows the resizing icon but does not turn back to a normal pointer when over the form.
Is there something that can be done to assure that, when the drop-down of the combobox shows, that the mouse pointer is visible when I move the pointer over the form?
I have tried:
Applicaiton.ProcessMessages after showing the drop-down.
Changing focus to the form the combobox is on after showing the drop-down.
Adding Key := #0; after calling the drop-down to show.
procedure TForm1.ComboBox1KeyPress(Sender: TObject; var Key: Char);
begin
SendMessage(ComboBox1.Handle, CB_SHOWDROPDOWN, Integer(True), 0);
Key := #0;
end;
Tried using a timer to trigger the drop-down within the key-press event.
Tried using "SetCursor" after commanding the drop-down to appear.
Tried using ".DroppedDown", but did not see any difference in result from that of "SendMessage".
I would hope to be able to show the mouse pointer after the drop-down is displayed, but it is hidden instead. Thanks for any suggestions.
(NOTE: This problem I have run into is not exlusive to Delphi. I was able to duplicate the issue using Visual C# 2017. Either way, if there is a way to correct this, it would be good to know).
As already commented to the question, the issue is not Delphi related. You can observe the same behavior in dialog boxes which contains a similar combo that the OS presents. One example is the one on the "run" dialog.
Involving a single environment, re-setting the cursor in an OnDropDown event handler fixes the problem.
procedure TForm1.ComboBox1DropDown(Sender: TObject);
begin
winapi.windows.SetCursor(Screen.Cursors[Cursor]);
end;
Originally I tested the above because no one calls SetCursor after the drop down. Though it seems that no one calls it before either. So I have no idea about the cause or why the above fix works.
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.
This question already has answers here:
How can I use an action to determine a control's visibility?
(3 answers)
Closed 8 years ago.
When I make a component invisible by setting the connected TAction to invisible, the onupdate event will not trigger anymore. To recreate, do the following.
Create a new VCL forms application
Drop a button, a checkbox and an actionlist on the form.
Create a new action, and connect the button to it.
Write the following code for the actions OnExecute and OnUpdate event:
procedure TForm1.Action1Execute(Sender: TObject);
begin
ShowMessage('Test');
end;
procedure TForm1.Action1Update(Sender: TObject);
begin
TAction(Sender).Enabled := not CheckBox1.Checked;
TAction(Sender).Visible := TAction(Sender).Enabled;
end;
Run the application. The button is visible, and works properly. Check the checkbox, and the button disappears. Uncheck the checkbox. The button doesn't appear. In fact, if you put a breakpoint in Action1Update, you'll never get to it. Why is this, and how do I fix it?
No need to fix this, it works as designed. Only visible controls need to update their state, so only actions whose linked controls are visible are updated. When you hide the button there's no more reason to update the action.
Have the OnUpdate only call a separate routine that does what is required. Then you can call that routine from other places. Action lists were designed for that.
I understand what you're trying to do, and it makes sense that you would want it to work that way. However, here's a workaround for the way it does work.
You can update other controls in an OnUpdate also. You're not limited to updating the control that receives the notification. So, in the action for the control that determines visibility, you can set the visibility of the other controls there. In your case, that's the checkbox:
Create a new action (Action2) and assign it to Checkbox1.
Then in the checkbox action's OnUpdate:
procedure TForm1.Action2Update(Sender: TObject);
begin
Button1.Visible := TAction(Sender).Checked;
end;
Be sure to assign an OnExecute to the checkbox as well. Something as simple as this is fine:
procedure TForm1.Action2Execute(Sender: TObject);
begin
TAction(Sender).Checked := not TAction(Sender).Checked;
end;
To me, this still makes logical sense. You'll be able to look in one spot to see all of the controls whose visibility relies on that checkbox being set.
You can override the InitiateAction method on the form. This will happen whenever the application goes idle, just as on OnUpdate event does for each action.
As you can see in my question history, I'm developing a eBook manager, that will be open-source and I will release it in about 10 days, but I have a TRadioGroup, as you can see:
TRadioGroup Used On My Form http://img85.imageshack.us/img85/1830/radiogroup.png
And I want to store somethings in a variable(that needs to be a Integer) that will be "linked" with this TRadioGroup.
I need to do a if function like this:
Caption Of The TRadioButton -> Number that will need to be stored in the variable
Fit 2xWidth - Default -> 0
Fit 2xHeight -> 1
Fit Width -> 2
Fit Height -> 3
But I just used a TRadioGroup and a TRadioButton one time, different than in C# that I've used more than 20 times. Then I want to know what I need to put on the if function, because what it will do I already know how to do:
var
num: Integer;
begin
if(TRadioButton1 checked?)
begin
num := 0;
end;
end.
What I need to put inside the brackets of the if function?
PS: I'm going to put the credits on the program for the people that helped me in this little project.
A TRadioButton has the Checked property. But A TRadioGroup has the ItemIndex property.
The items in a TRadioGroup are stored using a TStrings. So you can associate an object to each option and you can cast an integer to a TObject to be stored.
Example:
// fill the radiogroup
radiogroup.Items.AddObject('Fit 2xWidth', TObject(0));
radiogroup.Items.AddObject('Fit 2xHeight', TObject(1));
radiogroup.Items.AddObject('Fit Width', TObject(2));
radiogroup.Items.AddObject('Fit Height', TObject(3));
radiogroup.ItemIndex := 0;
To read the current setting:
value := radiogroup.ItemIndex;
Or to get the associated integer:
index := radiogroup.ItemIndex;
Assert(index>=0); // Sanity check
value := Integer(radiogroup.Items.Objects[index]);
In your case, the values are 0 to 3 so you can use the ItemIndex.
As a note, if is not a function. A function is a piece of code that returns a value based on the input parameters. If is a statement, which is a command that can be executed. The if statement is special because it enables you to execute a different statement based on the if condition.
Just a little TIP: Setting .ItemIndex does not send keyboard focus to the radio item, i know how to fix it, read ahead.
Instead of selecting by code a Radio in a RadioGroup by setting .ItemIndex it is much better to do it by sending focus to the radio item; just to be very clear: i mean sending focus just to the radio item, not the whole radio group.
Instead of: radiogroup.itemindex:=TheIndex;
Do it as this: TRadioButton(radiogroup.Controls[TheIndex]).SetFocus;
It will make the radio item to be selected and send the keyboard focus to it, so it will display the dotted rectangle arroud it, just as if the user had clicked on it.
Note1: To see it in action use keyboard cursor keys and compare behavor of just setting .ItemIndex and sending focus to radio item.
Note2: If you use TRadioButton(radiogroup.Controls[TheIndex]).SetFocus; then there is no no need to set .ItemIndex at all, it will also be done.
Hope that helps someone having the same problem as me, when need to set it by code, for example to avoid circular keyboard behavor, for example for making it to stay on last radio item when last radio item is selected and keyboard right cursor is pressed, same for first.
I have a TListBox with multiselect and ExtendedSelect both set to true. I need to be able to drag multiple items in the list box to re-arrange them. My problem is what happens when the user clicks on an item that is already selected without holding down the CTRL or SHIFT key.
Case 1: DragMode is set to dmManual
The selection is cleared before the mouse down. This will not allow multiple items to be dragged.
Case 2: DragMode is set to dmAutomatic
The MouseDown event never fires. The selection is not cleared so dragging is OK, but the user cannot clear the selection by clicking on one of the selected items. This really causes a problem if all the items are selected or the next item the user wants to select was part of the current selection.
Note that this problem only happens if you assign something to the DragObject in the OnStartDrag procedure. I think the problem would go away if OnStartDrag would only start after the user moves the mouse. I have Mouse.DragImmediate := false set but I still get the StartDrag fired as soon as I click on an item in the list box.
I am using Delphi 7 for this project but I see the same behavior in Delphi 2007.
I have played with this for a while. And observe the same effects.
I would use Case2 and add a (Select All/Deselect All) button to the list. It even adds extra functionality and solves the most annoying part of the problem.
Use Case 2 and when the TListBox.OnMouseUp event fires check to see if multiple items are selected and were dragged. If multiple items are selected, but weren't dragged, then deselect all items apart from the clicked item.
I would use this method because Windows Explorer works this way.
Bit of a kludge but this works. DragMode on the ListBox is set to dmAutomatic.
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
iDropIdx, i: Integer;
pDropPoint: TPoint;
slSelected: TStrings;
begin
{Which item is being dropped onto?}
pDropPoint := Point(X, Y);
iDropIdx := ListBox1.ItemAtPos(pDropPoint, False);
slSelected := TStringList.Create;
try
{Copy the selected items to another string list}
for i := 0 to Pred(ListBox1.Items.Count) do
begin
if (ListBox1.Selected[i]) then
slSelected.Append(ListBox1.Items[i]);
end;
{Find the selected items in the listbox and swap them with the drop target}
for i := 0 to Pred(slSelected.Count) do
begin
ListBox1.Items.Exchange(ListBox1.Items.IndexOf(slSelected[i]), iDropIdx);
inc(iDropIdx);
end;
finally
slSelected.Free;
end;
end;
I'm not sure why this makes a difference but if I change the DragObject to be a TDragControlObjectEx (instead of a TDragObjectEx) I get the behavior I am looking for. Drag mode is set to Automatic.
I tried to look and see what this was affecting but I could not figure it out.