Topics

Help with sysListView selection

Alberto Buffolino
 

Hi all,
I'm working on ColumnsReview add-on, but I have a very specific question about sysListView, so nvda-devel could be a good place too...
I'd like to select/unselect programmatically one or more list items, but it seems not so easy indeed. I found this promising page:
http://vbnet.mvps.org/index.html?code/comctl/lvselectall.htm
and so, starting from a list item and opening NVDA console, I wrote:
***
from NVDAObjects.IAccessible.sysListView32 import *
import watchdog
LVM_SETITEMSTATE = (LVM_FIRST + 43)
***
but then I don't know how to proceed exactly. I tried creating an LVITEM instance (class is in sysListView32) with various mask/state/etc parameters, and passing it as 4th arguments of
***
watchdog.cancellableSendMessage(nav.parent.windowHandle, LVM_SETITEMSTATE, -1, LVITEMInstance)
***
but even if I receive no errors, I don't see changes... and I tried and tried various solutions, with LPARAM, and so on, without success.
Do you have any suggestions?
Thanks in advance.
Alberto

Abdel
 

Hi Alberto,

You wrote:

I tried creating an LVITEM instance (class is in sysListView32) with various mask/state/etc parameters, and passing it as 4th arguments of watchdog.cancellableSendMessage.

In fact, the fourth parameter of watchdog.cancellableSendMessage, or the second parameter of the LVM_SETITEMSTATE message, is not an instance of the LVITEM structure, but a pointer to this instance.

Here is an example for selecting all items that works here on the desktop, under a Windows-10.

It is imperative that the type of your list view is as follows:

class 'NVDAObjects.IAccessible.sysListView32.List'

For example, you can put your nav object on the first parent of the desktop window or use focus.parent.windowHandle in your console.

Once on your desktop, you open the Python console with NVDA + Control + Z.

This done, you write the following:

from NVDAObjects.IAccessible.sysListView32 import *
from watchdog import cancellableSendMessage
from ctypes import byref
# Instantiation of the LVITEM object.
lvItem = LVITEM (mask=LVIF_STATE, state=LVIS_SELECTED, stateMask=LVIS_SELECTED)
# You must then pass this instantiation as a pointer, using byref, to the cancellableSendMessage function.
cancellableSendMessage (nav.windowHandle, LVM_SETITEMSTATE, -1, byref(lvItem))

For unselecting all items you juste have to assign LVIF_STATE to the mask member and LVIS_SELECTED to stateMask as described here:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/45b14a4b-6ee8-42c4-9d94-912008931552/deselect-all-items-in-listview-c?forum=vcgeneral

However, I find that it does not always work, so it's not really reliable.

You will find a detailed description of the members of the LVITEM structure on Microsoft Doc:

https://docs.microsoft.com/en-us/windows/desktop/api/commctrl/ns-commctrl-taglvitema

Hope this helps.

Kind regards,
Abdel.


Le 05/04/2019 à 19:27, Alberto Buffolino a écrit :
Hi all,
I'm working on ColumnsReview add-on, but I have a very specific question about sysListView, so nvda-devel could be a good place too...
I'd like to select/unselect programmatically one or more list items, but it seems not so easy indeed. I found this promising page:
http://vbnet.mvps.org/index.html?code/comctl/lvselectall.htm
and so, starting from a list item and opening NVDA console, I wrote:
***
from NVDAObjects.IAccessible.sysListView32 import *
import watchdog
LVM_SETITEMSTATE = (LVM_FIRST + 43)
***
but then I don't know how to proceed exactly. I tried creating an LVITEM instance (class is in sysListView32) with various mask/state/etc parameters, and passing it as 4th arguments of
***
watchdog.cancellableSendMessage(nav.parent.windowHandle, LVM_SETITEMSTATE, -1, LVITEMInstance)
***
but even if I receive no errors, I don't see changes... and I tried and tried various solutions, with LPARAM, and so on, without success.
Do you have any suggestions?
Thanks in advance.
Alberto


Alberto Buffolino
 

Abdel, il 07/04/2019 23.14, ha scritto:
However, I find that it does not always work, so it's not really reliable.
Alberto:
Hi Abdel, and Robert,
first, sorry for delay.
Then, thanks for your support, as usual.
Unfortunately, yes, use of LVITEM seems not very reliable, I encountered a list where it brings even to program crash... I must discover an alternative method.
Thanks again.
Alberto

Robert Hänggi
 

Hi Alberto
Did you try the native method first?

obj.IAccessibleObject.accSelect

Check for the bitness as well, I think 32-bit should work as outlined before.
However, make sure to use the right LVITEM for 64-bit.

Cheers
Robert

Alberto Buffolino
 

Robert Hänggi, il 27/05/2019 19.10, ha scritto:
Hi Alberto
Did you try the native method first?
obj.IAccessibleObject.accSelect
Alberto:
Hi Robert,
thanks, I tried some time ago, but only today I found an explanation of parameters, starting from here:
https://docs.microsoft.com/it-it/windows/desktop/api/oleacc/nf-oleacc-iaccessible-accselect
and ok, it seems to work (with SELFLAG_ADDSELECTION). Now I'm investigating about how to get STATE_SYSTEM_MULTISELECTABLE from accState, to provide multi-selection only when really available; I get a VARIANT structure, but I don't understand how to process it and DuckDuckGo does not help me for now, hmm.
Alberto

Alberto Buffolino
 

Alberto Buffolino via Groups.Io, il 28/05/2019 19.46, ha scritto:
Now I'm
investigating about how to get STATE_SYSTEM_MULTISELECTABLE from accState, to provide multi-selection only when really available
Alberto:
ok, I saw in getting devInfo in NVDAObject/IAccessible/__init__.py.
If nav is a list item, then relevant code is:
***
from oleacc import STATE_SYSTEM_MULTISELECTABLE
states = nav.IAccessibleObject.accState(nav.IAccessibleChildID)
if states & STATE_SYSTEM_MULTISELECTABLE:
print 'multi-selection available'
***
...and things proceed...
Alberto

Robert Hänggi
 

Nice that you've found a solution.
I actually wanted to hint at the multi-selection flag.
Best
Robert

On 28/05/2019, Alberto Buffolino <a.buffolino@...> wrote:
Alberto Buffolino via Groups.Io, il 28/05/2019 19.46, ha scritto:
Now I'm
investigating about how to get STATE_SYSTEM_MULTISELECTABLE from
accState, to provide multi-selection only when really available
Alberto:
ok, I saw in getting devInfo in NVDAObject/IAccessible/__init__.py.
If nav is a list item, then relevant code is:
***
from oleacc import STATE_SYSTEM_MULTISELECTABLE
states = nav.IAccessibleObject.accState(nav.IAccessibleChildID)
if states & STATE_SYSTEM_MULTISELECTABLE:
print 'multi-selection available'
***
...and things proceed...
Alberto