how do I set the acc_role of a ListViewGadget's items?

Just starting out? Need help? Post your questions and find answers here.
Quin
Addict
Addict
Posts: 1135
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

how do I set the acc_role of a ListViewGadget's items?

Post by Quin »

Hi,
I have a

Code: Select all

ListViewGadget()
in my program that I use the

Code: Select all

#PB_ListView_ClickSelect
flag on. This works fine, but I want the list to give slightly more feedback to screen reader users on Windows, so I figured I'd set the role of each item to a checkbox. However, I can't figure out how to do it. It seems that PB (quite helpfully) has the

Code: Select all

IAccessible
interface wrapped, but it only contains

Code: Select all

put_accName
and

Code: Select all

put_accValue
, nothing about roles. You can get the role, but not easily set it. Is it possible to do what I'm trying a different way?
Thanks!
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: how do I set the acc_role of a ListViewGadget's items?

Post by breeze4me »

Do you mean something like this?

Code: Select all

; /* System object Id's */
#OBJID_WINDOW            = 0
#OBJID_SYSMENU           = -1
#OBJID_TITLEBAR          = -2
#OBJID_MENU              = -3
#OBJID_CLIENT            = -4
#OBJID_VSCROLL           = -5
#OBJID_HSCROLL           = -6
#OBJID_SIZEGRIP          = -7
#OBJID_CARET             = -8
#OBJID_CURSOR            = -9
#OBJID_ALERT             = -10
#OBJID_SOUND             = -11
#OBJID_QUERYCLASSNAMEIDX = -12
#OBJID_NATIVEOM          = -16

#ROLE_SYSTEM_TITLEBAR = $1
#ROLE_SYSTEM_MENUBAR = $2
#ROLE_SYSTEM_SCROLLBAR = $3
#ROLE_SYSTEM_GRIP = $4
#ROLE_SYSTEM_SOUND = $5
#ROLE_SYSTEM_CURSOR = $6
#ROLE_SYSTEM_CARET = $7
#ROLE_SYSTEM_ALERT = $8
#ROLE_SYSTEM_WINDOW = $9
#ROLE_SYSTEM_CLIENT = $a
#ROLE_SYSTEM_MENUPOPUP = $b
#ROLE_SYSTEM_MENUITEM = $c
#ROLE_SYSTEM_TOOLTIP = $d
#ROLE_SYSTEM_APPLICATION = $e
#ROLE_SYSTEM_DOCUMENT = $f
#ROLE_SYSTEM_PANE = $10
#ROLE_SYSTEM_CHART = $11
#ROLE_SYSTEM_DIALOG = $12
#ROLE_SYSTEM_BORDER = $13
#ROLE_SYSTEM_GROUPING = $14
#ROLE_SYSTEM_SEPARATOR = $15
#ROLE_SYSTEM_TOOLBAR = $16
#ROLE_SYSTEM_STATUSBAR = $17
#ROLE_SYSTEM_TABLE = $18
#ROLE_SYSTEM_COLUMNHEADER = $19
#ROLE_SYSTEM_ROWHEADER = $1a
#ROLE_SYSTEM_COLUMN = $1b
#ROLE_SYSTEM_ROW = $1c
#ROLE_SYSTEM_CELL = $1d
#ROLE_SYSTEM_LINK = $1e
#ROLE_SYSTEM_HELPBALLOON = $1f
#ROLE_SYSTEM_CHARACTER = $20
#ROLE_SYSTEM_LIST = $21
#ROLE_SYSTEM_LISTITEM = $22
#ROLE_SYSTEM_OUTLINE = $23
#ROLE_SYSTEM_OUTLINEITEM = $24
#ROLE_SYSTEM_PAGETAB = $25
#ROLE_SYSTEM_PROPERTYPAGE = $26
#ROLE_SYSTEM_INDICATOR = $27
#ROLE_SYSTEM_GRAPHIC = $28
#ROLE_SYSTEM_STATICTEXT = $29
#ROLE_SYSTEM_TEXT = $2a
#ROLE_SYSTEM_PUSHBUTTON = $2b
#ROLE_SYSTEM_CHECKBUTTON = $2c
#ROLE_SYSTEM_RADIOBUTTON = $2d
#ROLE_SYSTEM_COMBOBOX = $2e
#ROLE_SYSTEM_DROPLIST = $2f
#ROLE_SYSTEM_PROGRESSBAR = $30
#ROLE_SYSTEM_DIAL = $31
#ROLE_SYSTEM_HOTKEYFIELD = $32
#ROLE_SYSTEM_SLIDER = $33
#ROLE_SYSTEM_SPINBUTTON = $34
#ROLE_SYSTEM_DIAGRAM = $35
#ROLE_SYSTEM_ANIMATION = $36
#ROLE_SYSTEM_EQUATION = $37
#ROLE_SYSTEM_BUTTONDROPDOWN = $38
#ROLE_SYSTEM_BUTTONMENU = $39
#ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3a
#ROLE_SYSTEM_WHITESPACE = $3b
#ROLE_SYSTEM_PAGETABLIST = $3c
#ROLE_SYSTEM_CLOCK = $3d
#ROLE_SYSTEM_SPLITBUTTON = $3e
#ROLE_SYSTEM_IPADDRESS = $3f
#ROLE_SYSTEM_OUTLINEBUTTON = $40

DataSection
  ; DEFINE_GUID(CLSID_AccPropServices, 0xb5f8350b, 0x0548, 0x48b1, 0xa6, 0xee, 0x88, 0xbd, 0x00, 0xb4, 0xa5, 0xe7);
  CLSID_AccPropServices:
  Data.l $b5f8350b
  Data.w $0548, $48b1
  Data.b $a6, $ee, $88, $bd, $00, $b4, $a5, $e7
  
  ; DEFINE_GUID(IID_IAccPropServices, 0x6e26e776, 0x04f0, 0x495d, 0x80, 0xe4, 0x33, 0x30, 0x35, 0x2e, 0x31, 0x69);
  IID_IAccPropServices:
  Data.l $6e26e776
  Data.w $04f0, $495d
  Data.b $80, $e4, $33, $30, $35, $2e, $31, $69
  
  ; DEFINE_GUID(PROPID_ACC_ROLE, 0xcb905ff2, 0x7bd1, 0x4c05, 0xb3, 0xc8, 0xe6, 0xc2, 0x41, 0x36, 0x4d, 0x70);
  PROPID_ACC_ROLE:
  Data.l $cb905ff2
  Data.w $7bd1, $4c05
  Data.b $b3, $c8, $e6, $c2, $41, $36, $4d, $70
EndDataSection


; https://learn.microsoft.com/en-us/windows/win32/winauto/using-direct-annotation
Procedure SetAccessibleProperties(Gadget)
  Protected pAccPropServices.IAccPropServices
  Protected var.VARIANT
  Protected hr.l, hwnd, ItemCount, i
  
  If GadgetType(Gadget) = #PB_GadgetType_ListView
    ItemCount = CountGadgetItems(Gadget)
    hwnd = GadgetID(Gadget)
    If ItemCount > 0
      hr = CoCreateInstance_(?CLSID_AccPropServices, 0, #CLSCTX_INPROC_SERVER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER, ?IID_IAccPropServices, @pAccPropServices)
      If hr = #S_OK And pAccPropServices
        var\vt = #VT_I4
        var\lVal = #ROLE_SYSTEM_CHECKBUTTON
        
        For i = 1 To ItemCount
          hr = pAccPropServices\SetHwndProp(hwnd, #OBJID_CLIENT, i, ?PROPID_ACC_ROLE, var)
          If hr <> #S_OK
            Debug "Error: item " + i
          EndIf
        Next
        pAccPropServices\Release()
      EndIf
    EndIf
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListViewGadget(0, 10, 10, 250, 120, #PB_ListView_ClickSelect)
  For a = 1 To 12
    AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview")
  Next
  
  SetAccessibleProperties(0)
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Quin
Addict
Addict
Posts: 1135
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: how do I set the acc_role of a ListViewGadget's items?

Post by Quin »

Wow, thank you so much! This works amazingly! The only thing I need to do now is make the states report properly. Currently they always say unchecked, and selected/not selected is reported when I hit space. Where are the Microsoft docs for these interfaces?
breeze4me wrote: Wed Mar 13, 2024 7:00 pm Do you mean something like this?

Code: Select all

; /* System object Id's */
#OBJID_WINDOW            = 0
#OBJID_SYSMENU           = -1
#OBJID_TITLEBAR          = -2
#OBJID_MENU              = -3
#OBJID_CLIENT            = -4
#OBJID_VSCROLL           = -5
#OBJID_HSCROLL           = -6
#OBJID_SIZEGRIP          = -7
#OBJID_CARET             = -8
#OBJID_CURSOR            = -9
#OBJID_ALERT             = -10
#OBJID_SOUND             = -11
#OBJID_QUERYCLASSNAMEIDX = -12
#OBJID_NATIVEOM          = -16

#ROLE_SYSTEM_TITLEBAR = $1
#ROLE_SYSTEM_MENUBAR = $2
#ROLE_SYSTEM_SCROLLBAR = $3
#ROLE_SYSTEM_GRIP = $4
#ROLE_SYSTEM_SOUND = $5
#ROLE_SYSTEM_CURSOR = $6
#ROLE_SYSTEM_CARET = $7
#ROLE_SYSTEM_ALERT = $8
#ROLE_SYSTEM_WINDOW = $9
#ROLE_SYSTEM_CLIENT = $a
#ROLE_SYSTEM_MENUPOPUP = $b
#ROLE_SYSTEM_MENUITEM = $c
#ROLE_SYSTEM_TOOLTIP = $d
#ROLE_SYSTEM_APPLICATION = $e
#ROLE_SYSTEM_DOCUMENT = $f
#ROLE_SYSTEM_PANE = $10
#ROLE_SYSTEM_CHART = $11
#ROLE_SYSTEM_DIALOG = $12
#ROLE_SYSTEM_BORDER = $13
#ROLE_SYSTEM_GROUPING = $14
#ROLE_SYSTEM_SEPARATOR = $15
#ROLE_SYSTEM_TOOLBAR = $16
#ROLE_SYSTEM_STATUSBAR = $17
#ROLE_SYSTEM_TABLE = $18
#ROLE_SYSTEM_COLUMNHEADER = $19
#ROLE_SYSTEM_ROWHEADER = $1a
#ROLE_SYSTEM_COLUMN = $1b
#ROLE_SYSTEM_ROW = $1c
#ROLE_SYSTEM_CELL = $1d
#ROLE_SYSTEM_LINK = $1e
#ROLE_SYSTEM_HELPBALLOON = $1f
#ROLE_SYSTEM_CHARACTER = $20
#ROLE_SYSTEM_LIST = $21
#ROLE_SYSTEM_LISTITEM = $22
#ROLE_SYSTEM_OUTLINE = $23
#ROLE_SYSTEM_OUTLINEITEM = $24
#ROLE_SYSTEM_PAGETAB = $25
#ROLE_SYSTEM_PROPERTYPAGE = $26
#ROLE_SYSTEM_INDICATOR = $27
#ROLE_SYSTEM_GRAPHIC = $28
#ROLE_SYSTEM_STATICTEXT = $29
#ROLE_SYSTEM_TEXT = $2a
#ROLE_SYSTEM_PUSHBUTTON = $2b
#ROLE_SYSTEM_CHECKBUTTON = $2c
#ROLE_SYSTEM_RADIOBUTTON = $2d
#ROLE_SYSTEM_COMBOBOX = $2e
#ROLE_SYSTEM_DROPLIST = $2f
#ROLE_SYSTEM_PROGRESSBAR = $30
#ROLE_SYSTEM_DIAL = $31
#ROLE_SYSTEM_HOTKEYFIELD = $32
#ROLE_SYSTEM_SLIDER = $33
#ROLE_SYSTEM_SPINBUTTON = $34
#ROLE_SYSTEM_DIAGRAM = $35
#ROLE_SYSTEM_ANIMATION = $36
#ROLE_SYSTEM_EQUATION = $37
#ROLE_SYSTEM_BUTTONDROPDOWN = $38
#ROLE_SYSTEM_BUTTONMENU = $39
#ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3a
#ROLE_SYSTEM_WHITESPACE = $3b
#ROLE_SYSTEM_PAGETABLIST = $3c
#ROLE_SYSTEM_CLOCK = $3d
#ROLE_SYSTEM_SPLITBUTTON = $3e
#ROLE_SYSTEM_IPADDRESS = $3f
#ROLE_SYSTEM_OUTLINEBUTTON = $40

DataSection
  ; DEFINE_GUID(CLSID_AccPropServices, 0xb5f8350b, 0x0548, 0x48b1, 0xa6, 0xee, 0x88, 0xbd, 0x00, 0xb4, 0xa5, 0xe7);
  CLSID_AccPropServices:
  Data.l $b5f8350b
  Data.w $0548, $48b1
  Data.b $a6, $ee, $88, $bd, $00, $b4, $a5, $e7
  
  ; DEFINE_GUID(IID_IAccPropServices, 0x6e26e776, 0x04f0, 0x495d, 0x80, 0xe4, 0x33, 0x30, 0x35, 0x2e, 0x31, 0x69);
  IID_IAccPropServices:
  Data.l $6e26e776
  Data.w $04f0, $495d
  Data.b $80, $e4, $33, $30, $35, $2e, $31, $69
  
  ; DEFINE_GUID(PROPID_ACC_ROLE, 0xcb905ff2, 0x7bd1, 0x4c05, 0xb3, 0xc8, 0xe6, 0xc2, 0x41, 0x36, 0x4d, 0x70);
  PROPID_ACC_ROLE:
  Data.l $cb905ff2
  Data.w $7bd1, $4c05
  Data.b $b3, $c8, $e6, $c2, $41, $36, $4d, $70
EndDataSection


; https://learn.microsoft.com/en-us/windows/win32/winauto/using-direct-annotation
Procedure SetAccessibleProperties(Gadget)
  Protected pAccPropServices.IAccPropServices
  Protected var.VARIANT
  Protected hr.l, hwnd, ItemCount, i
  
  If GadgetType(Gadget) = #PB_GadgetType_ListView
    ItemCount = CountGadgetItems(Gadget)
    hwnd = GadgetID(Gadget)
    If ItemCount > 0
      hr = CoCreateInstance_(?CLSID_AccPropServices, 0, #CLSCTX_INPROC_SERVER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER, ?IID_IAccPropServices, @pAccPropServices)
      If hr = #S_OK And pAccPropServices
        var\vt = #VT_I4
        var\lVal = #ROLE_SYSTEM_CHECKBUTTON
        
        For i = 1 To ItemCount
          hr = pAccPropServices\SetHwndProp(hwnd, #OBJID_CLIENT, i, ?PROPID_ACC_ROLE, var)
          If hr <> #S_OK
            Debug "Error: item " + i
          EndIf
        Next
        pAccPropServices\Release()
      EndIf
    EndIf
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListViewGadget(0, 10, 10, 250, 120, #PB_ListView_ClickSelect)
  For a = 1 To 12
    AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview")
  Next
  
  SetAccessibleProperties(0)
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: how do I set the acc_role of a ListViewGadget's items?

Post by breeze4me »

Quin wrote: Wed Mar 13, 2024 7:38 pm Wow, thank you so much! This works amazingly! The only thing I need to do now is make the states report properly. Currently they always say unchecked, and selected/not selected is reported when I hit space. Where are the Microsoft docs for these interfaces?
You can do this in a similar way.
I don't know much about the accessibility, but you might need to call the NotifyWinEvent function.
https://learn.microsoft.com/en-us/windo ... fywinevent
https://learn.microsoft.com/en-us/windo ... -constants

Code: Select all

; /* System object Id's */
#OBJID_WINDOW            = 0
#OBJID_SYSMENU           = -1
#OBJID_TITLEBAR          = -2
#OBJID_MENU              = -3
#OBJID_CLIENT            = -4
#OBJID_VSCROLL           = -5
#OBJID_HSCROLL           = -6
#OBJID_SIZEGRIP          = -7
#OBJID_CARET             = -8
#OBJID_CURSOR            = -9
#OBJID_ALERT             = -10
#OBJID_SOUND             = -11
#OBJID_QUERYCLASSNAMEIDX = -12
#OBJID_NATIVEOM          = -16

; https://learn.microsoft.com/en-us/windows/win32/winauto/object-state-constants
#STATE_SYSTEM_NORMAL = 0
#STATE_SYSTEM_UNAVAILABLE = $1
#STATE_SYSTEM_SELECTED = $2
#STATE_SYSTEM_FOCUSED = $4
#STATE_SYSTEM_PRESSED = $8
#STATE_SYSTEM_CHECKED = $10
#STATE_SYSTEM_MIXED = $20
#STATE_SYSTEM_INDETERMINATE = #STATE_SYSTEM_MIXED
#STATE_SYSTEM_READONLY = $40
#STATE_SYSTEM_HOTTRACKED = $80
#STATE_SYSTEM_DEFAULT = $100
#STATE_SYSTEM_EXPANDED = $200
#STATE_SYSTEM_COLLAPSED = $400
#STATE_SYSTEM_BUSY = $800
#STATE_SYSTEM_FLOATING = $1000
#STATE_SYSTEM_MARQUEED = $2000
#STATE_SYSTEM_ANIMATED = $4000
#STATE_SYSTEM_INVISIBLE = $8000
#STATE_SYSTEM_OFFSCREEN = $10000
#STATE_SYSTEM_SIZEABLE = $20000
#STATE_SYSTEM_MOVEABLE = $40000
#STATE_SYSTEM_SELFVOICING = $80000
#STATE_SYSTEM_FOCUSABLE = $100000
#STATE_SYSTEM_SELECTABLE = $200000
#STATE_SYSTEM_LINKED = $400000
#STATE_SYSTEM_TRAVERSED = $800000
#STATE_SYSTEM_MULTISELECTABLE = $1000000
#STATE_SYSTEM_EXTSELECTABLE = $2000000
#STATE_SYSTEM_ALERT_LOW = $4000000
#STATE_SYSTEM_ALERT_MEDIUM = $8000000
#STATE_SYSTEM_ALERT_HIGH = $10000000
#STATE_SYSTEM_PROTECTED = $20000000
#STATE_SYSTEM_VALID = $7fffffff

#ROLE_SYSTEM_TITLEBAR = $1
#ROLE_SYSTEM_MENUBAR = $2
#ROLE_SYSTEM_SCROLLBAR = $3
#ROLE_SYSTEM_GRIP = $4
#ROLE_SYSTEM_SOUND = $5
#ROLE_SYSTEM_CURSOR = $6
#ROLE_SYSTEM_CARET = $7
#ROLE_SYSTEM_ALERT = $8
#ROLE_SYSTEM_WINDOW = $9
#ROLE_SYSTEM_CLIENT = $a
#ROLE_SYSTEM_MENUPOPUP = $b
#ROLE_SYSTEM_MENUITEM = $c
#ROLE_SYSTEM_TOOLTIP = $d
#ROLE_SYSTEM_APPLICATION = $e
#ROLE_SYSTEM_DOCUMENT = $f
#ROLE_SYSTEM_PANE = $10
#ROLE_SYSTEM_CHART = $11
#ROLE_SYSTEM_DIALOG = $12
#ROLE_SYSTEM_BORDER = $13
#ROLE_SYSTEM_GROUPING = $14
#ROLE_SYSTEM_SEPARATOR = $15
#ROLE_SYSTEM_TOOLBAR = $16
#ROLE_SYSTEM_STATUSBAR = $17
#ROLE_SYSTEM_TABLE = $18
#ROLE_SYSTEM_COLUMNHEADER = $19
#ROLE_SYSTEM_ROWHEADER = $1a
#ROLE_SYSTEM_COLUMN = $1b
#ROLE_SYSTEM_ROW = $1c
#ROLE_SYSTEM_CELL = $1d
#ROLE_SYSTEM_LINK = $1e
#ROLE_SYSTEM_HELPBALLOON = $1f
#ROLE_SYSTEM_CHARACTER = $20
#ROLE_SYSTEM_LIST = $21
#ROLE_SYSTEM_LISTITEM = $22
#ROLE_SYSTEM_OUTLINE = $23
#ROLE_SYSTEM_OUTLINEITEM = $24
#ROLE_SYSTEM_PAGETAB = $25
#ROLE_SYSTEM_PROPERTYPAGE = $26
#ROLE_SYSTEM_INDICATOR = $27
#ROLE_SYSTEM_GRAPHIC = $28
#ROLE_SYSTEM_STATICTEXT = $29
#ROLE_SYSTEM_TEXT = $2a
#ROLE_SYSTEM_PUSHBUTTON = $2b
#ROLE_SYSTEM_CHECKBUTTON = $2c
#ROLE_SYSTEM_RADIOBUTTON = $2d
#ROLE_SYSTEM_COMBOBOX = $2e
#ROLE_SYSTEM_DROPLIST = $2f
#ROLE_SYSTEM_PROGRESSBAR = $30
#ROLE_SYSTEM_DIAL = $31
#ROLE_SYSTEM_HOTKEYFIELD = $32
#ROLE_SYSTEM_SLIDER = $33
#ROLE_SYSTEM_SPINBUTTON = $34
#ROLE_SYSTEM_DIAGRAM = $35
#ROLE_SYSTEM_ANIMATION = $36
#ROLE_SYSTEM_EQUATION = $37
#ROLE_SYSTEM_BUTTONDROPDOWN = $38
#ROLE_SYSTEM_BUTTONMENU = $39
#ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3a
#ROLE_SYSTEM_WHITESPACE = $3b
#ROLE_SYSTEM_PAGETABLIST = $3c
#ROLE_SYSTEM_CLOCK = $3d
#ROLE_SYSTEM_SPLITBUTTON = $3e
#ROLE_SYSTEM_IPADDRESS = $3f
#ROLE_SYSTEM_OUTLINEBUTTON = $40

DataSection
  ; DEFINE_GUID(CLSID_AccPropServices, 0xb5f8350b, 0x0548, 0x48b1, 0xa6, 0xee, 0x88, 0xbd, 0x00, 0xb4, 0xa5, 0xe7);
  CLSID_AccPropServices:
  Data.l $b5f8350b
  Data.w $0548, $48b1
  Data.b $a6, $ee, $88, $bd, $00, $b4, $a5, $e7
  
  ; DEFINE_GUID(IID_IAccPropServices, 0x6e26e776, 0x04f0, 0x495d, 0x80, 0xe4, 0x33, 0x30, 0x35, 0x2e, 0x31, 0x69);
  IID_IAccPropServices:
  Data.l $6e26e776
  Data.w $04f0, $495d
  Data.b $80, $e4, $33, $30, $35, $2e, $31, $69
  
  ; DEFINE_GUID(PROPID_ACC_ROLE, 0xcb905ff2, 0x7bd1, 0x4c05, 0xb3, 0xc8, 0xe6, 0xc2, 0x41, 0x36, 0x4d, 0x70);
  PROPID_ACC_ROLE:
  Data.l $cb905ff2
  Data.w $7bd1, $4c05
  Data.b $b3, $c8, $e6, $c2, $41, $36, $4d, $70
  
  ; DEFINE_GUID(PROPID_ACC_STATE, 0xa8d4d5b0, 0x0a21, 0x42d0, 0xa5, 0xc0, 0x51, 0x4e, 0x98, 0x4f, 0x45, 0x7b);
  PROPID_ACC_STATE:
  Data.l $a8d4d5b0
  Data.w $0a21, $42d0
  Data.b $a5, $c0, $51, $4e, $98, $4f, $45, $7b
  
EndDataSection


; https://learn.microsoft.com/en-us/windows/win32/winauto/using-direct-annotation
Procedure SetAccessibleProperties(Gadget)
  Protected pAccPropServices.IAccPropServices
  Protected var.VARIANT
  Protected hr.l, hwnd, ItemCount, i
  
  If GadgetType(Gadget) = #PB_GadgetType_ListView
    ItemCount = CountGadgetItems(Gadget)
    hwnd = GadgetID(Gadget)
    If ItemCount > 0
      hr = CoCreateInstance_(?CLSID_AccPropServices, 0, #CLSCTX_INPROC_SERVER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER, ?IID_IAccPropServices, @pAccPropServices)
      If hr = #S_OK And pAccPropServices
        var\vt = #VT_I4
        var\lVal = #ROLE_SYSTEM_CHECKBUTTON
        
        For i = 1 To ItemCount
          hr = pAccPropServices\SetHwndProp(hwnd, #OBJID_CLIENT, i, ?PROPID_ACC_ROLE, var)
          If hr <> #S_OK
            Debug "Error: item " + i
          EndIf
        Next
        pAccPropServices\Release()
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure SetAccessibleCheckState(Gadget)
  Protected pAccPropServices.IAccPropServices
  Protected var.VARIANT
  Protected hr.l, hwnd, ItemCount, i, State
  
  If GadgetType(Gadget) = #PB_GadgetType_ListView
    ItemCount = CountGadgetItems(Gadget)
    hwnd = GadgetID(Gadget)
    If ItemCount > 0
      hr = CoCreateInstance_(?CLSID_AccPropServices, 0, #CLSCTX_INPROC_SERVER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER, ?IID_IAccPropServices, @pAccPropServices)
      If hr = #S_OK And pAccPropServices
        
        var\vt = #VT_I4
        
        For i = 1 To ItemCount
          State = GetGadgetItemState(Gadget, i - 1)
          If State
            State = #STATE_SYSTEM_MULTISELECTABLE | #STATE_SYSTEM_FOCUSABLE | #STATE_SYSTEM_CHECKED ;| #STATE_SYSTEM_SELECTABLE
          Else
            State = #STATE_SYSTEM_MULTISELECTABLE | #STATE_SYSTEM_FOCUSABLE ;| #STATE_SYSTEM_SELECTABLE
          EndIf
          
          var\lVal = State
          
          hr = pAccPropServices\SetHwndProp(hwnd, #OBJID_CLIENT, i, ?PROPID_ACC_STATE, var)
          If hr <> #S_OK
            Debug "Error: item " + i
          EndIf
        Next
        
        pAccPropServices\Release()
      EndIf
    EndIf
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListViewGadget(0, 10, 10, 250, 120, #PB_ListView_ClickSelect)
  For a = 1 To 12
    AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview")
  Next
  
  SetAccessibleProperties(0)
  
  Repeat
    e = WaitWindowEvent()
    
    If e = #PB_Event_Gadget And EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
      SetAccessibleCheckState(0)
    EndIf
    
  Until e = #PB_Event_CloseWindow
EndIf
Quin
Addict
Addict
Posts: 1135
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: how do I set the acc_role of a ListViewGadget's items?

Post by Quin »

Thanks, breeze4me! This does exactly what I want! :)
breeze4me wrote: Thu Mar 14, 2024 9:22 am
Quin wrote: Wed Mar 13, 2024 7:38 pm Wow, thank you so much! This works amazingly! The only thing I need to do now is make the states report properly. Currently they always say unchecked, and selected/not selected is reported when I hit space. Where are the Microsoft docs for these interfaces?
You can do this in a similar way.
I don't know much about the accessibility, but you might need to call the NotifyWinEvent function.
https://learn.microsoft.com/en-us/windo ... fywinevent
https://learn.microsoft.com/en-us/windo ... -constants

Code: Select all

; /* System object Id's */
#OBJID_WINDOW            = 0
#OBJID_SYSMENU           = -1
#OBJID_TITLEBAR          = -2
#OBJID_MENU              = -3
#OBJID_CLIENT            = -4
#OBJID_VSCROLL           = -5
#OBJID_HSCROLL           = -6
#OBJID_SIZEGRIP          = -7
#OBJID_CARET             = -8
#OBJID_CURSOR            = -9
#OBJID_ALERT             = -10
#OBJID_SOUND             = -11
#OBJID_QUERYCLASSNAMEIDX = -12
#OBJID_NATIVEOM          = -16

; https://learn.microsoft.com/en-us/windows/win32/winauto/object-state-constants
#STATE_SYSTEM_NORMAL = 0
#STATE_SYSTEM_UNAVAILABLE = $1
#STATE_SYSTEM_SELECTED = $2
#STATE_SYSTEM_FOCUSED = $4
#STATE_SYSTEM_PRESSED = $8
#STATE_SYSTEM_CHECKED = $10
#STATE_SYSTEM_MIXED = $20
#STATE_SYSTEM_INDETERMINATE = #STATE_SYSTEM_MIXED
#STATE_SYSTEM_READONLY = $40
#STATE_SYSTEM_HOTTRACKED = $80
#STATE_SYSTEM_DEFAULT = $100
#STATE_SYSTEM_EXPANDED = $200
#STATE_SYSTEM_COLLAPSED = $400
#STATE_SYSTEM_BUSY = $800
#STATE_SYSTEM_FLOATING = $1000
#STATE_SYSTEM_MARQUEED = $2000
#STATE_SYSTEM_ANIMATED = $4000
#STATE_SYSTEM_INVISIBLE = $8000
#STATE_SYSTEM_OFFSCREEN = $10000
#STATE_SYSTEM_SIZEABLE = $20000
#STATE_SYSTEM_MOVEABLE = $40000
#STATE_SYSTEM_SELFVOICING = $80000
#STATE_SYSTEM_FOCUSABLE = $100000
#STATE_SYSTEM_SELECTABLE = $200000
#STATE_SYSTEM_LINKED = $400000
#STATE_SYSTEM_TRAVERSED = $800000
#STATE_SYSTEM_MULTISELECTABLE = $1000000
#STATE_SYSTEM_EXTSELECTABLE = $2000000
#STATE_SYSTEM_ALERT_LOW = $4000000
#STATE_SYSTEM_ALERT_MEDIUM = $8000000
#STATE_SYSTEM_ALERT_HIGH = $10000000
#STATE_SYSTEM_PROTECTED = $20000000
#STATE_SYSTEM_VALID = $7fffffff

#ROLE_SYSTEM_TITLEBAR = $1
#ROLE_SYSTEM_MENUBAR = $2
#ROLE_SYSTEM_SCROLLBAR = $3
#ROLE_SYSTEM_GRIP = $4
#ROLE_SYSTEM_SOUND = $5
#ROLE_SYSTEM_CURSOR = $6
#ROLE_SYSTEM_CARET = $7
#ROLE_SYSTEM_ALERT = $8
#ROLE_SYSTEM_WINDOW = $9
#ROLE_SYSTEM_CLIENT = $a
#ROLE_SYSTEM_MENUPOPUP = $b
#ROLE_SYSTEM_MENUITEM = $c
#ROLE_SYSTEM_TOOLTIP = $d
#ROLE_SYSTEM_APPLICATION = $e
#ROLE_SYSTEM_DOCUMENT = $f
#ROLE_SYSTEM_PANE = $10
#ROLE_SYSTEM_CHART = $11
#ROLE_SYSTEM_DIALOG = $12
#ROLE_SYSTEM_BORDER = $13
#ROLE_SYSTEM_GROUPING = $14
#ROLE_SYSTEM_SEPARATOR = $15
#ROLE_SYSTEM_TOOLBAR = $16
#ROLE_SYSTEM_STATUSBAR = $17
#ROLE_SYSTEM_TABLE = $18
#ROLE_SYSTEM_COLUMNHEADER = $19
#ROLE_SYSTEM_ROWHEADER = $1a
#ROLE_SYSTEM_COLUMN = $1b
#ROLE_SYSTEM_ROW = $1c
#ROLE_SYSTEM_CELL = $1d
#ROLE_SYSTEM_LINK = $1e
#ROLE_SYSTEM_HELPBALLOON = $1f
#ROLE_SYSTEM_CHARACTER = $20
#ROLE_SYSTEM_LIST = $21
#ROLE_SYSTEM_LISTITEM = $22
#ROLE_SYSTEM_OUTLINE = $23
#ROLE_SYSTEM_OUTLINEITEM = $24
#ROLE_SYSTEM_PAGETAB = $25
#ROLE_SYSTEM_PROPERTYPAGE = $26
#ROLE_SYSTEM_INDICATOR = $27
#ROLE_SYSTEM_GRAPHIC = $28
#ROLE_SYSTEM_STATICTEXT = $29
#ROLE_SYSTEM_TEXT = $2a
#ROLE_SYSTEM_PUSHBUTTON = $2b
#ROLE_SYSTEM_CHECKBUTTON = $2c
#ROLE_SYSTEM_RADIOBUTTON = $2d
#ROLE_SYSTEM_COMBOBOX = $2e
#ROLE_SYSTEM_DROPLIST = $2f
#ROLE_SYSTEM_PROGRESSBAR = $30
#ROLE_SYSTEM_DIAL = $31
#ROLE_SYSTEM_HOTKEYFIELD = $32
#ROLE_SYSTEM_SLIDER = $33
#ROLE_SYSTEM_SPINBUTTON = $34
#ROLE_SYSTEM_DIAGRAM = $35
#ROLE_SYSTEM_ANIMATION = $36
#ROLE_SYSTEM_EQUATION = $37
#ROLE_SYSTEM_BUTTONDROPDOWN = $38
#ROLE_SYSTEM_BUTTONMENU = $39
#ROLE_SYSTEM_BUTTONDROPDOWNGRID = $3a
#ROLE_SYSTEM_WHITESPACE = $3b
#ROLE_SYSTEM_PAGETABLIST = $3c
#ROLE_SYSTEM_CLOCK = $3d
#ROLE_SYSTEM_SPLITBUTTON = $3e
#ROLE_SYSTEM_IPADDRESS = $3f
#ROLE_SYSTEM_OUTLINEBUTTON = $40

DataSection
  ; DEFINE_GUID(CLSID_AccPropServices, 0xb5f8350b, 0x0548, 0x48b1, 0xa6, 0xee, 0x88, 0xbd, 0x00, 0xb4, 0xa5, 0xe7);
  CLSID_AccPropServices:
  Data.l $b5f8350b
  Data.w $0548, $48b1
  Data.b $a6, $ee, $88, $bd, $00, $b4, $a5, $e7
  
  ; DEFINE_GUID(IID_IAccPropServices, 0x6e26e776, 0x04f0, 0x495d, 0x80, 0xe4, 0x33, 0x30, 0x35, 0x2e, 0x31, 0x69);
  IID_IAccPropServices:
  Data.l $6e26e776
  Data.w $04f0, $495d
  Data.b $80, $e4, $33, $30, $35, $2e, $31, $69
  
  ; DEFINE_GUID(PROPID_ACC_ROLE, 0xcb905ff2, 0x7bd1, 0x4c05, 0xb3, 0xc8, 0xe6, 0xc2, 0x41, 0x36, 0x4d, 0x70);
  PROPID_ACC_ROLE:
  Data.l $cb905ff2
  Data.w $7bd1, $4c05
  Data.b $b3, $c8, $e6, $c2, $41, $36, $4d, $70
  
  ; DEFINE_GUID(PROPID_ACC_STATE, 0xa8d4d5b0, 0x0a21, 0x42d0, 0xa5, 0xc0, 0x51, 0x4e, 0x98, 0x4f, 0x45, 0x7b);
  PROPID_ACC_STATE:
  Data.l $a8d4d5b0
  Data.w $0a21, $42d0
  Data.b $a5, $c0, $51, $4e, $98, $4f, $45, $7b
  
EndDataSection


; https://learn.microsoft.com/en-us/windows/win32/winauto/using-direct-annotation
Procedure SetAccessibleProperties(Gadget)
  Protected pAccPropServices.IAccPropServices
  Protected var.VARIANT
  Protected hr.l, hwnd, ItemCount, i
  
  If GadgetType(Gadget) = #PB_GadgetType_ListView
    ItemCount = CountGadgetItems(Gadget)
    hwnd = GadgetID(Gadget)
    If ItemCount > 0
      hr = CoCreateInstance_(?CLSID_AccPropServices, 0, #CLSCTX_INPROC_SERVER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER, ?IID_IAccPropServices, @pAccPropServices)
      If hr = #S_OK And pAccPropServices
        var\vt = #VT_I4
        var\lVal = #ROLE_SYSTEM_CHECKBUTTON
        
        For i = 1 To ItemCount
          hr = pAccPropServices\SetHwndProp(hwnd, #OBJID_CLIENT, i, ?PROPID_ACC_ROLE, var)
          If hr <> #S_OK
            Debug "Error: item " + i
          EndIf
        Next
        pAccPropServices\Release()
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure SetAccessibleCheckState(Gadget)
  Protected pAccPropServices.IAccPropServices
  Protected var.VARIANT
  Protected hr.l, hwnd, ItemCount, i, State
  
  If GadgetType(Gadget) = #PB_GadgetType_ListView
    ItemCount = CountGadgetItems(Gadget)
    hwnd = GadgetID(Gadget)
    If ItemCount > 0
      hr = CoCreateInstance_(?CLSID_AccPropServices, 0, #CLSCTX_INPROC_SERVER | #CLSCTX_LOCAL_SERVER | #CLSCTX_REMOTE_SERVER, ?IID_IAccPropServices, @pAccPropServices)
      If hr = #S_OK And pAccPropServices
        
        var\vt = #VT_I4
        
        For i = 1 To ItemCount
          State = GetGadgetItemState(Gadget, i - 1)
          If State
            State = #STATE_SYSTEM_MULTISELECTABLE | #STATE_SYSTEM_FOCUSABLE | #STATE_SYSTEM_CHECKED ;| #STATE_SYSTEM_SELECTABLE
          Else
            State = #STATE_SYSTEM_MULTISELECTABLE | #STATE_SYSTEM_FOCUSABLE ;| #STATE_SYSTEM_SELECTABLE
          EndIf
          
          var\lVal = State
          
          hr = pAccPropServices\SetHwndProp(hwnd, #OBJID_CLIENT, i, ?PROPID_ACC_STATE, var)
          If hr <> #S_OK
            Debug "Error: item " + i
          EndIf
        Next
        
        pAccPropServices\Release()
      EndIf
    EndIf
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListViewGadget(0, 10, 10, 250, 120, #PB_ListView_ClickSelect)
  For a = 1 To 12
    AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview")
  Next
  
  SetAccessibleProperties(0)
  
  Repeat
    e = WaitWindowEvent()
    
    If e = #PB_Event_Gadget And EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
      SetAccessibleCheckState(0)
    EndIf
    
  Until e = #PB_Event_CloseWindow
EndIf
Post Reply