适用于 Windows 64 位的 LVITEM [英] LVITEM for windows 64 bit

查看:27
本文介绍了适用于 Windows 64 位的 LVITEM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很长一段时间以来,我尝试使用带有 LVIF_TEXT 掩码的 LVM_GETITEMW 消息来获取 ListView 的文本.我的程序可以在 32 位架构下运行,但不能在 64 位架构中运行.

For a long time I tried to use the LVM_GETITEMW message with LVIF_TEXT mask to get the text of a ListView. My program worked in 32 bit but not in 64 bit architecture.

我发现问题出在 LVITEM 结构上.很快,我的问题是哪个结构适合 64 位以及为什么.

I discovered that the problem was at the LVITEM struct. Shortly, my question is which struct is the appropriate one for 64 bit and why.

我用作 LVITEMW 结构的结构具有以下字段:

The struct I used as the LVITEMW struct had the following fields:

('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)

(用 python 2.7 ctypes 写的,但这只是一种写法——语言真的无关紧要).

(Written with python 2.7 ctypes, but this is just a form of writing - the language is really irrelevant).

这些字段就像 记录.

经过大量谷歌搜索后,我发现这个论坛我需要 - 64 位解决方案!

After a lot of googling, I found this forum which had exactly what I needed - the 64 bit solution!

所以在 64 位结构中应该有更多的空间",并且应该看起来像这样(指针现在是 64 位,而且 stateMask 是 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):

('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)

论坛建议:

('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

这也适用,在我需要的列表中,这是 pszText 指向的文本.

Which also works, at list for my need which is the text pointed by pszText.

我的问题是:

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

谢谢!

推荐答案

感谢 Raymond Chen 的评论,我找到了答案!

Thanks to the comment by Raymond Chen I was able to figure out the answer!

这是关于数据对齐.每个指针都应该是 8 个字节,并且还应该对齐到一个可以被 8 整除的地址,所以有时在指针之前应该有一个填充.此外,结构的大小应该可以被 min(max(sizeof(each field in the struct)), 8) 整除,在我们的例子中是 8,因为指针的大小是 8.

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. 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.

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
    ]

或者因为这真的应该写 - 没有 _pack_ = 1:

Or as this should really be written - without the _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),
    ]

确实 ctypes.sizeof(LVITEMW) 返回 88,与 ctypes.sizeof(LVITEMW_explicit) 相同.

And indeed ctypes.sizeof(LVITEMW) returns 88, same as ctypes.sizeof(LVITEMW_explicit).

再次感谢您的有益评论!

Thanks again for the helpful comments!

这篇关于适用于 Windows 64 位的 LVITEM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆