简体   繁体   English

适用于Windows 64位的LVITEM

[英]LVITEM for windows 64 bit

For a long time I tried to use the LVM_GETITEMW message with LVIF_TEXT mask to get the text of a ListView. 很长时间以来,我尝试将LVM_GETITEMW消息与LVIF_TEXT掩码一起使用以获取ListView的文本。 My program worked in 32 bit but not in 64 bit architecture. 我的程序在32位上工作,但在64位体系结构上工作。

I discovered that the problem was at the LVITEM struct. 我发现问题出在LVITEM结构上。 Shortly, my question is which struct is the appropriate one for 64 bit and why. 不久,我的问题是哪种结构适合64位,为什么呢?

The struct I used as the LVITEMW struct had the following fields: 我用作LVITEMW结构的结构具有以下字段:

('mask', c_uint32),
('iItem', c_int32),
('iSubItem', c_int32),
('state', c_uint32),
('stateMask', c_uint32),
('pszText', c_uint32),
('cchTextMax', c_int32),
('iImage', c_int32),
('lParam', c_uint64),
('iIndent', c_int32),
('iGroupId', c_int32),
('cColumns', c_uint32),
('puColumns', c_uint32),
('piColFmt', c_int32),
('iGroup', c_int32)

(Written with python 2.7 ctypes, but this is just a form of writing - the language is really irrelevant). (使用python 2.7 ctypes编写,但这只是一种书写形式-语言确实无关紧要)。

These fields are just as documented . 这些字段已记录

After a lot of googling, I found this forum which had exactly what I needed - the 64 bit solution! 经过大量的搜寻,我发现这个论坛正是我所需要的-64位解决方案!

So in 64 bit the struct should have more "spaces", and should look something like this (the pointers are now 64 bit and also the stateMask is 64 bit. That's a little bit different from what the forum suggested but works too): 因此,在64位中,该结构应该具有更多的“空间”,并且应该看起来像这样(指针现在为64位, stateMask也为64位。这与论坛建议的内容略有不同,但也可以使用):

('mask', c_uint32),
('iItem', c_int32),
('iSubItem', c_int32),
('state', c_uint32),
('stateMask', c_uint64), <-- Now 64 bit
('pszText', c_uint64), <-- Now 64 bit which makes sense since this is a pointer
('cchTextMax', c_int32),
('iImage', c_int32),
('lParam', c_uint64),
('iIndent', c_int32),
('iGroupId', c_int32),
('cColumns', c_uint32),
('puColumns', c_uint64), <-- Now 64 bit which makes sense since this is a pointer
('piColFmt', c_int64), <-- Now 64 bit which makes sense since this is a pointer
('iGroup', c_int32)

The forum suggested having: 该论坛建议:

('mask', c_uint32),
('iItem', c_int32),
('iSubItem', c_int32),
('state', c_uint32),
('stateMask', c_uint64),
('pszText', c_uint64),
('cchTextMax', c_int32),
('iImage', c_int64), <-- Now 64 bit
('lParam', c_uint32),
('iIndent', c_int32),
('iGroupId', c_int32),
('cColumns', c_uint32),
('puColumns', c_uint32),
('piColFmt', c_int32),
('iGroup', c_int64), <-- Now 128 bit all together
('iGroup2', c_int64) <-- continuation

Which also works, at list for my need which is the text pointed by pszText. pszText指向的文本也可以用,在我需要的列表中。

And my questions are: 我的问题是:

  1. Is this documented anywhere? 这在任何地方都有记录吗?
  2. Why should the stateMask be c_uint64 - shouldn't it always be the same size as the state ? 对为什么要stateMaskc_uint64 -它不应该永远是大小相同的state
  3. Which one is the true struct for 64 bit? 哪一个是64位的真正结构?

Thank you! 谢谢!

Thanks to the comment by Raymond Chen I was able to figure out the answer! 感谢Raymond Chen的评论,我得以弄清楚答案!

It's about data alignment . 这与数据对齐有关 Every pointer should be 8 bytes and should also be aligned to an address that can be divided by 8, so sometimes there should be a padding before the pointer. 每个指针应为8个字节,并且还应对齐可除以8的地址,因此有时指针前应有填充。 Also, the size of the struct should be dividable by min(max(sizeof(each field in the struct)), 8) which is 8 in our case since the size of a pointer is 8. 另外,该结构的大小应可除以min(max(sizeof(each field in the struct)), 8) ,在本例中为8,因为指针的大小为8。

class LVITEMW_explicit(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ('mask', c_uint32),         # 0
        ('iItem', c_int32),         # 4
        ('iSubItem', c_int32),      # 8
        ('state', c_uint32),        # 12
        ('stateMask', c_uint32),    # 16
        ('padding1', c_int),
        ('pszText', c_uint64),      # 20 --> 24 after padding (A pointer)
        ('cchTextMax', c_int32),    # 32
        ('iImage', c_int32),        # 36
        ('lParam', c_uint64),       # 40 (On 32 bit should be c_long which is 32 bits)
        ('iIndent', c_int32),       # 48
        ('iGroupId', c_int32),      # 52
        ('cColumns', c_uint32),     # 56
        ('padding2', c_int),
        ('puColumns', c_uint64),    # 60 --> 64 after padding (A pointer)
        ('piColFmt', c_int64),      # 72 (A pointer)
        ('iGroup', c_int32),        # 80
        ('padding3', c_int32),      # The total length was 84 before padding3 was added, which is not dividable by 8
    ]

Or as this should really be written - without the _pack_ = 1 : 还是应该这样写-没有_pack_ = 1

class LVITEMW(ctypes.Structure):
    _fields_ = [
        ('mask', c_uint32),
        ('iItem', c_int32),
        ('iSubItem', c_int32),
        ('state', c_uint32),
        ('stateMask', c_uint32),
        ('pszText', c_uint64),
        ('cchTextMax', c_int32),
        ('iImage', c_int32),
        ('lParam', c_uint64), # On 32 bit should be c_long
        ('iIndent', c_int32),
        ('iGroupId', c_int32),
        ('cColumns', c_uint32),
        ('puColumns', c_uint64),
        ('piColFmt', c_int64),
        ('iGroup', c_int32),
    ]

And indeed ctypes.sizeof(LVITEMW) returns 88, same as ctypes.sizeof(LVITEMW_explicit) . 实际上, ctypes.sizeof(LVITEMW)返回88,与ctypes.sizeof(LVITEMW_explicit)相同。

Thanks again for the helpful comments! 再次感谢您的有用评论!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM