适用于 Windows 64 位的 LVITEM [英] LVITEM for windows 64 bit
问题描述
很长一段时间以来,我尝试使用带有 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.
我的问题是:
- 这是否在任何地方都有记录?
- 为什么
stateMask
应该是c_uint64
- 它不应该总是与state
的大小相同吗? - 哪个是 64 位的真正结构体?
- Is this documented anywhere?
- Why should the
stateMask
bec_uint64
- shouldn't it always be the same size as thestate
? - 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屋!