[Mono-dev] Question on the C->C# translation of WinApi MSG struct.
Mike Edenfield
kutulu at kutulu.org
Sat Sep 22 16:16:28 EDT 2007
StApostol wrote:
> I am writing OpenTK, a game development toolkit which makes extensive
> use of P/Invoke calls. On the Windows platform, I encountered some
> strange behavior regarding the MSG struct.
>
> In winuser.h, MSG is defined like this:
>
> typedef struct tagMSG {
> HWND hwnd;
> UINT message;
> WPARAM wParam;
> LPARAM lParam;
> DWORD time;
> POINT pt;
> #ifdef _MAC
> DWORD lPrivate;
> #endif
> } MSG;
>
> The C# equivalent, as suggested at the .Net dev forums, would look like
> this:
>
> [StructLayout(LayoutKind.Sequential), CLSCompliant(false)]
> public struct MSG
> {
> public IntPtr HWnd;
> public WindowMessage Message;
> public IntPtr WParam;
> public IntPtr LParam;
> public uint Time;
> public POINT Point;
>
> public override string ToString()
> {
> return String.Format("msg=0x{0:x} ({1}) hwnd=0x{2:x}
> wparam=0x{3:x} lparam=0x{4:x} pt=0x{5:x}", (int)Message,
> Message.ToString(), HWnd.ToInt32(), WParam.ToInt32(), LParam.ToInt32(),
> Point);
> }
> }
>
> However, Mono's implementation in xplatui adds one more field to the struct:
>
> [StructLayout(LayoutKind.Sequential), CLSCompliant(false)]
> public struct MSG
> {
> public IntPtr HWnd;
> public WindowMessage Message;
> public IntPtr WParam;
> public IntPtr LParam;
> public uint Time;
> public POINT Point;
>
> public object RefObject;
>
> public override string ToString()
> {
> return String.Format("msg=0x{0:x} ({1}) hwnd=0x{2:x}
> wparam=0x{3:x} lparam=0x{4:x} pt=0x{5:x}", (int)Message,
> Message.ToString(), HWnd.ToInt32(), WParam.ToInt32(), LParam.ToInt32 (),
> Point);
> }
> }
> My guess is that it is used for some kind of synchronization, but will
> this not corrupt the stack? Both seem to work correctly for extended
> periods of time on both 32- and 64-bit platforms, which I find a little
> strange. Which is the correct one? What is RefObject doing there?
The Windows API almost always passes structures like this as
pointers. PeekMessage() and all of the GetMessage() calls
pass an LPMSG parameter, for example. The only thing the
unmanaged code inside Windows knows about are the field
defined in the header, which are accessed as "x number of
bytes past the pointer value". As long as any additional
information is at the end of the structure, Windows will
ignore it.
In fact, Windows uses this fact itself when new features
come out, by adding fields to the end of key structures and
internally using sizeof(blah) to figure out what fields are
available.
The only thing you would need to watch out for is anything
that tries to take the size of a struct MSG, but I don't
know of any Windows API call that does so.
-- Mike
Still using IE? Get Firefox!
http://www.spreadfirefox.com/?q=affiliates&id=6492&t=1
More information about the Mono-devel-list
mailing list