External Cut and paste problem

Megalith

Well-known member
Joined
Aug 21, 2006
Messages
66
Programming Experience
10+
is there a way i can Automatically cut and paste the contents of a regularly updating richtext box in an external application (manually cutting and pasting does work) while at the same time allowing the user to perform other tasks both within my application and other external applications(like chatting on yahoo)?

I have tried the following unsuccesfully:-

SendMessage API. the routine returned an empty string.

Performing mousemove and click commands to select text right click select copy move to my text box and paste it in it. this worked but prevented me from performing any other tasks on the computer

sending key commands. This worked in a way but the Alt-Tab would select the wrong window and again it meant i was unable to perform tasks like chat on yahoo.

The richtextbox in the external application is updated upto 5 times a second at times and at other times once in every 15 seconds or longer. what would be perfect would be a method to act when the box updates.

any suggestions? I've read & re-read the API-Guide and cant seem to find a routine that will perform this, what i presume to be, simple task.

The contents of the box are plain text of a standard font type and size with 2 colours red and black the background colour is like old printer-paper ie white/light green alternating lines. My application successfully determines the Hwnd property if i need it.
 
Been thinking more about this problem, perhaps theres a way to copy the region of memory that this text is stored? any information/pointers to information to do this would be greatly appreciated, I see that theres an API functioncalled CopyMemory but i have no idea where this controls contents are being stored.
 
You want to replace text in other applications ('remote') richtextbox? But how is remote text that continually updates selected? You can only Cut selected text. Also if remote text changes to when you will Paste back that will be a problem. Perhaps this also is not the case, and you only need to get text from remote? This is a little different code. Please clarify, and I will input some more.
 
Hey john thanks for the reply, ok i'll expand a bit. I need to obtain the text from a continually updating remote applications richtextbox, the local code will act on specific keywords that are generated by the remote Richtextbox, Specifically the keyword "Alert: "

The ideal solution would be to read this data as it is updated but i have no idea if it is possible to do this.

As i mentioned in the first thread SendMessage returns an empty string yet the text can be manually selected by single clicking a line (Maybe this isnt a RichTextBox?) then copied by right clicking and selecting copy(just right clicking will select the entire current line). Obviously this is no use because if i the user am sitting there i can see the message appear and act accordingly.

The method i wrote using mouse move selected the lastline and copied it by rightclicking near to the bottom right of the box then waiting for the menu to display, moving the mouse and clicking where copy would be. This worked but rendered the pc useless for any other task.

i have no need to paste onto the remote application only to obtain the details from this logbox

i know the ClassName of the box (and the container it is inside) and can determine its handle should i need to use this information.
 
You perhaps tried WM_GETTEXT with SendMessage before? Since you know the class name I think you would have known if it was a textbox (Edit) or richtextbox (RICHEDIT50W) because that's too obvious. So what is the class name? Btw, you can use LB_GETTEXT for Listboxes and LVM_GETITEMTEXT for listviews.
 
sadly the class is not named in a way to help identify what it is. Its named ftmlog, the container for it is named ftmlogframe which is no help at all, why i feel it might not be a textbox is that clicking a line selects the whole line.

i will try using the constants you suggest and try treating it as a listbox /view and let you know how i get on. yes i did use WM_GETTEXT btw. Is there a site which lists these constants? more usefully with the values included?
 
ftmlog? ftmlogframe? Never heard of them, and no results in web searches. You can double check with for example Winspector or similar Spy++ tool, Winspector displays class name while mouse over and also has got this 'aiming icon' you can drag right onto the control to select it. You could also try the RealGetWindowClass function to see if it is a subclassed common control registrered with a different name.

MSDN is the first reference for this stuff, it's not very available if you don't already know how it works, and the reference is for C++. If you search those constants it is usually one of the first hits in the list, and you can use the tree structure from one such article to find relevance. For example here WM_GETTEXT is very known to use for common windows, that article mention the listbox LB_GETTEXT, going to that article give you all the common controls in navigation treeview.
 
ok i tried the Winspector program and it confirmed that the 'box' is called ftmlog the properties show the following Styles:-

WS_CHILD, WS_VISABLE, WS_VSCROLL

and the following StylesEx:-
WS_EX_TRANSPARENT, WS_EX_LEFT, WS_EX_LTRREADING, WS_EX_RIGHTSCROLLBAR

and says it has an ID of 771

selecting Messages for this box in Winspector displays the following structure that is updated as the box is.

> (P) WM_USER + 111(0x0000046f)
wParam: 0x00020008
lParam: 0x00000099
> (S) WM_PAINT
> (S) WM_ERASEBKGND
< (S) WM_ERASEBKGND
< (S) WM_PAINT

where the < and > are used to represent arrows.

Does this help you at all? i need to read up on this program more i presume the (S) is SendMessage and the (P) is PostMessage. the only part of interest to me is the WM_USER + 111 section. Sometimes it is a WM_USER + 110 that is generated but these lines are of no use to me.
:confused:
 
No, doesn't tell me anything.

Note that the messages sent to the control window could give you the information or event notification about update, but it is not possible to write VB.Net code to hook another application.
 
ok i have a few questions relating to this.

If it cant be done with VB can it be done with C or assembly? or will i just have to accept defeat on this and rewrite the whole application?

how would i use the RealGetWindowClass in VB? some simple example could be useful

is it possible to multithread the mouse so effectively i have a mouse i can use and one the program does?

i find it hard to take that if i can copy from this box manually then i should be able to automate it somehow :(

presumably the memory where this external application stores this information would have a protected flag?

i looked over the routine i wrote using SendMessage:-

Public Function GetWindowText(ByVal WindowHandle As IntPtr) As String

Dim ptrRet As IntPtr
Dim ptrLength As IntPtr

'get length for buffer...
ptrLength = SendMessage(WindowHandle, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero)

'create buffer for return value...
Dim sbText As New System.Text.StringBuilder(ptrLength.ToInt32 + 1)

'get window text...
ptrRet = SendMessage(WindowHandle, WM_GETTEXT, ptrLength.ToInt32 + 1, sbText)

'get return value...
Return sbText.ToString

End Function


i found that the textlength is 0 if i use WM_GETTEXTLENGTH or LB_GETTEXTLENGTH
and hence why i am getting returned a Null String. is there a problem in this method? perhaps i should use Integer and not IntPtr?
:confused:
 
If it cant be done with VB can it be done with C or assembly? or will i just have to accept defeat on this and rewrite the whole application?
Hooking is unmanaged code only, any language but I have not seen this done with unmanaged .Net, you should be able to find compiled working hook dlls in C++ or VB6.
how would i use the RealGetWindowClass in VB? some simple example could be useful
VB.NET:
'declaration:
Declare Function RealGetWindowClass Lib "user32.dll" ( _
  ByVal hwnd As Int32, ByVal pszType As System.Text.StringBuilder, ByVal cchType As Int32) As Int32
'example:
Dim sb As New System.Text.StringBuilder(256)
RealGetWindowClass(hwnd, sb, 256)
MsgBox(sb.ToString)
is it possible to multithread the mouse so effectively i have a mouse i can use and one the program does?
No, mouse is system wide and shared, you can't create a new mouse instance that will function as a second system mouse.
i find it hard to take that if i can copy from this box manually then i should be able to automate it somehow :(
That could be the case.
presumably the memory where this external application stores this information would have a protected flag?
Reading the other applications memory would be searching in blindness in all its memory usage. Maybe this Code Project article is interesting for you: How to write a Memory Scanner using C#
i found that the textlength is 0 if i use WM_GETTEXTLENGTH or LB_GETTEXTLENGTH
and hence why i am getting returned a Null String.
My best guess is that this ftmlog control is user-drawn ie done privately in that application, when you click a line they detect it and draw it as selected, when you request a copy they copy the text to clipboard. This way they can protect themselves from prying automators by several ways, they could refuse to send text to clipboard with all messages except when a 'line' is selected with mousedown. Have you tried sending the control a WM_COPY message (without or with prior manual selection), then checking the contents of clipboard?
is there a problem in this method (SendMessage)? perhaps i should use Integer and not IntPtr?
Appears it doesn't matter, but IntPtr has got more specific tasks, Integer is the default declaration. Integer and IntPtr is both 4bytes on the 32bit platform.
 
i found a great article on hooking and successfully wrote a method to hook onto the USER + 110 routine but alas was still unable to obtain the actual text being displayed (i obtained the lparam and wparam properties displayed using winspector - hmmm can i use these in sendmessage in some way?) :( it has however provided me with a method to determine when the text has changed which is a good starting point. i should now be able to select and copy the text that has updated as it updates so i'll play about with what is happening when i manually select and copy.

i can send keycodes to the control to cut and paste but i dont know how i can 'trick' the box into thinking it has focus without clicking it. can that be done any other way than by clicking it or using Alt-Tab? and if it can be done would the user still be able to perform a task in another window that does have focus?
 
Back
Top