[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