Problema ao obter o conteúdo de uma caixa de listagem com Python e Ctypes no Win32
Pergunta
Eu gostaria de obter o conteúdo de uma caixa de listagem graças ao Python e Ctypes.
item_count = ctypes.windll.user32.SendMessageA(hwnd, win32con.LB_GETCOUNT, 0, 0)
items = []
for i in xrange(item_count):
text_len = ctypes.windll.user32.SendMessageA(hwnd, win32con.LB_GETTEXTLEN, i, 0)
buffer = ctypes.create_string_buffer("", text_len+1)
ctypes.windll.user32.SendMessageA(hwnd, win32con.LB_GETTEXT, i, buffer)
items.append(buffer.value)
print items
O número de itens está correto, mas o texto está errado. Todos os text_len são 4 e os valores de texto são algo como '0 xd9 xee x02 x90'
Eu tentei usar um buffer Unicode com um resultado semelhante.
Eu não encontro meu erro. Qualquer ideia?
Solução
Se a caixa de listagem em questão for desenhada, esta passagem do Lb_getText A documentação pode ser relevante:
Se você criar a caixa de listagem com um estilo proprietário, mas sem o estilo lbs_hasstrings, o buffer apontado pelo parâmetro LPARAM receberá o valor associado ao item (os dados do item).
Os quatro bytes que você recebeu certamente parecem ser um ponteiro, o que é um valor típico para armazenar nos dados por item.
Outras dicas
Parece que você precisa usar uma estrutura embalada para o resultado. Encontrei um exemplo online, talvez isso o ajude:
http://www.brunningonline.net/simon/blog/archives/winguiauto.py.html
# Programmer : Simon Brunning - simon@brunningonline.net
# Date : 25 June 2003
def _getMultipleWindowValues(hwnd, getCountMessage, getValueMessage):
'''A common pattern in the Win32 API is that in order to retrieve a
series of values, you use one message to get a count of available
items, and another to retrieve them. This internal utility function
performs the common processing for this pattern.
Arguments:
hwnd Window handle for the window for which items should be
retrieved.
getCountMessage Item count message.
getValueMessage Value retrieval message.
Returns: Retrieved items.'''
result = []
VALUE_LENGTH = 256
bufferlength_int = struct.pack('i', VALUE_LENGTH) # This is a C style int.
valuecount = win32gui.SendMessage(hwnd, getCountMessage, 0, 0)
for itemIndex in range(valuecount):
valuebuffer = array.array('c',
bufferlength_int +
" " * (VALUE_LENGTH - len(bufferlength_int)))
valueLength = win32gui.SendMessage(hwnd,
getValueMessage,
itemIndex,
valuebuffer)
result.append(valuebuffer.tostring()[:valueLength])
return result
def getListboxItems(hwnd):
'''Returns the items in a list box control.
Arguments:
hwnd Window handle for the list box.
Returns: List box items.
Usage example: TODO
'''
return _getMultipleWindowValues(hwnd,
getCountMessage=win32con.LB_GETCOUNT,
getValueMessage=win32con.LB_GETTEXT)