views:

298

answers:

1

I'm trying to subclass an unmanaged statusbar window from my managed COM server using a class inherited from NativeWindow, and am running into a wall trying to make sense of how to properly marshal the contents of an lParam.

http://msdn.microsoft.com/en-us/library/bb760757%28VS.85%29.aspx says that the contents of this lParam is of type (LPARAM)(LPINT) aWidths, and that the contents of this variable is actually a "pointer to an integer array."

I can't figure out a way to marshal this correctly. The goal is to read the lParam, add our value to the array, and then send the new message via base.wndProc(ref m).

It'd be nice if I could just int[] array = (int[])m.*lParam or somesuch, but life isn't so simple (and I don't get to use unsafe code). I've clumsily tried to force the marshaller to give me something via Marshal.PtrToStructure() but knew this was doomed from the start as the C-array isn't a struct and the struct I tried to make is obviously not blittable.

Right now we are letting the original call go through and then making additional WinAPI calls to get the array, format it, and then resend it before the statusbar can repaint. This is working well, but not well enough.

Any ideas?

Thanks!

Tom

PS- I've had a lot of trouble grokking how lParams are used in C#, the documentation is quite confusing :-/

A: 

Following the "dtb"'s comment, you can borrow some code from this SO entry.

The LPARAM you must supply is a pointer to the first element of the array. Then all you have to do is:

int[] parts = new int[]{ 1, 2, 3, 4 };
int nParts = parts.Length;
IntPtr pointer = Marshal.AllocHGlobal(nParts * Marshal.SizeOf(typeof(int));
for (int i = 0; i < nParts; i++) {
    Marshal.WriteInt32(pointer, i * Marshal.SizeOf(typeof(int), parts[i]);
}
// Call SendMessage with WPARAM = nParts and LPARAM = Pointer
Marshal.FreeHGlobal(pointer);
Laurent Etiemble