Results 1 to 14 of 14

Thread: Retrieving Text from an external app?

  1. #1

    Thread Starter
    New Member
    Join Date
    Apr 2005
    Posts
    14

    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:
    1. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    2. 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
    3. 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
    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
    5.  
    6. Private Const WM_GETTEXT = &HD
    7. Private Const WM_SETTEXT = &HC
    8. Private Const EM_GETLINECOUNT = &HBA
    9.  
    10.  
    11.  
    12. Private Sub CMDGETEDIT_Click()
    13. Dim lNotepadHwnd As Long
    14. Dim lNotepadEdit As Long
    15. Dim sCaption As String * 256  '// YES A BUFFER
    16.  
    17.     lNotepadHwnd = FindWindow("POPUP_INT_DLG_WINDOW", vbNullString)
    18.     lNotepadEdit = FindWindowEx(lNotepadHwnd, 0&, "RichEdit20A", vbNullString)
    19.  
    20.    
    21.    
    22.    
    23.     SendMessageSTRING lNotepadEdit, WM_GETTEXT, 256, sCaption
    24.  
    25. txtNotepad.Text = sCaption
    26. 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

  2. #2
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    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

  3. #3

    Thread Starter
    New Member
    Join Date
    Apr 2005
    Posts
    14

    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

  4. #4
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    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

  5. #5

    Thread Starter
    New Member
    Join Date
    Apr 2005
    Posts
    14

    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

  6. #6
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: Retrieving Text from an external app?

    Well I'm working on it now. I couldn't find any documentation on it in VB so I'm having to convert it from C++

    Welcome to VBForums by the way Don't ever say we don't work hard for one another

  7. #7

    Thread Starter
    New Member
    Join Date
    Apr 2005
    Posts
    14

    Re: Retrieving Text from an external app?

    Thanks very much (for the welcome and the help) people seem friendly enough round here.

    Chris

  8. #8
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    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

  9. #9
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    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

  10. #10

    Thread Starter
    New Member
    Join Date
    Apr 2005
    Posts
    14

    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:
    1. SendMessage hWndNotepadEdit, EM_STREAMOUT, SF_RTF, udtStreamInfo

    The window closes itself!

    How strange.

    Chris

  11. #11
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    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?

  12. #12

    Thread Starter
    New Member
    Join Date
    Apr 2005
    Posts
    14

    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

  13. #13
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    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:
    1. dim i as integer, myStr as String
    2. myStr=""
    3. for i=0 to cb-1
    4.   myStr = myStr & chr(pbBuff(i))
    5. next i
    Try that

  14. #14
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    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
  •  



Click Here to Expand Forum to Full Width