Package NVDAObjects :: Package IAccessible :: Module sysListView32
[hide private]
[frames] | no frames]

Source Code for Module NVDAObjects.IAccessible.sysListView32

  1  #NVDAObjects/sysListView32.py 
  2  #A part of NonVisual Desktop Access (NVDA) 
  3  #Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/> 
  4  #This file is covered by the GNU General Public License. 
  5  #See the file COPYING for more details. 
  6   
  7  import time 
  8  from ctypes import * 
  9  from ctypes.wintypes import * 
 10  import oleacc 
 11  import controlTypes 
 12  import speech 
 13  import api 
 14  import eventHandler 
 15  import winKernel 
 16  import winUser 
 17  from . import IAccessible, List 
 18  from ..window import Window  
 19  import watchdog 
 20   
 21  #Window messages 
 22  LVM_FIRST=0x1000 
 23  LVM_GETITEMSTATE=LVM_FIRST+44 
 24  LVM_GETFOCUSEDGROUP=LVM_FIRST+93 
 25  LVM_GETGROUPINFOBYINDEX=LVM_FIRST+153 
 26  LVM_GETITEMCOUNT=LVM_FIRST+4 
 27  LVM_GETITEM=LVM_FIRST+75 
 28  LVN_GETDISPINFO=0xFFFFFF4F 
 29   
 30  #item mask flags 
 31  LVIF_TEXT=0x01  
 32  LVIF_IMAGE=0x02 
 33  LVIF_PARAM=0x04 
 34  LVIF_STATE=0x08 
 35  LVIF_INDENT=0x10 
 36  LVIF_GROUPID=0x100 
 37  LVIF_COLUMNS=0x200 
 38   
 39  #group mask flags 
 40  LVGF_HEADER=0x1 
 41  LVGF_FOOTER=0x2 
 42  LVGF_STATE=0x4 
 43  LVGF_ALIGN=0x8 
 44  LVGF_GROUPID=0x10 
 45   
 46  #Item states 
 47  LVIS_FOCUSED=0x01 
 48  LVIS_SELECTED=0x02 
 49  LVIS_STATEIMAGEMASK=0xF000 
 50   
 51  LVS_OWNERDRAWFIXED=0x0400 
 52   
53 -class LVGROUP(Structure):
54 _fields_=[ 55 ('cbSize',c_uint), 56 ('mask',c_uint), 57 ('pszHeader',c_void_p), 58 ('cchHeader',c_int), 59 ('pszFooter',c_void_p), 60 ('cchFooter',c_int), 61 ('iGroupId',c_int), 62 ('stateMask',c_uint), 63 ('state',c_uint), 64 ('uAlign',c_uint), 65 ('pszSubtitle',c_void_p), 66 ('cchSubtitle',c_uint), 67 ('pszTask',c_void_p), 68 ('cchTask',c_uint), 69 ('pszDescriptionTop',c_void_p), 70 ('cchDescriptionTop',c_uint), 71 ('pszDescriptionBottom',c_void_p), 72 ('cchDescriptionBottom',c_uint), 73 ('iTitleImage',c_int), 74 ('iExtendedImage',c_int), 75 ('iFirstItem',c_int), 76 ('cItems',c_uint), 77 ('pszSubsetTitle',c_void_p), 78 ('cchSubsetTitle',c_uint), 79 ]
80
81 -class LVItemStruct(Structure):
82 _fields_=[ 83 ('mask',c_uint), 84 ('iItem',c_int), 85 ('iSubItem',c_int), 86 ('state',c_uint), 87 ('stateMask',c_uint), 88 ('text',LPWSTR), 89 ('cchTextMax',c_int), 90 ('iImage',c_int), 91 ('lParam',LPARAM), 92 ('iIndent',c_int), 93 ('iGroupID',c_int), 94 ('cColumns',c_uint), 95 ('puColumns',c_uint), 96 ('piColFmt',POINTER(c_int)), 97 ('iGroup',c_int), 98 ]
99
100 -class NMLVDispInfoStruct(Structure):
101 _fields_=[ 102 ('hdr',winUser.NMHdrStruct), 103 ('item',c_int), 104 ]
105
106 -def getListGroupInfo(windowHandle,groupIndex):
107 processHandle=oleacc.GetProcessHandleFromHwnd(windowHandle) 108 if not processHandle: 109 return None 110 localInfo=LVGROUP() 111 localInfo.cbSize=sizeof(LVGROUP) 112 localInfo.mask=LVGF_HEADER|LVGF_FOOTER|LVGF_STATE|LVGF_ALIGN|LVGF_GROUPID 113 localInfo.stateMask=0xffffffff 114 remoteInfo=winKernel.virtualAllocEx(processHandle,None,sizeof(LVGROUP),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) 115 try: 116 winKernel.writeProcessMemory(processHandle,remoteInfo,byref(localInfo),sizeof(LVGROUP),None) 117 messageRes=watchdog.cancellableSendMessage(windowHandle,LVM_GETGROUPINFOBYINDEX,groupIndex,remoteInfo) 118 winKernel.readProcessMemory(processHandle,remoteInfo,byref(localInfo),sizeof(LVGROUP),None) 119 finally: 120 winKernel.virtualFreeEx(processHandle,remoteInfo,0,winKernel.MEM_RELEASE) 121 localHeader=create_unicode_buffer(localInfo.cchHeader) 122 winKernel.readProcessMemory(processHandle,localInfo.pszHeader,localHeader,localInfo.cchHeader*2,None) 123 localFooter=create_unicode_buffer(localInfo.cchFooter) 124 winKernel.readProcessMemory(processHandle,localInfo.pszFooter,localFooter,localInfo.cchFooter*2,None) 125 winKernel.closeHandle(processHandle) 126 if messageRes==1: 127 return dict(header=localHeader.value,footer=localFooter.value,groupID=localInfo.iGroupId,state=localInfo.state,uAlign=localInfo.uAlign,groupIndex=groupIndex) 128 else: 129 return None
130
131 -class List(List):
132
133 - def _get_name(self):
134 name=super(List,self)._get_name() 135 if not name: 136 name=super(IAccessible,self)._get_name() 137 return name
138
139 - def event_gainFocus(self):
140 #See if this object is the focus and the focus is on a group item. 141 #if so, then morph this object to a groupingItem object 142 if self is api.getFocusObject(): 143 groupIndex=watchdog.cancellableSendMessage(self.windowHandle,LVM_GETFOCUSEDGROUP,0,0) 144 if groupIndex>=0: 145 info=getListGroupInfo(self.windowHandle,groupIndex) 146 if info is not None: 147 ancestors=api.getFocusAncestors() 148 if api.getFocusDifferenceLevel()==len(ancestors)-1: 149 self.event_focusEntered() 150 groupingObj=GroupingItem(windowHandle=self.windowHandle,parentNVDAObject=self,groupInfo=info) 151 return eventHandler.queueEvent("gainFocus",groupingObj) 152 return super(List,self).event_gainFocus()
153
154 -class GroupingItem(Window):
155
156 - def __init__(self,windowHandle=None,parentNVDAObject=None,groupInfo=None):
157 super(GroupingItem,self).__init__(windowHandle=windowHandle) 158 self.parent=parentNVDAObject 159 self.groupInfo=groupInfo
160
161 - def _isEqual(self,other):
162 return isinstance(other,self.__class__) and self.groupInfo==other.groupInfo
163
164 - def _set_groupInfo(self,info):
165 self._groupInfoTime=time.time() 166 self._groupInfo=info
167
168 - def _get_groupInfo(self):
169 now=time.time() 170 if (now-self._groupInfoTime)>0.25: 171 self._groupInfoTime=now 172 self._groupInfo=getListGroupInfo(self.windowHandle,self._groupInfo['groupIndex']) 173 return self._groupInfo
174
175 - def _get_name(self):
176 return self.groupInfo['header']
177
178 - def _get_role(self):
180
181 - def _get_value(self):
182 return self.groupInfo['footer']
183
184 - def _get_states(self):
185 states=set() 186 if self.groupInfo['state']&1: 187 states.add(controlTypes.STATE_COLLAPSED) 188 else: 189 states.add(controlTypes.STATE_EXPANDED) 190 return states
191
192 - def script_collapseOrExpand(self,gesture):
193 gesture.send() 194 self.event_stateChange()
195
196 - def initOverlayClass(self):
197 for gesture in ("kb:leftArrow", "kb:rightArrow"): 198 self.bindGesture(gesture, "collapseOrExpand")
199
200 -class ListItem(IAccessible):
201
202 - def _get_lvAppImageID(self):
203 item=LVItemStruct(iItem=self.IAccessibleChildID-1,mask=LVIF_IMAGE) 204 processHandle=self.processHandle 205 internalItem=winKernel.virtualAllocEx(processHandle,None,sizeof(LVItemStruct),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) 206 try: 207 winKernel.writeProcessMemory(processHandle,internalItem,byref(item),sizeof(LVItemStruct),None) 208 watchdog.cancellableSendMessage(self.windowHandle,LVM_GETITEM,0,internalItem) 209 dispInfo=NMLVDispInfoStruct() 210 dispInfo.item=internalItem 211 dispInfo.hdr.hwndFrom=self.windowHandle 212 dispInfo.hdr.idFrom=self.windowControlID 213 dispInfo.hdr.code=LVN_GETDISPINFO 214 internalDispInfo=winKernel.virtualAllocEx(processHandle,None,sizeof(NMLVDispInfoStruct),winKernel.MEM_COMMIT,winKernel.PAGE_READWRITE) 215 try: 216 winKernel.writeProcessMemory(processHandle,internalDispInfo,byref(dispInfo),sizeof(NMLVDispInfoStruct),None) 217 watchdog.cancellableSendMessage(self.parent.parent.windowHandle,winUser.WM_NOTIFY,LVN_GETDISPINFO,internalDispInfo) 218 finally: 219 winKernel.virtualFreeEx(processHandle,internalDispInfo,0,winKernel.MEM_RELEASE) 220 winKernel.readProcessMemory(processHandle,internalItem,byref(item),sizeof(LVItemStruct),None) 221 finally: 222 winKernel.virtualFreeEx(processHandle,internalItem,0,winKernel.MEM_RELEASE) 223 return item.iImage
224
225 - def _get_description(self):
226 return None
227
228 - def _get_value(self):
229 value=super(ListItem,self)._get_description() 230 if (not value or value.isspace()) and self.windowStyle & LVS_OWNERDRAWFIXED: 231 value=self.displayText 232 if not value: 233 return None 234 #Some list view items in Vista can contain annoying left-to-right and right-to-left indicator characters which really should not be there. 235 value=value.replace(u'\u200E','') 236 value=value.replace(u'\u200F','') 237 return value
238
239 - def _get_positionInfo(self):
240 index=self.IAccessibleChildID 241 totalCount=watchdog.cancellableSendMessage(self.windowHandle,LVM_GETITEMCOUNT,0,0) 242 return dict(indexInGroup=index,similarItemsInGroup=totalCount)
243
244 - def event_stateChange(self):
245 if self.hasFocus: 246 super(ListItem,self).event_stateChange()
247