How do I check/uncheck items in a ListBox with pywinauto? - listbox

I am trying to automate the Cambium LINKPlanner application using pywinauto, and found controls for almost everything I needed. However, there is a checked list box which has the identifier 'ListBox' and there doesn't seem to be any way to check/uncheck the items in the list.
I can list the contents of the ListBox:
>>> app.LINKPlanner.ListBox.item_texts()
['PMP 450b High Gain', 'PMP 450b Mid-gain', 'PMP450 (retired)', 'PMP450d (retired)', 'PMP450i', 'PMP450i ATEX/HAZLOC']
I can highlight an item in the ListBox either by name or position:
>>> app.LINKPlanner.ListBox.select('PMP450i')
<win32_control.ListBoxWrapper - '', ListBox, 70154>
>>> app.LINKPlanner.ListBox.select(2)
<win32_control.ListBoxWrapper - '', ListBox, 70154>
But I can't check/uncheck the checkbox inside the list items.
Any suggestions?
EDIT:
Using Vasily's suggestion, I was able to see the bounding box, then use click_input to click the checkbox.
>>> app.LINKPlanner.ListBox.select('PMP 450b High Gain').item_rect(0)
<RECT L0, T0, R276, B17>
>>> app.LINKPlanner.ListBox.select('PMP 450b High Gain').click_input(coords=(9,9))

If it's detected as ListBox, it may be owner-drawn check boxes which can't be detected separately. I'd suggest using method .item_rect(item_name) and then method .click_input(). Also method .client_to_screen() may be helpful.

I'm using .select("item text") and .send_keys("{SPACE}").
I tried Vasily's answer to use item_rect(). That works but it has some drawbacks.
In my case item_rect was not reliable: it was always 2 to 4 pixels taller than in reality. This error adds up for consecutive items. My script ended up clicking the wrong checkboxes.
Also, if the list is too long it requires scrolling. This requires a separate workaround.
I found my ListBox would toggle the checkbox at the press of the space bar.
So I'm doing this instead:
# De-select all (there is a button to do this).
dialog.window(title="Deselect all").click()
# Select the desired items.
for item in ["Item 1 name", "Item 5 name"]:
dialog.ListBox.select(item)
dialog.ListBox.type_keys("{SPACE}")

Related

How to SelectAll only visible VirtualTreeView items?

I have hidden some VirtualTreeView items using VirtualTree.IsVisible[n] := false;.
In one function I iterate through all selected items using VirtualTree.GetNextSelected(n); method. But there is a problem - if I manually select a few items for example using CTRL-click or SHIFT, the items which get looped are the ones selected.
But if I press CTRL + A to select all then GetNextSelected gives me all nodes, including those which are hidden.
I did a workaround by checking if (VirtualTree.IsVisible[n]) ... to avoid looping through all items and fetch only visible ones, but this seems like a bug or maybe there is an option which controls how CTRL + A will behave - will it select only visible nodes or all of them?
So is this a bug or maybe I missed some selection option (I examined them all) or am I supposed to use some other method for looping only through visible nodes?
As it appears by David Heffernan and Joachim Marder, it is a design choice and not a bug. For this reason, one needs to introduce a workaround when looping through items using GetNextSelected by checking if (VirtualTree.IsVisible[n]) ... to loop only through visible items.

TComboBox.AutoCloseUp Property: What does it do?

From the documentations:
Specifies whether the drop-down closes up automatically when the user
selects an item.
I have played with this property (combined with AutoComplete and AutoDropDown) and I just can't seem to figure out the UI behavior of this property.
Setting it to True or False I can't see any difference in how it behaves.
Can anyone explain to me what it does exactly?
You will see the difference if you have AutoCloseUp = True and also AutoDropDown = True. For example, if you have items '0', '1' and '2' and the ComoBox has focus, when you use the keyboard and press 2 the dropdown list flashes briefly and is closed again with item '2' selected. If you change AutoCloseUp = False, then the dropdownlist remains open (and you can change your selection with the arrow keys) until you indicate your selection with Enter
If you operate the combo only with your mouse, then there's no difference.
Addition after comments
If you add to my example items '22' and 'more' and you also have AutoComplete = True (which it is by default) you will note the following:
item '22' is not selectable with two consecutive hits on 2. It is of course still selectable with the arrow keys, like all other items.
The AutoCloseUp feature closes the dropdown when AutoComplete finds a matching item for all sofar typed keys. If you type m, o, r the list is still open, 'more' selected and the list is finally closed if you type the missing e.

Increase/Decrease a field in OpenOffice Calc

I'm trying to count (and sum up) different (physical) items and input those counts in a spreadsheet. Is there a way to increase (or decrease) an integer in a field in OpenOffice Calc? Mouse or keyboard input.
Either a shortcut+macro combination or something along the lines of these (fictive) arrows:
i.e. pressing up would increase the field to value 43
In fact I would be happy for any suggestion for an open programme that would digitalize such input and produce some sort of csv or similar output.
Via View - Toolbars - Form Controls get the toolbar Form Controls visible.
There you have Spin Button control (see tooltips).
Insert this on the sheet by clicking it and pull the size of it with the mouse. Pull it longer than width.
Right click the control and select Control... from the context menu.
On the Data tab set the Linked cell to A3 for example.
Now switch the design mode to off by clicking the corresponding button at the toolbar Form Controls (see tooltips).

How to a TFilterComboBox (drop down box) larger?

By default, when I click a Delphi TFilterComboBox it will display only 8 items. To access the rest of them, the user has to scroll down which is such a wast of time. Can I make it display more items (or even all of them)?
I have found an answer that says: "If you click the combobox in the resource template editor, you can drag its "opened" frame size to fit more items".
But I don't know what is this "resource template editor".
Normally one would like to use its DropDownCount property to set the maximum number of items visible in the dropdown window. But that seems to be hidden here (i.e. it is protected). I guess one can send it a message directly:
SendMessage(FilterComboBox1.Handle, CB_SETMINVISIBLE,
WPARAM(YourDropDownCount), 0);

Creating a ComboBox with one or more separator items?

I'm using Delphi7 and I'd like to have a ComboBox with separator items (Just like in popup menus).
I've seen this beautifully implemented in Mozilla Sunbird (I know, it's not Delphi...) the following way:
The separator item is a simple gray line
drawn in the center of the item
If you hover over the separator with
the mouse, the selection doesn't
appear
If the user clicks the separator,
it's not selected either AND the
combobox doesn't closeup.
No. 1 could be implemented using DrawItem. I could live without No. 2 because I have no idea about that.
For No. 3 I'm asking for your help. I've figured out that straight after closing up a CBN_CLOSEUP message is sent to the combobox.
I thought about hooking the window proc and if CBN_CLOSEUP is sent to a certain combobox then countering it. But I'm unsure if this is the best solution, or maybe there are other, more elegant ways?
Whatever the solution is, I'd like to have a standard ComboBox which supports WinXP/Vista/7 theming properly.
Thanks!
Edit: For a working component please see this thread:
Can you help translating this very small C++ component to Delphi?
I played around with making unclickable separator items (as described in this answer) and ran into several UI glitches. The problem is that combo boxes have several aspects to their behavior that can be hard to get exactly right:
Pressing the up and down arrow keys navigates the list while the list is dropped down.
Pressing Enter closes the dropped down list, selecting the current item.
Pressing Escape closes the dropped down list, selecting the current item (if the current item was chosen with the up and down arrow keys) or the last selected item.
If the combo box has the focus, then pressing the up and down arrow keys to changes the current selection without displaying the list.
If the combo box has the focus, then typing anything selects the combo box item matching whatever is typing.
If the combo box has the focus, then pressing F4 drops down the combo box list, which can then be controlled by keyboard or mouse.
Ensuring that disabled separator items don't respond to any of these events (plus any other events which I may be missing, e.g., screen readers?) seems fraught with error.
Instead, the approach I'm using is to draw the separator as part of the item:
Use a variable height owner draw combo box.
Add 3 pixels to the height for any items that need separators.
Draw a horizontal line at the top of each item needing a separator.
Here's some C++Builder code to accomplish this; translating it to Delphi should be easy enough.
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
bool draw_separator = NeedsSeparator(Index) &&
!State.Contains(odComboBoxEdit);
TCanvas *canvas = dynamic_cast<TCustomCombo*>(Control)->Canvas;
canvas->FillRect(Rect);
TRect text_rect = Rect;
// Add space for separator if needed.
if (draw_separator) {
text_rect.Top += 3;
}
canvas->TextOut(text_rect.Left + 3,
(text_rect.Top + text_rect.Bottom) / 2 -
canvas->TextHeight(ComboBox1->Items->Strings[Index]) / 2),
ComboBox1->Items->Strings[Index]);
// Draw a separator line above the item if needed.
if (draw_separator) {
canvas->Pen->Color = canvas->Font->Color;
canvas->MoveTo(Rect.Left, Rect.Top + 1);
canvas->LineTo(Rect.Right, Rect.Top + 1);
}
}
void __fastcall TForm1::ComboBox1MeasureItem(
TWinControl * /* Control */, int Index, int &Height)
{
Height = ComboBox1->ItemHeight;
// Add space for the separator if needed.
if (Index != -1 && NeedsSeparator(Index)) {
Height += 3;
}
}
What you want is an owner-drawn combobox. See this: http://delphi.about.com/od/vclusing/a/drawincombobox.htm
Also, this seems to solve making the item unclicable:
http://borland.newsgroups.archived.at/public.delphi.vcl.components.using.win32/200708/0708225320.html
As far as I know there is no VCL way of doing that, so you'll have to subclass the combobox. It would be nice to create component encapsulating those functionalities so you can reuse them easily.
God bless
If you want your controls to look good use the free SpTBXLib. It supports combo style components which popup a popup menu with lines.

Resources