Marshaling Struct for native SendMessage

M

michelqa

Hi,

I need to call a lot of different native SendMessage to retreive
informations from non managed application.

Some win32 messages use struct pointer for lparam....how to create and
marshaling the struct to be able to use it in sendmessage...

Here is an example LM_GETITEM:
http://msdn.microsoft.com/en-us/library/bb760720(VS.85).aspx
---------------------------------------------------------

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr
wparam, IntPtr lparam);
//...
[StructLayout(LayoutKind.Sequential)]
public struct LITEM
{
uint mask;
int iLink;
uint state;
uint stateMask;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
string szID; //??? is it equivalent to WCHAR ?//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
string szUrl; //??? is it equivalent to WCHAR ?//
}

LITEM MyLItem = new LITEM();
int MsgResult = SendMessage(Handle,LM_GETITEM,IntPtr.Zero,ref
MyLItem); //<----- ???????

I know the information in the struct must be set before calling
sendmessage...the code is just an incomplete example, but how to
create and marshaling a valid struct to call sendmessage in this
case? Is it possible when the Handle is in a different process??

Thanks for any help and example...
 
P

Pavel Minaev

Hi,

   I need to call a lot of different native SendMessage to retreive
informations from non managed application.

Some win32 messages use struct pointer for lparam....how to create and
marshaling the struct to be able to use it in sendmessage...

Here is an example LM_GETITEM:http://msdn.microsoft.com/en-us/library/bb760720(VS.85).aspx
---------------------------------------------------------

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr
wparam, IntPtr lparam);
//...
[StructLayout(LayoutKind.Sequential)]
public struct LITEM
{
        uint mask;
        int iLink;
        uint state;
        uint stateMask;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        string szID;    //??? is it equivalent to WCHAR  ?//
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        string szUrl;   //??? is it equivalent to WCHAR  ?//

}

LITEM MyLItem = new LITEM();
int MsgResult = SendMessage(Handle,LM_GETITEM,IntPtr.Zero,ref
MyLItem);   //<----- ???????

I know the information in the struct must be set before calling
sendmessage...the code is just an incomplete example, but how to
create and marshaling a valid struct to call sendmessage in this
case?

Consider using Marshal.StructureToPtr() method. You'll need to
allocate a memory block of proper size first, then call StructureToPtr
to marshal your structure into that block in the appropriate format,
and then you can pass the address of that block as IntPtr to
SendMessage.
Is it possible when the Handle is in a different process??

It is, though it has no relevance to P/Invoke marshalling - it's the
SendMessage function itself that checks whether a handle belongs to a
different process, and does any further necessary marshalling to
deliver it properly. However, this SendMessage feature only works for
Win32 predefined message types (with codes less than WM_USER), not for
any custom messages.
 
M

michelqa

Thanks for your help... I really need help on this :(

Ok now my code look like this... but sendMessage return 0
- Is anybody can confirm that the code look correct (for passing a
structure pointer to sendmessage??)
- After calling sendmessage how can I access to the structure
information returned by MyLItemPtr???
- Since LM_GETITEM is WM_USER +771.... I suspect I need other
marshaling to get the structure back with the information??

//----------- BEGIN CODE -------------//
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr
wparam, IntPtr lparam);
//...
int WM_USER =1024,
int LM_GETITEM = (WM_USER + 0x303)
int LIF_ITEMINDEX = 1;
int LIF_URL = 8;

//..
[StructLayout(LayoutKind.Sequential)]
public struct LITEM
{
uint mask;
int iLink;
uint state;
uint stateMask;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)]
string szID; //??? is it equivalent to WCHAR ?//
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2084)]
string szUrl; //??? is it equivalent to WCHAR ?//
}


LITEM MyLItem = new LITEM();
MyLItem.mask=(uint)LIF_ITEMID | (uint)LIF_URL; //must use these
masks to get the url
MyLItem.iLink=0;
IntPtr MyLItemPtr = Marshal.AllocHGlobal(Marshal.SizeOf(MyLItem));
Marshal.StructureToPtr(MyLItem, MyLItemPtr, false);
IntPtr MsgResult =
Win32.SendMessage(Handle,LM_GETITEM,IntPtr.Zero,MyLItemPtr);
MessageBox.Show(MsgResult.ToString()); //this return 0 :(
Marshal.FreeHGlobal(MyLItemPtr);
//----------- END CODE -------------//

Thanks again
 
M

michelqa

Thanks for the suggestion.. I post my problem in this newsgroup also.

For now I will maybe try to recreate this directly in a win32 project
to make sure the problem is not a misunderstanding of the LM_GETITEM
API....but by looking at the LM_GETITEM in controlSpy my parameters
seems to be ok. (http://www.microsoft.com/downloads/details.aspx?
familyid=19d4294d-0531-4ec2-8b27-2e463b315f16&displaylang=en)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top