0

After I receive the Caret (x,y) position using GetCaretPos I want to SendMessage() of EM_CHARFROMPOS. The problem is that the lParam should be of type IntPtr, and the result of GetCaretPos is a point. How do I cast the point to an IntPtr correctly?

Tal XD
  • 45
  • 6
  • You need a pointer to unmanaged memory. So use : https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.structuretoptr?view=netcore-3.1 – jdweng Apr 28 '20 at 15:21
  • The return value of `GetCaretPos` is a [POINT](https://learn.microsoft.com/en-us/previous-versions/dd162805(v=vs.85)). That's binary compatible with a [POINTL](https://learn.microsoft.com/en-us/previous-versions/dd162807(v=vs.85)), so you can pass a pointer to it unmodified, if you are targeting a Rich Edit control. For a standard Edit control, you're going to have to truncate the `x` and `y` fields to 16-bit unsigned values, and binary OR them together into a 32-bit value. You can pass a zero-extended value of pointer size as the `lParam` when targeting a standard Edit control. – IInspectable Apr 28 '20 at 15:29
  • How do I do that? @IInspectable – Tal XD Apr 28 '20 at 15:31
  • That generally involves to stop being a managed-only developer. Apart from that it seems irrational to avoid UI Automation for what you're trying to do. – IInspectable Apr 28 '20 at 15:49
  • I need it for google chorme, which doesn't support UI Automation. @IInspectable – Tal XD Apr 28 '20 at 17:11
  • Google Chrome doesn't use native Windows controls either, so that's not going to work anyway. – IInspectable Apr 28 '20 at 17:37

1 Answers1

1

The code must be different if you target a Rich edit control vs an Edit control, but you can get inspiration from .NET's code (and you can define multiple versions of SendMessage that suit your needs):

For a text box: https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/TextBoxBase.cs,1754

...
var pt = (IntPtr)MAKELONG(pt.X, pt.Y);
SendMessage(handle, EM_CHARFROMPOS, 0, pt);
...
public static int MAKELONG(int low, int high) {
  return (high << 16) | (low & 0xffff);
}

[DllImport("user32", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

For a rich text box: https://referencesource.microsoft.com/#system.windows.forms/winforms/Managed/System/WinForms/RichTextBox.cs,2323

...
var pt = new POINT(pt.X, pt.Y);
SendMessage(handle, EM_CHARFROMPOS, 0, pt);
...

[StructLayout(LayoutKind.Sequential)]
public class POINT
{
  public int x;
  public int y;
}

[DllImport("user32", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, POINT lParam);
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298