如何在C#中定义TBBUTTON结构?

时间:2011-03-31 06:21:15

标签: c# interop 64-bit

问候所有人,

TBBUTTON结构在MSDN上定义如下:

typedef struct {
  int       iBitmap;
  int       idCommand;
  BYTE      fsState;
  BYTE      fsStyle;
#ifdef _WIN64
  BYTE      bReserved[6];
#else 
#if defined(_WIN32)
  BYTE      bReserved[2];
#endif 
#endif 
  DWORD_PTR dwData;
  INT_PTR   iString;
} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;

我需要使用这个结构在C#中进行一些互操作。我如何复制这个怪物,以便在为AnyCPU编译时正确定义?谷歌显然充满了危险的错误信息!

2 个答案:

答案 0 :(得分:3)

啊,我知道必须有办法。这是:

[StructLayout(LayoutKind.Sequential)]
public struct TBBUTTON {
    public int iBitmap;
    public int idCommand;
    [StructLayout(LayoutKind.Explicit)]
    private struct TBBUTTON_U {
        [FieldOffset(0)] public byte fsState;
        [FieldOffset(1)] public byte fsStyle;
        [FieldOffset(0)] private IntPtr bReserved;
    }
    private TBBUTTON_U union;
    public byte fsState { get { return union.fsState; } set { union.fsState = value; } }
    public byte fsStyle { get { return union.fsStyle; } set { union.fsStyle = value; } }
    public UIntPtr dwData;
    public IntPtr iString;
}

Marshal.SizeOf在x64进程上返回32,在x86进程上返回20,当我将其传递给SendMessage时,一切都会结束。我知道你可以做到,C#!

答案 1 :(得分:2)

最好的办法是定义两个版本,一个用于32位,另一个用于64位。

public struct TBBUTTON32
{
    int       iBitmap;
    int       idCommand;
    byte      fsState;
    byte      fsStyle;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
    byte[]    bReserved;
    UIntPtr   dwData;
    IntPtr    iString;
}

64位版本是相同的,但在保留字节数组上有SizeConst = 6

然后你需要在运行时在它们之间切换。您的C#代码必须检测它是以32位还是64位进程运行。