Prev: SendInput and Unicode
Next: Run Time Creating Controls
From: mayayana on 3 Feb 2009 10:10 > EM_LINEFROMCHAR seems to be a very convenient way to find the character. > I'm still confused about what you're trying to do. I thought you were trying to use EM_CHARFROMPOS to get the char. offset. But your second post sounded like you're actually trying to get the line number. I'm guessing that's what Bill McCarthy was answering. EM_LINEFROMCHAR (or EM_EXLINEFROMCHAR, which is recommended) is actually for getting the line number. (More confusing docs there: The docs say it returns the "line index", meaning that it returns the line number. Then there's EM_LINEINDEX, which returns the offset of the first char. in the line. :) And note that sending -1 to EM_LINEFROMCHAR gets you the *beginning* of the selection. That's not necessarily the line where mouseup happened, but it's OK if you want SelStart. > @mayayana: > could you please tell me how to manage the char offset as input for the > GetCharPos in Eduardo's Richedit? > Again, I think it would be easier for everyone if you try to make more clear exactly what you need to do. Eduardo's function takes the char. offset (SelStart in an RTB, assuming you want the position where the mouse just clicked). It returns line number and/or offset ("index") of the first char. in the line. This is the code: '---------------------------- Public Sub GetCharPos(ByVal CharIndex As Long, Optional Line As Long, Optional Column As Long) Dim lFirstCharPos As Long ' Get the line index Line = SendMessage(m_hWndRE, EM_EXLINEFROMCHAR, 0, ByVal CharIndex) ' Get the index of the first char in line lFirstCharPos = SendMessage(m_hWndRE, EM_LINEINDEX, Line, ByVal 0&) ' Calculate the column Column = CharIndex - lFirstCharPos + 1 ' Increment the line to ' make it 1 based Line = Line + 1 End Sub '------------------------------ Do you want to find the char. offset of where the mouse clicked, but you're not finding EM_CHARFROMPOS to be what you wanted? And then maybe you want to get the line number? Here's another approach for a basic SelStart function, returning the offset where the caret currently is, or more specifically, where the beginning of the selection is: Dim CR1 As CHARRANGE SendMessage hRTB, EM_EXGETSEL, 0, CR1 SelStart = CR1.cpMin You might want to read up on the EM_ calls. There are a lot of them. You can sometimes accomplish something in more than one way. I'm sorry if this is getting confusing. I'm not sure of what you need and I'm not really familiar with Eduardo's control. I looked at the .ctl file but the control itself won't load for me. It causes an error. From looking at the .ctl there seem to be a lot of things lacking, not least of which is SelStart. Frankly, if it were me I might be inclined to try the vbAccelerator RTB if you need v. 2 and don't want to mess with creating it yourself. Eduardo Morcillo does some interesting stuff, but in my experience his code is usually quirky, "adventurous" and oftern partial. He often seems to be just writing the code as an exercise to explore this or that. And it always lacks documentation. (On the up side, he's written code for things that are hard to find elsewhere.)
From: mayayana on 3 Feb 2009 11:17 The following works well for me in an RTB. I can't try it in Eduardo Morcillo's RTB, since I can't load it. This code loads a file into an RTB. There are also 4 textboxes on the form. When the RTB is clicked they show X, Y, SelStart, and word clicked. (It's rough code. If you click before a word the last word is highlighted. To do a thorough job you need to look for delimiters.) '--------------------------------------------------------- Private Type point x As Long y As Long End Type Private Const WM_USER = &H400 Private Const EM_CHARFROMPOS& = &HD7 Private Const EM_FINDWORDBREAK = (WM_USER + 76) Private Const WB_RIGHTBREAK = 7& Private Const WB_MOVEWORDRIGHT = 5& Private Const WB_MOVEWORDLEFT = 4& Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Private Sub Form_Load() RTB.LoadFile "C:\windows\desktop\error codes.txt" End Sub Private Sub RTB_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single) Text1.Text = x \ Screen.TwipsPerPixelX Text2.Text = y \ Screen.TwipsPerPixelY Dim Pt1 As point Dim LRet As Long, CPos As Long, LLeft As Long, LEnd As Long Pt1.x = x \ Screen.TwipsPerPixelX Pt1.y = y \ Screen.TwipsPerPixelY '-- get character offset. LRet = SendMessage(RTB.hwnd, EM_CHARFROMPOS, 0&, Pt1) Text3.Text = LRet LLeft = SendMessageLong(RTB.hwnd, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, LRet) LEnd = SendMessageLong(RTB.hwnd, EM_FINDWORDBREAK, WB_RIGHTBREAK, LLeft) With RTB .SelStart = LLeft .SelLength = LEnd - LLeft Text4.Text = .SelText End With End Sub '--------------------------------------------------------- > Yes, that's the problem. I am still experimenting, but so far the value > returned from CHARFROMPOS is not usable. I changed > Pt1.x = 1 to Pt1.x = x to get a bit closer, but still not much > success. > > Jan > > > Doesn't EM_CHARFROMPOS do that, regardless of font size? > > Maybe you should explain what you're trying to accomplish. > >
From: mayayana on 3 Feb 2009 12:06 Interesting problems here... There seem to be some quirks between RTB v. 1 and v. 2. The code I just posted worked well with a VB RTB (v. 1), but when I tried it with my own version of an RTB v. 2, I get nothing no matter where I click. LLeft and LEnd return the same value. But if I add 1 to LLeft on the second call it works fine, except for the fine-tuning quirks. (Ex, clicking in front of the first letter of a wrod selects the prior word.) LEnd = SendMessageLong(RTB.hwnd, EM_FINDWORDBREAK, WB_RIGHTBREAK, LLeft + 1) I don't know if that helps, except to demonstrate that RichEdit v. 1 and v. 2 seem to have some minor compatibility issues.
From: Jan Opitz on 3 Feb 2009 12:33
I assume the EM_CHARFROMPOS unfortunately does not work with Eduard's RE, anyway not with the code for a RTB. The RE is different in many ways. That is why I tried to use the EM_LINEFROMCHAR value and then calculate from the x value the character closest to the cursor. But this due to font changes and character width differences ist not accurate emough. Also, I am working with Asean languages, so there is no wordbreak. In a MouseUp procedure I am able to retreive the Character following the EM_EXGETSEL you suggested, thank you. I may have to use a RTB as an (unvisible) mirror of the RE, just for position calculations, since the RE is the better choice for processing non-ANSI strings. Jan > The following works well for me in an RTB. I can't > try it in Eduardo Morcillo's RTB, since I can't load it. > This code loads a file into an RTB. There are also 4 > textboxes on the form. When the RTB is clicked they > show X, Y, SelStart, and word clicked. > > |