I already post a similar question last week without success.
Ok I want to get the current text selection in a RICHEDIT control..
This can be easily done in C++ with EM_EXGETSEL message. I really
need to do the same thing in C#.
How can I put the structure in memory to be able to call SendMessage
and get the expected results in the structure.
Im playing with the following code but the target application always
crash.
For using the following example you need to start WordPad.exe (not
notepad), manually get the handle of the RichEdit control with Spy++
and replace the handle parameter in the sendmessage
initial condition : Type and select some text in WordPad
The following code must return Starting and ending position of
selected text in WordPad.
using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Diagnostics;
//..
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr
wparam, IntPtr lparam);
private const int WM_USER = 1024;
private const int EM_EXGETSEL = WM_USER + 52;
[StructLayout(LayoutKind.Sequential)]
public struct CharRange
{
public int From;
public int To;
public CharRange(int from, int to)
{
this.From = from;
this.To = to;
}
}
//..
CharRange ChrRange= new CharRange();
IntPtr ChrRangePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(ChrRange));
Marshal.StructureToPtr(ChrRange,ChrRangePtr, false);
SendMessage(Handle,EM_EXGETSEL,IntPtr.Zero,ChrRangePtr);
Marshal.PtrToStructure(ChrRangePtr,ChrRange);
MessageBox.Show("From="+ChrRange.From.ToString()+",
to="+ChrRange.To.ToString());
Is anybody know how to correctly code the structure pointer marshaling
part??? How to make this simple example working?
Please help me if you can.. :(
At the first glance your declarations are okay. The problem seems to
be this:
Marshal.PtrToStructure(ChrRangePtr,ChrRange);
It doesn't work like that. The signature of this method is:
public static void PtrToStructure(
IntPtr ptr,
Object structure
);
It is actually quite misleading, but the second argument named
"structure" actually is of type object - so when you pass a struct
(i.e. a value type) to it, it gets boxed first, and the method
operates on that boxed copy. In fact, this method tries to detect
this, as described in MSDN:
"Exceptions: ArgumentException when structure layout is not
sequential or explicit or structure is a boxed value type."
What you need to do is to use the second overload, like this:
ChrRange = (CharRange)PtrToStructure(ChrRangePtr,
typeof(CharRanger));
See if that helps.
Also, don't forget to free the memory block you've allocated - GC
won't do it for you.
the target application is still crashing when executing SendMessage :
The memory could not be 'written'
What is wrong with my ChrRangePtr???
Note: In my test the target application is WordPad.exe and Handle is
the RichEdit Handle
You cannot pass pointers via SendMessage to another process!!
In order to do this you would need to allocate memory in the other process's
space, send that via SendMessage and then read it back to your process. But
you should have a very good reason before you start messing around with
another process's memory.
"michelqa" <mich...@yahoo.ca> wrote in message
news:be603115-8e3c-4207...@v26g2000prm.googlegroups.com...
This is not entirely true, since SendMessage does perform pointer
marshalling for cross-process sends, but only for message types that
it knows - and those are all messages with codes smaller than WM_USER.
To quote MSDN:
"The system only does marshalling for system messages (those in the
range 0 to (WM_USER-1)). To send other messages (those >= WM_USER) to
another process, you must do custom marshalling."
Which is just the case here, considering this declaration:
Thanks, that's an important correction. When I edited my post I accidentally
dropped a bit about non-system messages. But, in particular, there are a
number of useful common control messages where the marshalling is done for
you.
Any example about how to allocate memory into the other process
memory? I really need to do that for several similar messages :
( ...for now I'm trying to get LVM_GETCOLUMN