Greetings all,
The TBBUTTON struct is defined on MSDN as follows:
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;
I need to do some interop in C# using this struct. How do I replicate this monster so that it's defined correctly when compiled for AnyCPU? Google is apparently full of dangerous misinformation!
Ahah, I knew there had to be a way. And here it is:
[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
returns 32 on x64 processes and 20 on x86 processes, and everything ends up where it should when I pass this to SendMessage
. I knew you could do it, C#!
Your best bet is to define two versions, one for 32 bit and one for 64 bit.
public struct TBBUTTON32
{
int iBitmap;
int idCommand;
byte fsState;
byte fsStyle;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2)]
byte[] bReserved;
UIntPtr dwData;
IntPtr iString;
}
The 64 bit version is just the same but with SizeConst = 6
on the reserved bytes array.
Then you need to switch between them at runtime. Your C# code will have to detect whether it's running as a 32 or 64 bit process.
精彩评论