Link to home
Create AccountLog in
Avatar of Valleriani
VallerianiFlag for Sweden

asked on

VB.NET 2010 - WM_GETTEXT/WM_GETTEXTLENGTH on a RichTextBox, ability to get only the last line & update whenever the window updates? (SendMessage/GetWindow/etc)

I'm using something like this to get all the text in a RichTextBox of another window.. ChatWindowHandler = the hwnd of the richtextbox...

        Dim length As IntPtr = SendMessage(ChatWindowHandler, WM_GETTEXTLENGTH, Nothing, 0)
        Dim Hndl As IntPtr = Marshal.AllocHGlobal(length)
        Dim NumText As Integer = SendMessage(ChatWindowHandler, WM_GETTEXT, length, Hndl)

        'copy the characters from the unmanaged memory to a managed string
        TextBox1.Text = Marshal.PtrToStringUni(Hndl)

This works well for getting text from an external richtextbox window. However, what I want to do is get the last line submitted ONLY and add it to the textbox instead of always getting ALL the information.. Is that possible?

Also, is it possible to get text only when the richtextbox update (aka when text is added to the richtextbox?)

If both are not possible... How can I get new text with a timer? Have to note that the richtextbox is sometimes cleared, so it needs to be able to detect this..

Any ideas? Thanks!
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Use EM_GETLINECOUNT and EM_GETLINE:
http://msdn.microsoft.com/en-us/library/bb761586(VS.85).aspx
http://msdn.microsoft.com/en-us/library/bb761584(VS.85).aspx

It's not possible using straight VB.Net to get notified when the text changes.  To do that would require a language that supports external hooking like Delphi or C++.
Avatar of Valleriani

ASKER

I've been looking at EM_GETLINE,

I know

Dim lines As Integer = SendMessage(ChatWindowHandler, EM_GETLINECOUNT, 0&, 0&)

should work,

Dim lngLength = SendMessage(ChatWindowHandler, EM_LINELENGTH, lines - 1, 0&) ///<---This one doesn't seem to be working?
ReDim Buffer(lngLength + 1)
Buffer(0) = lngLength + 1
SendMessage(ChatWindowHandler, EM_GETLINE, lines, Buffer(0))

I think its the lngLength causing the issue because it seems to be returning the same value with any line.. Could be wrong about the EM_GETLINE too but I think it should be something like that anyways.
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Hi,

The EM_ constants don't automatically marshal across process boundries like the WM counterparts (WM_GETTEXT). You would have to add marshal code to get it to work for control handles in another process. In order to do that you would have to also use VirtualAllocEx, WriteProcessMemory, ReadProcessMemory. You have to allocate a buffer in the address space of the other process and pass the memory address to SendMessage instead of local buffering.
Actually that coding there was almost perfect, thanks!
Yeah I was wrong the EM_GETLINE is within the WM_USER range so it is marshaled correctly! I should have looked first at the value anything above WM_USER(&H400) doesn't perform default marshaling some of them include EM_STREAMOUT, EM_STREAMIN.