Sending text to NotePad! It sounds easy, doesn’t it? Well this is where things get tricky. With the introduction of the 32-bit application, Microsoft separated the memory space that each program uses to produce a more stable product. While a more stable product was the result, it also made accessing the memory space of another application harder. Using the Windows API, we have three options to send text to another application. The first method is to set the focus on the other application (NotePad in this case) and use SendKeys. This option is not a very good one because SendKeys is not supported by Vista and so any program that uses SendKeys will not work with the Vista operating system. So now we are left with two options. We can send keystrokes just as if we were typing the text into the Notepad. This requires a lot of code and may be the best options for some integrations, but it is way too much work for what we are doing. Now we are left with one last option (which is really two). It is the API SendMessage/PostMessage.
As with any API, we will have to make a declaration statement. Program declarations will go under the “Public Class” line but before any “Subs” or “Functions”. So lets add both the SendMessage and the PostMessage to our form.
- Code: Select all
Declare Function SendMessageAsString Lib "USER32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Declare Function PostMessage Lib "USER32" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
As we look at the SendMessage API, we see that it takes 4 inputs and returns an integer. The first input we need is the windows handle for the control to send the message to. Now is when the other tools start to come in handy. Some how we need to find the handle for the control inside of Notepad that the text goes in. Let’s start Notepad as well as both JK’s API Spy and AutoIt3 Window Spy (part of AutoHotKeys install).
Now we can see that both these spy programs give us similar information. We do notice that in JK’s the class name is “Edit” while in AutoIt3 the class name “Edit1”. What is the number for on the end? As you play with the window spy programs, you will see that a lot of times programs have multiple controls that are the same type. For instance, multiple buttons. The number at the end of the class name is the order in which it occurs when the controls are enumerated. In JK’s Spy, we can see that it is showing us the handle. So why not just hard code the handle 331008? Well every time a control is created, it is assigned a new handle. So the handle is never the same. Therefore we must find a way to get the handle each time.
JK’s API Spy has a code generator tab that can be used to create the code needed to find the handle, but that is not always going to be the best way.
- Code: Select all
Dim notepad As Long, editx As Long
notepad = FindWindow("notepad", vbNullString)
editx = FindWindowEx(notepad, 0&, "edit", vbNullString)
Added Declarations:
- Code: Select all
Declare Auto Function FindWindow Lib "USER32" Alias "FindWindow" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Declare Function FindWindowEx Lib "USER32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer
- Code: Select all
Dim notepad As Integer, editx As Integer
notepad = FindWindow("notepad", vbNullString)
editx = FindWindowEx(notepad, 0&, "edit", vbNullString)
MsgBox(editx.ToString)
- Code: Select all
Declare Function EnumChildWindows Lib "USER32" (ByVal hWndParent As Integer, ByVal lpEnumFunc As EnumChildWindowsCallback, ByVal lParam As Integer) As Integer
So we will create a function:
- Code: Select all
Private Function EnumChildWindowByClassName(ByVal ChildhWnd As Integer, ByVal lParam As Integer) As Integer
End Function
- Code: Select all
Delegate Function EnumChildWindowsCallback(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
- Code: Select all
Dim SFClassName As String
Dim SFClassIndex As Integer
Dim SFHnd As Integer
- Code: Select all
Declare Function GetClassName Lib "USER32" Alias "GetClassNameA" (ByVal hwnd As Integer, ByVal lpClassName As StringBuilder, ByVal cch As Integer) As Integer
- Code: Select all
Imports System.Text
- Code: Select all
Dim StringBufferLength As Integer = 255
Dim wClass As New StringBuilder(StringBufferLength)
- Code: Select all
GetClassName(ChildhWnd, wClass, StringBufferLength)
- Code: Select all
If wClass.ToString.ToLower = SFClassName.ToLower Then
End If
- Code: Select all
Dim SFClassHit As Integer
- Code: Select all
SFClassHit += 1
- Code: Select all
If SFClassHit = SFClassIndex Then
SFHnd = ChildhWnd
EnumChildWindowByClassName = 0
Exit Function
End If
- Code: Select all
EnumChildWindowByClassName = 1
- Code: Select all
Public Function GetSubFormByClassNameWithMWClassWithMWCaption(ByVal MainWindowClass As String, ByVal MainWindowCaption As String, ByVal SubFormClass As String, ByVal SubFormClassIndex As Integer) As Integer
End Function
- Code: Select all
SFHnd = 0
SFClassHit = 0
SFClassIndex = SubFormClassIndex
SFClassName = SubFormClass
- Code: Select all
EnumChildWindows(FindWindow(MainWindowClass, MainWindowCaption), AddressOf EnumChildWindowByClassName, 0)
GetSubFormByClassNameWithMWClassWithMWCaption = SFHnd
- Code: Select all
Dim EditHndl As Integer = GetSubFormByClassNameWithMWClassWithMWCaption("Notepad", "Untitled - Notepad", "Edit", 1)
MsgBox(EditHndl.ToString)




