我们从 CommCtrl.h 中得到这些定义:
#define TreeView_SetItemState(hwndTV, hti, data, _mask) \
{ TVITEM _ms_TVi;\
_ms_TVi.mask = TVIF_STATE; \
_ms_TVi.hItem = (hti); \
_ms_TVi.stateMask = (_mask);\
_ms_TVi.state = (data);\
SNDMSG((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_ms_TVi);\
}
#define TreeView_SetCheckState(hwndTV, hti, fCheck) \
TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), TVIS_STATEIMAGEMASK)
我们可以使用 PInvoke 将其转换为 C#。首先,我们将这些宏实现为函数,然后添加使这些函数工作所需的任何其他支持。这是我的第一次尝试。您应该仔细检查我的代码,尤其是在结构编组方面。此外,您可能希望跨线程发布消息,而不是调用 SendMessage。
最后,我不确定这是否会起作用,因为我相信通用控件使用 WM_USER+ 消息。当这些消息被跨进程发送时,数据参数的地址不会被修改,由此产生的进程可能会导致访问冲突。无论您使用哪种语言(C++ 或 C#),这都会是一个问题,所以也许我在这里错了(您说您有一个有效的 C++ 程序)。
static class Interop {
public static IntPtr TreeView_SetCheckState(HandleRef hwndTV, IntPtr hti, bool fCheck) {
return TreeView_SetItemState(hwndTV, hti, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), (uint)TVIS.TVIS_STATEIMAGEMASK);
}
public static IntPtr TreeView_SetItemState(HandleRef hwndTV, IntPtr hti, uint data, uint _mask) {
TVITEM _ms_TVi = new TVITEM();
_ms_TVi.mask = (uint)TVIF.TVIF_STATE;
_ms_TVi.hItem = (hti);
_ms_TVi.stateMask = (_mask);
_ms_TVi.state = (data);
IntPtr p = Marshal.AllocCoTaskMem(Marshal.SizeOf(_ms_TVi));
Marshal.StructureToPtr(_ms_TVi, p, false);
IntPtr r = SendMessage(hwndTV, (int)TVM.TVM_SETITEMW, IntPtr.Zero, p);
Marshal.FreeCoTaskMem(p);
return r;
}
private static uint INDEXTOSTATEIMAGEMASK(int i) { return ((uint)(i) << 12); }
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(HandleRef hWnd, int msg, IntPtr wParam, IntPtr lParam);
private enum TVIF : uint {
TVIF_STATE = 0x0008
}
private enum TVIS : uint {
TVIS_STATEIMAGEMASK = 0xF000
}
private enum TVM : int {
TV_FIRST = 0x1100,
TVM_SETITEMA = (TV_FIRST + 13),
TVM_SETITEMW = (TV_FIRST + 63)
}
private struct TVITEM {
public uint mask;
public IntPtr hItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
}
}