|
-
Apr 25th, 2005, 10:07 PM
#1
Thread Starter
New Member
Retrieving Text from an external app?
Hi, i'm having some trouble with the following code i used from an example and then ammended could someone help me please?
VB Code:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessageSTRING Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
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 Const WM_GETTEXT = &HD
Private Const WM_SETTEXT = &HC
Private Const EM_GETLINECOUNT = &HBA
Private Sub CMDGETEDIT_Click()
Dim lNotepadHwnd As Long
Dim lNotepadEdit As Long
Dim sCaption As String * 256 '// YES A BUFFER
lNotepadHwnd = FindWindow("POPUP_INT_DLG_WINDOW", vbNullString)
lNotepadEdit = FindWindowEx(lNotepadHwnd, 0&, "RichEdit20A", vbNullString)
SendMessageSTRING lNotepadEdit, WM_GETTEXT, 256, sCaption
txtNotepad.Text = sCaption
End Sub
The trouble i'm having is that it works fine for a short while (probably about 5-10 secs) then it just returns nothing i.e the txtnotepad textbox is empty.
EDIT - Sorry forgot to add that it returns blank until i close the external application's window and then reopen it again then the problem repeats -
Any ideas?
Chris
Last edited by cado1982; Apr 25th, 2005 at 10:10 PM.
Reason: Addition
-
Apr 26th, 2005, 06:38 AM
#2
Re: Retrieving Text from an external app?
I couldn't reproduce your problem, but I edited it to make it work with normal Notepad. Have fun
Code:
Private Sub cmdGetEdit_Click()
Dim lNotepadHwnd As Long
Dim lNotepadEdit As Long
Dim sCaption As String
Dim lngChars As Long
sCaption = String$(255, 0)
' Get Notepad hWnd
lNotepadHwnd = FindWindow("Notepad", vbNullString)
' Get Notepad's text box hWnd
lNotepadEdit = FindWindowEx(lNotepadHwnd, 0, "Edit", vbNullString)
' Get the buffer size and the text
lngChars = SendMessageSTRING(lNotepadEdit, WM_GETTEXT, 255, sCaption)
' Trim buffer to length of text
sCaption = Left$(sCaption, lngChars)
txtNotepad.Text = sCaption
End Sub
-
Apr 26th, 2005, 07:15 AM
#3
Thread Starter
New Member
Re: Retrieving Text from an external app?
Ok, thanks for that it helped me find the problem by stepping through your new commented code
The problem is that the text in the text box exceeds the length of the string (255) and then it just returns 0.
I'm not sure how to make the string a larger size as when i change wParam in the SendMessageSTRING function it says it's not an optional argument.
Any ideas?
Chris
-
Apr 26th, 2005, 07:39 AM
#4
Re: Retrieving Text from an external app?
Well when I tested it with a 128 char buffer and a humungously long string in Notepad, it still returned the 1st 128 characters.
from MSDN
Rich Edit: If the text to be copied exceeds 64K, use either the EM_STREAMOUT or EM_GETSELTEXT message.
I see in your code it says RichEdit... maybe we should try this.
It involves a callback function, they're always fun
-
Apr 26th, 2005, 08:05 AM
#5
Thread Starter
New Member
Re: Retrieving Text from an external app?
Yes it's definately a Rich Text Box so that is probably the problem right?
I did a few searches of EM_STREAMOUT but i couldn't find anything fruitful.
Any ideas what the call might look like?
Thanks again
Chris
-
Apr 26th, 2005, 08:07 AM
#6
-
Apr 26th, 2005, 08:20 AM
#7
Thread Starter
New Member
Re: Retrieving Text from an external app?
Thanks very much (for the welcome and the help) people seem friendly enough round here.
Chris
-
Apr 26th, 2005, 08:52 AM
#8
Re: Retrieving Text from an external app?
I have to admit, although everything else is straightforward enough, the actual contents of the callback function are a little beyond me at the moment To be more precise, converting a byte buffer to a string...
But anyway, here's what I got so far and since I don't know what you are using it on I can't really test it... Until I try and to it to WordPad
Put this in your form along with a RichEdit control called rtfEdit.
Code:
Option Explicit
'#define EM_STREAMOUT (WM_USER + 74)
'Public Const WM_USER As Long = &H400
Private Const WM_GETTEXT As Long = &HD
'Private Const WM_SETTEXT As Long = &HC
'Private Const EM_GETLINECOUNT As Long = &HBA
Private Const EM_STREAMOUT As Long = 1098 ' &H400 + 74
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) _
As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) _
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
'
'' Message EM_STREAMOUT
''
''----------- DESCRIPTION FROM MSDN (edited) -----------
'Parameters
'
' wParam
' Specifies the data format and replacement options.
'
' This value must be one of the following values.
'
' SF_RTF
' Rich Text Format (RTF).
' SF_RTFNOOBJS
' RTF with spaces in place of Component Object Model (COM) objects.
' SF_TEXT
' Text with spaces in place of COM objects.
' SF_TEXTIZED
' Text with a text representation of COM objects.
'
' The SF_RTFNOOBJS option is useful if an application stores COM objects itself,
' as RTF representation of COM objects is not very compact. The control word,
' \objattph, followed by a space denotes the object position.
'
' lParam
' Pointer to an EDITSTREAM structure. On input, the pfnCallback member of this
' structure must point to an application–defined EditStreamCallback function.
' On output, the dwError member can contain a nonzero error code if an error occurred.
'
Private Sub cmdGetEdit_Click()
Dim hWndNotepad As Long
Dim hWndNotepadEdit As Long
Dim udtStreamInfo As EDITSTREAM
Dim lngTextlen As Long
Dim strText As String
' Get hWnd
hWndNotepad = FindWindow("POPUP_INT_DLG_WINDOW", vbNullString)
' Get rich edit hWnd
hWndNotepadEdit = FindWindowEx(hWndNotepad, 0, "RichEdit20A", vbNullString)
' Set the info for the stream-out
With udtStreamInfo
.dwCookie = 0 ' No use to us
.dwError = 0 ' ditto (so far :D)
' Callback function
.pfnCallback = GetAddress(AddressOf EditStreamCallBack)
End With
' Start the callback
Set ghTextBox = rtfText
SendMessage hWndNotepadEdit, EM_STREAMOUT, SF_RTF, udtStreamInfo
' Now check for an error code
If (udtStreamInfo.dwError) Then
MsgBox "Error ID " & udtStreamInfo.dwError & " occured", vbExclamation
Else ' If there was no error,
' copy the contents of the buffer into
' the RTF Edit control
rtfText.TextRTF = gstrBuffer
End If
End Sub
'
see next post
Last edited by penagate; Apr 26th, 2005 at 08:55 AM.
Reason: stuffed up one of the constants
-
Apr 26th, 2005, 08:54 AM
#9
Re: Retrieving Text from an external app?
and this in a module
Code:
Option Explicit
'#define SF_TEXT 0x0001
'#define SF_RTF 0x0002
'#define SF_RTFNOOBJS 0x0003 // Write only
'#define SF_TEXTIZED 0x0004 // Write only
Public Const SF_TEXT As Long = 1
Public Const SF_RTF As Long = 2
Public Const SF_RTFNOOBJS As Long = 3
Public Const SF_TEXTIZED As Long = 4
'typedef struct _editstream
'{
' DWORD_PTR dwCookie; // User value passed to callback as first parameter
' DWORD dwError; // Last error
' EDITSTREAMCALLBACK pfnCallback;
'} EDITSTREAM;
Public Type EDITSTREAM
dwCookie As Long ' App-defined value
dwError As Long ' Error code (if/when applicable)
pfnCallback As Long ' Address of callback function
End Type
Public ghTextBox As RichTextBox ' Reference to textbox to put text in
'
'When you send an EM_STREAMOUT message, the rich edit control makes repeated calls to the
'EditStreamCallback function specified by the pfnCallback member of the EDITSTREAM
'structure. Each time it calls the callback function, the control passes a buffer containing
'a portion of the contents of the control. This process continues until the control has
'passed all its contents to the callback function, or until an error occurs.
'Parameters
'dwCookie
' [in] Value of the dwCookie member of the EDITSTREAM structure.
' The application specifies this value when it sends the EM_STREAMIN or EM_STREAMOUT message.
'pbBuff
' [in] Pointer to a buffer to read from or write to.
' For a stream-in (read) operation, the callback function
' fills this buffer with data to transfer into the rich edit control.
' *********:
' For a stream-out (write) operation, the buffer contains data from
' the control that the callback function writes to some storage.
'cb
' [in] Number of bytes to read or write.
'pcb
' [in] Pointer to a variable that the callback function sets to
' the number of bytes actually read or written.
'Return Value
'
' The callback function returns zero to indicate success.
'
' The callback function returns a nonzero value to indicate an error.
' If an error occurs, the read or write operation ends and the rich
' edit control discards any data in the pbBuff buffer. If the callback
' function returns a nonzero value, the rich edit control uses the
' dwError member of the EDITSTREAM structure to pass the value back to
' the application.
'
'Remarks
'
' The control calls the callback function repeatedly, transferring a portion
' of the data with each call. The control continues to call the callback
' function until one of the following conditions occurs:
'
' * The callback function returns a nonzero value.
' * The callback function returns zero in the * pcb parameter.
' * An error occurs that prevents the rich edit control from transferring
' data into or out of itself. Examples are out-of-memory situations,
' failure of a system function, or an invalid character in the read buffer.
' * For a stream-in operation, the RTF code contains data specifying the end of an RTF block.
' * For a stream-in operation on a single-line edit control, the callback
' reads in an end-of-paragraph character (CR, LF, VT, LS, or PS).
'typedef DWORD (CALLBACK *EDITSTREAMCALLBACK)(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
Public Function EditStreamCallBack(ByVal dwCookie As Long, _
ByVal pbBuff As Byte, _
ByVal cb As Long, _
ByRef pcb As Long) _
As Long '{
' pbBuff = pointer to a string buffer
Dim strBuffer As String
Dim strRTFText As String
Dim i As Long
' Set buffer size
strBuffer = String$(cb, 0)
' Get the string contents
For i = 0 To cb
strBuffer = strBuffer & ChrB$((Mid(pbBuff, i, 1)))
Next i
' Set the no. of bytes received
pcb = pcb + i
' Add buffer to text box
strRTFText = ghTextBox.TextRTF & strBuffer
ghTextBox.TextRTF = strRTFText
' Return zero to allow continuation of callback
EditStreamCallBack = 0
' }
End Function
'
'DWORD __stdcall MEditStreamOutCallback( DWORD dwCookie,
' LPBYTE pbBuff,
' LONG cb,
' LONG *pcb)
'{
' CString sThisWrite;
' sThisWrite.GetBufferSetLength(cb);
'
' CString *psBuffer = (CString *)dwCookie;
'
' for (int i=0;i<cb;i++) {
' sThisWrite.SetAt(i,*(pbBuff+i));
' }
'
' *psBuffer += sThisWrite;
'
' *pcb = sThisWrite.GetLength();
' sThisWrite.ReleaseBuffer();
' return 0;
'}
'
' A seemingly pointless function, used in conjuction with
' AddressOf operator in order to return the address of
' a function (in this case our callback routine above) :
Public Function GetAddress(ByVal plngAddress As Long) As Long
GetAddress = plngAddress
End Function
'
Hopefully you or someone else wiser than me can make some sense of it
-
Apr 26th, 2005, 09:24 AM
#10
Thread Starter
New Member
Re: Retrieving Text from an external app?
Ok, that was complicated! 
The problem we have now is that whenever this line is run
VB Code:
SendMessage hWndNotepadEdit, EM_STREAMOUT, SF_RTF, udtStreamInfo
The window closes itself!
How strange.
Chris
-
Apr 26th, 2005, 09:47 AM
#11
Re: Retrieving Text from an external app?
Haha... sounds just like typical API programming
Which window closes... VB or the notepad thing?
And also, what program is it that you are trying to capture the text from?
-
Apr 26th, 2005, 12:46 PM
#12
Thread Starter
New Member
Re: Retrieving Text from an external app?
It's the external app that closes.
It's a online poker room but it doesn't let me save the hand history in the software so i'm trying to write my own app that saves it and organises it automatically.
Thanks again
Chris
-
Apr 26th, 2005, 06:30 PM
#13
Re: Retrieving Text from an external app?
There are some problems with your EditStreamCallback Function
The second parameter you have defined as ByVal Byte.
It is a long pointer to a byte array so that you should either define it as
ByVal pbBuff as Long
or
pbBuff() as Byte
If you choose the second option you can form your string like this
VB Code:
dim i as integer, myStr as String
myStr=""
for i=0 to cb-1
myStr = myStr & chr(pbBuff(i))
next i
Try that
-
Apr 27th, 2005, 12:14 AM
#14
Re: Retrieving Text from an external app?
Thanks, moeur, at least you know what you're doing
Made a couple of mistakes in my code (obviously)
In the form code
Code:
If (udtStreamInfo.dwError) Then
MsgBox "Error ID " & udtStreamInfo.dwError & " occured", vbExclamation
Else ' If there was no error,
' copy the contents of the buffer into
' the RTF Edit control
rtfText.TextRTF = gstrBuffer
End If
should be
Code:
If (udtStreamInfo.dwError) Then
MsgBox "Error ID " & udtStreamInfo.dwError & " occured", vbExclamation
End If
and in the module code, as moeur pointed out
Code:
Public Function EditStreamCallBack(ByVal dwCookie As Long, _
pbBuff() As Byte, _
ByVal cb As Long, _
ByRef pcb As Long) _
As Long '{
' pbBuff = pointer to byte array (thanks moeur :)
Dim strBuffer As String
Dim strRTFText As String
Dim i As Long
' Get the string contents
For i = 0 To (cb - 1)
strBuffer = strBuffer & Chr$(pbBuff(i))
Next i
' Set the no. of bytes received
pcb = pcb + cb
' Add buffer to text box
strRTFText = ghTextBox.TextRTF & strBuffer
ghTextBox.TextRTF = strRTFText
' Return zero to allow continuation of callback
EditStreamCallBack = 0
' }
End Function
hope this gets a bit further
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|