• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 377
  • Last Modified:

Problem calling ::SendMessage on a CRichEditCtrl

I am trying to find out the location of the pointer within a CRichEditCtrl without clicking within the control.  I need to know the character index it is on, not just the coordinates of the pointer.  To do this I'm calling
int charIndex = ::SendMessage(theCtrl, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));

from within the view's OnMouseMove() function, to convert the mouse position to a character index.  theCtrl is the richeditctrl instance, and pt is a CPoint object that is based on the point passed into OnMouseMove, but might be a few pixels shifted (for a reason, but I won't bother explaining why unless someone needs to know.)

I get an access violation when I hit this code.  Not every time, most often when I am in a part of the richeditctrl that I had to scroll down to get to, but also in places at the top if I go over them a few times.  It will work a few times then give the access violation eventually.

Any ideas?  Other ways to get the character index I'm pointing at without using this code?
0
appleby
Asked:
appleby
1 Solution
 
GlennDeanCommented:
You need to pass a handle to SendMessage.  If I understood you right, instead of passing theCtrl pass
theCtrl.m_hWnd to SendMessage.
0
 
mnewton022700Commented:
According to MSDN the lparam parameter should be a pointer to a POINTL structure. Try this:

POINTL pointl;
pointl.x = pt.x;
pointl.y = pt.y;

int charIndex = ::SendMessage(theCtrl, EM_CHARFROMPOS, 0, &pointl);
0
 
RONSLOWCommented:
int RichEditCharFromPos(CRichEditCtrl& theCtrl, const CPoint& pt) {
  ASSERT(::IsWindow(theCtrl.m_hWnd));
  return (int)::SendMessage(theCtrl.m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
}

This should work fine

0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
RONSLOWCommented:
Indeed .. tanks mnewton.

Richedit is indeed different from Edit control in this respect (why did MS do this?????).

So lets make it:

int RichEditCharFromPos(CRichEditCtrl& theCtrl, const CPoint& pt) {
  ASSERT(::IsWindow(theCtrl.m_hWnd));
  POINTL pointl;
  pointl.x = pt.x;
  pointl.y = pt.y;
  return (int)::SendMessage(theCtrl.m_hWnd, EM_CHARFROMPOS, 0, &pointl);
}

0
 
RONSLOWCommented:
Interestingly, the latest WTL from MS doesn't seem to know about this ... it uses this code for rich edit controls:

  int CharFromPos(POINT pt) const
  {
    ATLASSERT(::IsWindow(m_hWnd));
    return (int)::SendMessage(m_hWnd, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
  }

Either MS is wrong, or MS is wrong.  How are we mere mortals supposed to know what is right if MS gets it wrong themselves??? :-(
0
 
NickRepinCommented:
<<lParam
Specifies the coordinates of a point in the control's client area. The coordinates are in screen units and are relative to the upper-left corner of the control's client area.

Rich edit controls: This is a pointer to a POINTL structure that contains the horizontal and vertical coordinates.

Edit controls: The low-order word contains the horizontal coordinate. The high-order word contains the vertical coordinate. >>

0
 
RONSLOWCommented:
thats what mnewton and I said.
0
 
NickRepinCommented:
Yes, I just want to say that it is documented in the new platform sdk.
0
 
RONSLOWCommented:
Yes .. it is documented.  But the latest SDK also includes WTL, which has a bug in that it uses the wrong one.  So either the MS docs are wrong (unlikely) or the MS WTL library is wrong (quite likely).

It seems a very poor design decision to give the same message different parameters.  Surely separate messages would have been better.  One of the great mysteries of life :-)
0
 
applebyAuthor Commented:
I had to explicitly cast the &pointl param to long, but otherwise it worked fine.  I'm accepting RONSLOW's comment as the answer since it put together the two pieces I was missing.

Thank you all for the help.
0
 
RONSLOWCommented:
BTW: the nice way to do the cast is

reinterpret_cast<LPARAM>(&pointl)

this makes it obvious that you are passing a pointer as an LPARAM.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now