I am trying to use SendMessage to find text in a certain window using the FindText structure as parameter.
But I keep on getting a "Object reference not set to instance of an object " when the Sendmessage gets executed.
The same code in vb works just fine!
Can anyone help me out please with what I might be doing wrong.
Since I am calling the api from an addin for Outlook and the SendMessage is taking a handle to an Outlook window, I don't think there is a problem with send message across process boundaries as both are running in the same process.
Any pointers in the right direction would be great. Its been really hard getting any working examples for a combination of SendMessage and Findtext structure parameters in c#.
I could post my code and declarations if need be.
Thanks,
jbhan.
Please do
Mattias
--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
These declarartions are in the file named RichEdit.cs
[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct FindText
{
public CHARRANGE chrg;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpstrText;
}
[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct CHARRANGE
{
public long cpMin;
public long cpMax;
}
[DllImport("User32.dll",CharSet = CharSet.Auto) ]
public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg,int wParam, IntPtr lParam);
[DllImport("User32.dll", EntryPoint="SendMessage", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessageLong(IntPtr hwnd,long wMsg,long wParam,long lParam);
This function is in RichTextWrapper.cs
public long FindTextW(string sText,ERECFindTypeOptions eOptions,long lStart,long lEnd)
{
RichEdit.CHARRANGE tCR = new RichEdit.CHARRANGE();
RichEdit.FindText tEx= new RichEdit.FindText();
IntPtr res = IntPtr.Zero;
IntPtr lPtr =IntPtr.Zero;
sText = "Martin\0";//+ Convert.ToChar(0);
tCR.cpMax =-1;
tCR.cpMin =0;
try
{
tEx.lpstrText= sText;
tEx.chrg = tCR;
lPtr = Marshal.AllocHGlobal(Marshal.SizeOf(tEx));
Marshal.StructureToPtr(tEx,lPtr,true);
res= RichEdit.SendMessage((IntPtr)m_hWnd,(int)RichEdit.EM_FINDTEXT,0, lPtr);
}
catch(Exception ex1)
{
MessageBox.Show(ex1.Message);
}
Marshal.FreeHGlobal(lPtr);
//res = RichEdit.SendMessageLong((IntPtr)m_hWnd,(int)RichEdit.EM_GETLINECOUNT, 0,0);
return (long)res;
}
You can also save some work by changing the lParam parameter type on
SendMessage to ref FINDTEXT and pass the tEx variable directly.
But now I have another problem, there is a piece of code in Vb and I don't know how to specify its equivalent in c#. This is specifically for the string member variable of the FindText structure.
//VB Code
Dim tCR As CHARRANGE
Dim lR As Long
Dim b() As Byte
tCR.cpMin = lStart
tCR.cpMax = lEnd
b = StrConv(sText, vbFromUnicode)
ReDim Preserve b(0 To UBound(b) + 1) As Byte
b(UBound(b)) = 0
tEx1.lpstrText = VarPtr(b(0))
LSet tEx1.chrg = tCR
lR = SendMessage(m_hWnd, EM_FINDTEXTEX, eOptions, tEx1)
The following is my version in C# ...which always returns me 0.
Byte [] bytes;
ASCIIEncoding ascii = new ASCIIEncoding();
int byteCount = ascii.GetByteCount(sText.ToCharArray());
bytes = new Byte[byteCount];
bytes = ascii.GetBytes(sText);
bytes[bytes.GetUpperBound(0)] = 0; // to remove the null character at the end of the string.
GCHandle gc = GCHandle.Alloc(bytes[0],GCHandleType.Pinned);
tEx.lpstrText = gc.AddrOfPinnedObject(); // lpstrText is an Intptr in the Findtext structure.
gc.Free();
tEx.chrg = new CHARRANGE();
tEx.chrg.cpMax =(int)lEnd;
tEx.chrg.cpMin =(int)lStart;
res= SendMessage((int)m_hWnd,EM_FINDTEXT ,(int)eOptions, ref tEx);
//res is always 0
How do I pass the pointer to an array of bytes as a value for the FindText structure's string member variable?
Thanks,
jbhan
HTML in a Rich Text Box? Well I don't know why it doesn't work in this
case, sorry.