Solved: SendMessage vs. SendKeys
In another thread, it was suggested that SendMessage could be used instead of SendKeys, e.g., to set the VBA Project Properties.
I started a thread on his topic very recently, but cannot find that thread, so here we go again.
I have found a way to get the handle of each of the fields in the VBA Project Properties dialog. To do this, one must first display the Project Properties dialog, then use the following code:
[vba]
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
strCaption = somedocobject.VBProject.Name & " - Project Properties".
lngHWnd - FindWindow(vbNullString, strCaption)
'Get Protection tab
SendKeys "^{TAB}": Sleep 50: DoEvents
EnumChildWindows lngHWnd, AddressOf EnumChildProc, ByVal 0&
[/vba]
Along with the following module:
[vba]
Option Explicit
Public Declare Function GetWindowText Lib "user32" _
Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
Public Declare Function GetWindowTextLength Lib "user32" _
Alias "GetWindowTextLengthA" _
(ByVal hwnd As Long) As Long
Public lngLockProject As Long
Public lngPassword As Long
Public lngConfirmPassword As Long
Public lngOK As Long
Public Function EnumChildProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
Dim strTemp As String
strTemp = Space$(GetWindowTextLength(hwnd) + 1)
GetWindowText hwnd, strTemp, Len(strTemp)
'remove Chr$(0)
strTemp = Left$(strTemp, Len(strTemp) - 1)
If strTemp <> "" Then
Debug.Print strTemp & " = " & hwnd
Select Case strTemp
Case "Lock project for &viewing"
lngLockProject = hwnd
Case "&Password"
lngPassword = hwnd
Case "&Confirm password"
lngConfirmPassword = hwnd
Case "OK"
lngOK = hwnd
End Select
End If
EnumChildProc = 1
End Function
[/vba]
Using the handles obtained supra, I tried a solution based on the code in MSFT KB article 176058.
In a VB 6 Form, I have the code below.
The handle passed to the sub is that of the Password field in a VBA Project
Properties dialog.
I get a message stating that the password is invalid but the cursor is where
it should be, i.e., in the Password field of the Project Properties dialog, with nothing getting inserted in the Password field.
I suspect that I am not using the COPYDATASTRUCT correctly or the string
being passed is not in a format required by VBA. I've also tried passing double byte strings, but got the same error message,
What am I missing, other than a good night's sleep?
[vba]
Private Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type
Private Const WM_COPYDATA = &H4A
Private Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName _
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
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
PrivateSub SendingApplication(strToSend As String, ThWnd As Long)
' strToSend: String to send
'ThWnd: hWnd of the target application
Dim i As Long
Dim cds As COPYDATASTRUCT
Dim buf(254) As Byte
Call CopyMemory(buf(0), ByVal strToSend, Len(strToSend))
cds.dwData = 3
cds.cbData = Len(strToSend) + 1
cds.lpData = VarPtr(buf(0))
i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)
Debug.Print ThWnd, i
End Sub
[/vba]