MessageWindow question

  • Thread starter Thread starter Tim Johnson
  • Start date Start date
T

Tim Johnson

I just learned that using a C# delegate as a function pointer to allow
callbacks from unmanaged C++ code isn't supported in .Net Compact Framework.
Big bummer.

So as I look into using MessageWindow instead (in which unmanaged code posts
a Win32 message which is received in C#), I see that you get the usual
lParam and wParam values inside a little C# msg structure. My question is,
how does marshalling get involved if at all? Specifically, if one of my
legacy functions posts a message whose lParam is a pointer to an array, or a
structure of ints, bools, and LPTSTRs, how do I safely get at all those
elements? I'm assuming marshalling doesn't play here so I'm not sure what
I'll be getting in C#, or what work I need to do in my code.
 
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this structure in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually
 
So far I can't even compile to try it. I'm trying to create a class
inheriting from MessageWindow but when I say "using System.Windows.Forms"
(as some articles say) it complains it doesn't know about MessageWindow.
And when I say "using Microsoft.WindowsCE.Forms" or "using
Microsoft.WindowCE.Forms" (as some other articles say), it complains there's
no such type or namespace as 'Microsoft'. Any idea what the real story is?

--
Tim Johnson

Alex Feinman said:
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this structure in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually
 
You need to add a reference to Microsoft.WindowsCE.Forms.dll, then add
"using Microsoft.WindowsCE.Forms"
The class you are building exists for example in this sample (unrelated
otherwise) http://www.alexfeinman.com/download.asp?doc=ScanTest.zip

--
Alex Feinman
---
Visit http://www.opennetcf.org
Tim Johnson said:
So far I can't even compile to try it. I'm trying to create a class
inheriting from MessageWindow but when I say "using System.Windows.Forms"
(as some articles say) it complains it doesn't know about MessageWindow.
And when I say "using Microsoft.WindowsCE.Forms" or "using
Microsoft.WindowCE.Forms" (as some other articles say), it complains
there's
no such type or namespace as 'Microsoft'. Any idea what the real story
is?

--
Tim Johnson

Alex Feinman said:
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an
array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this structure in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually

--
Alex Feinman
---
Visit http://www.opennetcf.org
Tim Johnson said:
I just learned that using a C# delegate as a function pointer to allow
callbacks from unmanaged C++ code isn't supported in .Net Compact
Framework.
Big bummer.

So as I look into using MessageWindow instead (in which unmanaged code
posts
a Win32 message which is received in C#), I see that you get the usual
lParam and wParam values inside a little C# msg structure. My question
is,
how does marshalling get involved if at all? Specifically, if one of
my
legacy functions posts a message whose lParam is a pointer to an array, or
a
structure of ints, bools, and LPTSTRs, how do I safely get at all those
elements? I'm assuming marshalling doesn't play here so I'm not sure what
I'll be getting in C#, or what work I need to do in my code.
 
Got it, thanks!

--
Tim Johnson
High Point Software
www.high-point.com
(503) 312-8625

Alex Feinman said:
You need to add a reference to Microsoft.WindowsCE.Forms.dll, then add
"using Microsoft.WindowsCE.Forms"
The class you are building exists for example in this sample (unrelated
otherwise) http://www.alexfeinman.com/download.asp?doc=ScanTest.zip

--
Alex Feinman
---
Visit http://www.opennetcf.org
Tim Johnson said:
So far I can't even compile to try it. I'm trying to create a class
inheriting from MessageWindow but when I say "using System.Windows.Forms"
(as some articles say) it complains it doesn't know about MessageWindow.
And when I say "using Microsoft.WindowsCE.Forms" or "using
Microsoft.WindowCE.Forms" (as some other articles say), it complains
there's
no such type or namespace as 'Microsoft'. Any idea what the real story
is?

--
Tim Johnson

Alex Feinman said:
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an
array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this
structure
in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually

--
Alex Feinman
---
Visit http://www.opennetcf.org
I just learned that using a C# delegate as a function pointer to allow
callbacks from unmanaged C++ code isn't supported in .Net Compact
Framework.
Big bummer.

So as I look into using MessageWindow instead (in which unmanaged code
posts
a Win32 message which is received in C#), I see that you get the usual
lParam and wParam values inside a little C# msg structure. My question
is,
how does marshalling get involved if at all? Specifically, if one of
my
legacy functions posts a message whose lParam is a pointer to an
array,
or
a
structure of ints, bools, and LPTSTRs, how do I safely get at all those
elements? I'm assuming marshalling doesn't play here so I'm not sure what
I'll be getting in C#, or what work I need to do in my code.
 
Marshal.PtrToStructure doesn't seem to work for me.

The original C+ struct is
typedef struct
{
unsigned char a[6];
TCHAR b[3];
int x;
int y;
} MyStruct;

I have a struct I defined in C# as
public struct MyStruct
{
public byte[] a;
public string b;
public int x;
public int y;
}

If I do Marshal.Copy to a byte[] buffer I can see all my data:

x01 x02 x03 x04 x05 x06 x41 x00 x42 x00 x43 x00 xAA x00 xBB x00

But if I do
MyStruct s = new MyStruct();
Marshal.PtrToStructure(msg.LParam, s);

the s Struct is empty. In any case I don't see how the marshaller could
know the byte[] array is only 6 bytes long, so how do you tell it this (given
the FieldOffset attribute isn't supported in .NetCF)?

What am I doing wrong? Or is there some way to manually march thru LParam
with a series of "copy" operations (although I don't see how to bump the
source field, as in msg.LParam+3, since ptrs aren't allowed).

Tim

Alex Feinman said:
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this structure in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually
 
It's because of the arrays. You'll have to manually marshal the data to
your class using Marshal.Copy, which you're close to having already anway.

-Chris


Tim Johnson said:
Marshal.PtrToStructure doesn't seem to work for me.

The original C+ struct is
typedef struct
{
unsigned char a[6];
TCHAR b[3];
int x;
int y;
} MyStruct;

I have a struct I defined in C# as
public struct MyStruct
{
public byte[] a;
public string b;
public int x;
public int y;
}

If I do Marshal.Copy to a byte[] buffer I can see all my data:

x01 x02 x03 x04 x05 x06 x41 x00 x42 x00 x43 x00 xAA x00 xBB x00

But if I do
MyStruct s = new MyStruct();
Marshal.PtrToStructure(msg.LParam, s);

the s Struct is empty. In any case I don't see how the marshaller could
know the byte[] array is only 6 bytes long, so how do you tell it this (given
the FieldOffset attribute isn't supported in .NetCF)?

What am I doing wrong? Or is there some way to manually march thru LParam
with a series of "copy" operations (although I don't see how to bump the
source field, as in msg.LParam+3, since ptrs aren't allowed).

Tim

Alex Feinman said:
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this structure in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually

--
Alex Feinman
---
Visit http://www.opennetcf.org
Tim Johnson said:
I just learned that using a C# delegate as a function pointer to allow
callbacks from unmanaged C++ code isn't supported in .Net Compact
Framework.
Big bummer.

So as I look into using MessageWindow instead (in which unmanaged code
posts
a Win32 message which is received in C#), I see that you get the usual
lParam and wParam values inside a little C# msg structure. My question
is,
how does marshalling get involved if at all? Specifically, if one of my
legacy functions posts a message whose lParam is a pointer to an array, or
a
structure of ints, bools, and LPTSTRs, how do I safely get at all those
elements? I'm assuming marshalling doesn't play here so I'm not sure what
I'll be getting in C#, or what work I need to do in my code.
 
Ok, so I see this one:

Marshal.Copy(msg.LParam, MyStruct.a, 0, 6);

but where to go from there? I can't do this:

Marshal.Copy(msg.LParam+6, MyStruct.b, 0, 3);

etc because I can't "offset" from msg.LParam. How to accomplish that in
..Net CF?

Or if I copy all 20 bytes into a larger byte[] buffer, then how do I access
the parts of it (the 1st 6 bytes is an array; next is a string, then 2
ints)?

--
Tim Johnson
High Point Software
www.high-point.com
(503) 312-8625

Chris Tacke said:
It's because of the arrays. You'll have to manually marshal the data to
your class using Marshal.Copy, which you're close to having already anway.

-Chris


Tim Johnson said:
Marshal.PtrToStructure doesn't seem to work for me.

The original C+ struct is
typedef struct
{
unsigned char a[6];
TCHAR b[3];
int x;
int y;
} MyStruct;

I have a struct I defined in C# as
public struct MyStruct
{
public byte[] a;
public string b;
public int x;
public int y;
}

If I do Marshal.Copy to a byte[] buffer I can see all my data:

x01 x02 x03 x04 x05 x06 x41 x00 x42 x00 x43 x00 xAA x00 xBB x00

But if I do
MyStruct s = new MyStruct();
Marshal.PtrToStructure(msg.LParam, s);

the s Struct is empty. In any case I don't see how the marshaller could
know the byte[] array is only 6 bytes long, so how do you tell it this (given
the FieldOffset attribute isn't supported in .NetCF)?

What am I doing wrong? Or is there some way to manually march thru LParam
with a series of "copy" operations (although I don't see how to bump the
source field, as in msg.LParam+3, since ptrs aren't allowed).

Tim

Alex Feinman said:
Actually marshal class is what you need. If a DLL in your process address
space sends up a message with LParam pointing to (hypothetically) an array
of ints and in WParam its size, in the message proc you will use:

int[] myData = new int[WParam];
Marshal.Copy(LParam, myData, 0, WParam);

If LParam is a pointer to a structure and you have defined this structure in
your managed code as MyStruct, use:

MyStruct st = new MysStruct();
Marshal.PtrToStructure(LParam, st);

With pointer to string you need to use:
string MyString = Marshal.PtrToStringUni(LParam);

If your structure contains pointers, you will need to dereference them
manually

--
Alex Feinman
---
Visit http://www.opennetcf.org
I just learned that using a C# delegate as a function pointer to allow
callbacks from unmanaged C++ code isn't supported in .Net Compact
Framework.
Big bummer.

So as I look into using MessageWindow instead (in which unmanaged code
posts
a Win32 message which is received in C#), I see that you get the usual
lParam and wParam values inside a little C# msg structure. My question
is,
how does marshalling get involved if at all? Specifically, if one
of
sure
 
Back
Top