I have an MS Access
form that contains Button
to open an application. The application is created using c#
. I want to get the TextBox
in the Form so that I will set a value on it using the MS Access project.
I am using the following code:
hwndParent = FindWindow(vbNullString, "Form1")
If hwndParent <> 0 Then
TextBoxHandle = FindWindowEx(hwndParent, 0&, "WindowsForms10.EDIT.app.0.3cb5890_r6_ad1", vbNullString)
SendMessage TextBoxHandle, WM_SETTEXT, 0&, ByVal strText
End If
Above code is working on my workstation: Windows 10 Pro.
When I open the MS Access in windows 8. it can't find the TextBox
.
TextBoxHandle
always return 0 in Windows 8. I am sure that the issue is with 3rd parameter in FinWindowEx
. I used spy++
from Microsoft to get the value WindowsForms10.EDIT.app.0.3cb5890_r6_ad1
cause when I try to just enter "Edit"
, it does not work.
Edit: Adjusted answer using information about dynamic name of class from Hans Passant.
First, we're going to declare WinAPI functions to be able to iterate through all windows and get their class name.
Then, we're going to declare a helper function to get the class name from a hWnd:
Then, we're going to iterate through all top-level windows, and return the hWnd from the one matching that class name:
Old answer:
There are numerous things that can go wrong when calling WinAPI functions from VBA with strings. These include passing a string that's not terminated by a null string, and passing a string that's in the wrong encoding.
For that first case, you get unstable behavior. If the string happens to be stored somewhere where there are a lot of zero's in memory, it works. Else, it continues reading bytes from memory and appending them to the string until it finds two bytes that happen to both be 0.
The first case is easily fixed by appending a null character to the end of your string:
Note that you should probably also make that last argument optional. Entering
vbNullString
there passes a pointer to a zero-length string, that might also not be delimited by a null character, causing WinAPI to read subsequent characters till it finds 2 null bytes. Setting the type toLongPtr
and passing 0 (the default value) passes an actual null pointer, which WinAPI expects when no string gets put in.The second code is more difficult. I tend to use bytearrays to make sure VBA doesn't do weird things
The corresponding declaration of FindWindowExW:
To debug problems and identify specific windows, I use the following function to iterate through all top and child windows, instead of Spy++. This one has the advantage of running in VBA, so you can set breakpoints and watches, which means you can very easily determine the class name and parent window of all open windows:
This uses the following 2 helper functions:
Corresponding WinAPI declarations for that sub:
Running this function with a watch on that class name should help you identify if it's top-level or a child window, and if it's a child window, which class it belongs to. You can also modify it to return the hWnd independent of nesting (by using an
If getWindowClass = "WindowsForms10.EDIT.app.0.3cb5890_r6_ad1" Then
or by checking the title).I think you should use Spy to conduct the same investigations on Windows 8 as you (presumably) did on Windows 10. Something must be different there, else your code would work.
Sidenote (because it bit me in the past): make sure you run the version of Spy whose 'bitness' (32 bit / 64 bit) matches the application you're interested in, otherwise message logging doesn't work.
Also, sorry for my previous post, it was a load of cr@p.
Edit Ah ha! Hans comments above that the class name is dynamically generated, so that's your problem. So now we know.