luc
luc

Reputation: 43096

Problem when getting the content of a listbox with python and ctypes on win32

I would like to get the content of a list box thanks to python and 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

The number of items is correct but the text is wrong. All text_len are 4 and the text values are something like '0\xd9\xee\x02\x90'

I have tried to use a unicode buffer with a similar result.

I don't find my error. Any idea?

Upvotes: 0

Views: 1387

Answers (2)

Matthew Xavier
Matthew Xavier

Reputation: 2128

If the list box in question is owner-drawn, this passage from the LB_GETTEXT documentation may be relevant:

If you create the list box with an owner-drawn style but without the LBS_HASSTRINGS style, the buffer pointed to by the lParam parameter will receive the value associated with the item (the item data).

The four bytes you received certainly look like they may be a pointer, which is a typical value to store in the per-item data.

Upvotes: 1

Andre Miller
Andre Miller

Reputation: 15493

It looks like you need to use a packed structure for the result. I found an example online, perhaps this will assist you:

http://www.brunningonline.net/simon/blog/archives/winGuiAuto.py.html

# Programmer : Simon Brunning - [email protected]
# 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)

Upvotes: 0

Related Questions