Solved

Windows 2000, Rich Text Box  and WM_GETTEXT

Posted on 2000-04-30
15
753 Views
Last Modified: 2008-03-17
I have been having trouble returning a string from a richtextbox control in Windows 2000 and I need help.

CODE:
child = findchildbyclass(getpar, "RICHCNTL")
GetTrim = sendmessage(child, WM_GETTEXTLEN, 0, 0)
TrimSpace$ = Space$(GetTrim)
GetString = sendmessage(child, WM_GETTEXT, GetTrim + 1, TrimSpace$)

PROBLEM:
   This works under Windows NT 4.0, 95, 98 but doesn't work under Windows 2000. getpar is the handle of the "RICHCNTL" richtextbox control.  WM_GetTextLength works fine and return a length of say 1380 chars.  But after I call the WM_GETTEXT I get a return strign of 0 in the TrimSpace$ buffer... Anybody know what's going on??? HELP???
0
Comment
Question by:orbitaltech
  • 8
  • 5
  • 2
15 Comments
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
sorry, getpar is the handle of the window housing the Rich textbox control.. it's an out-of-process (in somebody elses program) -works fine
0
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
have you done a check to ensure that all handles involved are valid handles?
0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
yup Everything is valid
0
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
just for grins, maybe try postmessage and see if the result is any different
0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
gave it a shot and no luck... Postmessage will return 0 on when used with WM_GETTEXTLENGTH and return nothing as well with WM_GETTEXT.

Any other ideas?
0
 
LVL 14

Expert Comment

by:wsh2
Comment Utility
WM_GETTEXT has changed for Windows/2000.. MS recommends you use one of the following instead.

From MSDN:
--------------------------------------
Rich Edit Text Operations

An application can send messages to retrieve or find text in a rich edit control. You can retrieve either the selected text or a specified range of text.

To get the selected text in a rich edit control, use the EM_GETSELTEXT message. The text is copied to the specified character array. You must ensure that the array is large enough to hold the selected text plus a terminating null character.

To retrieve a specified range of text, use the EM_GETTEXTRANGE message. The TEXTRANGE structure used with this message specifies the text range to retrieve and points to a character array that receives the text. Here again, the application must ensure that the array is large enough for the specified text plus a terminating null character.

You can search for a string in a rich edit control by using the EM_FINDTEXT message. The FINDTEXT structure used with this message specifies the text range to search and the string to search for. You can also specify such options as whether the search is case-sensitive.
0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
I have researched that article on MSDN and found it to not work quite the way it states.. First off to use EM_GETTEXTEX, EM_GETTEXTLENGTHEX (not mentioned above) or EM_GETSELTEXT -

 it uses sendmessage(hWnd, EM_GETTEXTEX, (pointer to gettextex),0)

the pointer to gettextex is a class typedef which I have no idea how to transform into VB code.  

SendMessage(
  (HWND) hWnd,            // handle to destination window
  EM_GETTEXTLENGTHEX,     // message to send
  (WPARAM) wParam;        // text length (GETTEXTLENGTHEX *)
  (LPARAM) lParam;        // not used; must be zero
);

Which references

typedef struct _gettextlengthex {
    DWORD    flags;
    UINT    codepage;
} GETTEXTLENGTHEX;


Therefore, without the typedef transformation, this will not work and returns the same old 0's that the program always has... Any other thoughts?  Ideas to change typedefs to VB code??

-Still searching
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
looks like this probably:

Public Type GETTEXTLENGTHEX
   flags As Long
   codepage As Integer
End Type
0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
I got that far, now how do you reference in in sendmessage?
0
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
before you call SendMessage declare a variable as that type, for example:

Dim gtStruct As GETEXTLENGTHEX

I dont know if they say this structure should pass parameters or receive parameters. if it passes them then initialize them to whatever they need to be,

gtStruct.flags = ????
gtStruct.codepage = ????

then call the function


retval = SendMessage(hWnd,EM_GETTEXTLENGTHEX,gtStruct,0)
0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
by using that method... a type mismatch occurs in
retval = SendMessage(hwnd,EM_GETTEXTLENGTHEX,gtStruct,0)

on gtStruct
0
 
LVL 28

Expert Comment

by:AzraSound
Comment Utility
probably b/c your declaration of sendmessage is still expecting a Long parameter, try changing it to
ByRef wParam As GETTEXTLENGTHEX
0
 
LVL 14

Accepted Solution

by:
wsh2 earned 100 total points
Comment Utility
The EM_GETTEXTEX and EM_GETTEXTLENGTHEX APIs that you are trying to employ are only compatable with Rich Edit Controls equal to or greater than Version 2. The example below is compatable with RichText v1, v2 and v3.

The xEchoRichTextBox1 Sub clears a ListBox.. and then copies all lines from a RichTextBox into the ListBox. Additionally, it stores the RichTextBox line delineatred into an Array named strLineText. As it runs from an hWnd, you can modify the code to your purpose.. <smile>.

======================================

1. Start a New Standard.Exe Project.
2. Add a RichTextBox (RichTextBox1) and a ListBox (List1) to it.
3. Set the MultiLine property of the RichTextBox to True.
4. In the Form1 code window Copy/Paste the following.
5. Press F5 to Run. Anything placed in the RichTextBox is echoed into the ListBox.

<----- Code Begin ----->

Option Explicit

Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" _
   (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) _
   As Long

Private Sub Form_Load()

   With Form1
      .Left = Screen.Width * 0.1
      .Height = Screen.Height * 0.8
      .Top = Screen.Height * 0.1
      .Width = Screen.Width * 0.8
   End With

   With RichTextBox1
      .Left = Form1.ScaleWidth * 0.1
      .Height = Form1.ScaleHeight * 0.8
      .Top = Form1.ScaleHeight * 0.1
      .Width = Form1.ScaleWidth * 0.4
   End With

   With List1
      .BackColor = Form1.BackColor
      .Left = Form1.ScaleWidth * 0.5
      .Height = Form1.ScaleHeight * 0.8
      .Top = Form1.ScaleHeight * 0.1
      .Width = Form1.ScaleWidth * 0.45
   End With
   
   RichTextBox1.Text = "RichTextbox1: Enter Data Here"
   RichTextBox1.SelStart = Len(RichTextBox1.Text)
   
End Sub

Private Sub RichTextBox1_Change()
   
   xEchoRichTextBox1

End Sub

Private Sub xEchoRichTextBox1()
   
   Const EM_GETLINE = &HC4
   Const EM_GETLINECOUNT = &HBA
   Const EM_LINELENGTH = &HC1
   
   Dim lngLineCount As Long
   Dim lngLineLength As Long
   Dim lngLineNumber As Long
   Dim lngLinePosition As Long
   Dim strLineText() As String
   List1.Clear
   lngLineCount = SendMessageLong(RichTextBox1.hwnd, EM_GETLINECOUNT, 0, 0)
   ReDim strLineText(lngLineCount)
   For lngLineNumber = 0 To lngLineCount - 1
      lngLineLength = SendMessageLong(RichTextBox1.hwnd, EM_LINELENGTH, lngLinePosition, 0)
      strLineText(lngLineNumber) = Space(lngLineLength + 1)
      lngLinePosition = lngLinePosition _
         + SendMessageLong(RichTextBox1.hwnd, EM_GETLINE, lngLineNumber, strLineText(lngLineNumber))
      strLineText(lngLineNumber) = Left(strLineText(lngLineNumber), Len(strLineText(lngLineNumber)) - 1)
      List1.AddItem strLineText(lngLineNumber)
      List1.Selected(lngLineNumber) = True
   Next lngLineNumber

End Sub

<----- Code End ----->

0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
Well, after a little modification the code has worked. Thank you wsh2.

NOTE:  I have added the constant EM_LINEINDEX to determine the offset of the first character in the specified line of the edit control(rich text box). This needs to be referenced or the  EM_LINELENGTH call will not return the proper character length (and will call GPF if I might add) since EM_LINELENGTH determines the length of the line containing an offset in the edit control text string.

After the slight modification, the commands work perfectly. Thanks again wsh2


Private Sub xEchoRichTextBox1()
   
   Const EM_GETLINE = &HC4
   Const EM_GETLINECOUNT = &HBA
   Const EM_LINELENGTH = &HC1
   Const EM_LINEINDEX = &HBB  
 
   Dim lngLineCount As Long
   Dim lngLineLength As Long
   Dim lngLineNumber As Long
   Dim lngLinePosition As Long
   Dim strLineText() As String
   List1.Clear
   lngLineCount = SendMessageLong(RichTextBox1.hwnd, EM_GETLINECOUNT, 0, 0)
   ReDim strLineText(lngLineCount)
   For lngLineNumber = 0 To lngLineCount - 1
      lngLineIndex = SendMessageLong(RichTextBox1.hwnd,EM_LINEINDEX,lngLineNumber,0)
      lngLineLength = SendMessageLong(RichTextBox1.hwnd, EM_LINELENGTH, lngLineIndex, 0)
      strLineText(lngLineNumber) = Space(lngLineLength + 1)
      lngLinePosition = lngLinePosition _
         + SendMessageLong(RichTextBox1.hwnd, EM_GETLINE, lngLineNumber, strLineText(lngLineNumber))
      strLineText(lngLineNumber) = Left(strLineText(lngLineNumber), Len(strLineText(lngLineNumber)) - 1)
      List1.AddItem strLineText(lngLineNumber)
      List1.Selected(lngLineNumber) = True
   Next lngLineNumber

End Sub
0
 
LVL 2

Author Comment

by:orbitaltech
Comment Utility
P.S. to my last comment....

Dont forget the
Dim lngLineIndex as Long
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now