我用createprocess运行程序a.exe,然后用sendmessage向a.exe中的一个窗体(唯一的窗体)发送消息。
我现在用findwindow方法得到窗体的hwnd.但是我怕有多个程序运行,窗体的caption不唯一。
能否在用createprocess运行后,用其他的方法得到窗体的hmnd.
我现在用findwindow方法得到窗体的hwnd.但是我怕有多个程序运行,窗体的caption不唯一。
能否在用createprocess运行后,用其他的方法得到窗体的hmnd.
与createprocess最后一个参数
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
中的dwProcessId比较
有没有不用findwindow,而得到hmwd的方法呢。
CreateProcess(...., pi, ...);
::EnumWindows(&EnumWindowsProc, pi.threadid);
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param)
{DWORD id = GetWindowThreadProcessId(hwnd, NULL)
if (id == (DWORD)param)
{
//do whatever we want to do
return false;
}
return true;
}
遍历窗体, 直到找出想要的, 包括TextBox, CommandButton等等的句柄
GetDesktopWindow, GetTopWindow, GetNextWindow得到hwnd可以发送关闭程序的消息,但是发数据不可以,也不能修改标题(用setwindowText),但是用FindWindow得到的hwnd可以发送关闭程序的消息,也可以发送数据,也可以修改标题(用setwindowText).下面是我的接收的程序的模块:
Option ExplicitType COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type Public Const GWL_WNDPROC = (-4)
Public Const WM_COPYDATA = &H4A
Global lpPrevWndProc As Long
Global gHW As Long 'Copies a block of memory from one location to another. Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long) Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As _
Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As _
Long) As Long Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As _
Long) As Long Public Sub Hook()
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
AddressOf WindowProc)
Debug.Print lpPrevWndProc
End Sub Public Sub Unhook()
Dim temp As Long
temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
End Sub Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_COPYDATA Then
Call mySub(lParam)
frmRecieve.Print "hw:" & hw & " uMsg:" & uMsg & " wParam:" & wParam & " lparam:" & lParam
End If
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, _
lParam)
End Function Sub mySub(lParam As Long)
Dim cds As COPYDATASTRUCT
Dim buf(1 To 255) As Byte
Dim a As String
Call CopyMemory(cds, ByVal lParam, Len(cds)) Select Case cds.dwData
Case 1
Debug.Print "got a 1"
'frmRecieve.Print "got a 1"
frmRecieve.Label1.Caption = a$ & " time: " & Now
' If frmRecieve.Visible = False Then
' frmRecieve.Show
' Else
' frmRecieve.Hide
' End If
Case 2
Debug.Print "got a 2"
frmRecieve.Print "got a 2"
Case 3
Call CopyMemory(buf(1), ByVal cds.lpData, cds.cbData)
a$ = StrConv(buf, vbUnicode)
a$ = Left$(a$, InStr(1, a$, Chr$(0)) - 1)
frmRecieve.Label1.Caption = a$ & " time: " & Now
End Select
End Sub
Public Sub Main()
Dim strTitle As String
strTitle = Command()
'MsgBox strTitle
If strTitle <> "" Then
frmRecieve.Caption = strTitle
Else
frmRecieve.Caption = "Target0"
End If
End Sub
下面是发送端的程序:' Return information about this window.
Private Sub GetWindowInfo(ByVal app_hWnd As Long, ByRef app_parent As Long, ByRef app_owner As Long, ByRef app_visible As Boolean, ByRef app_style As Long, ByRef app_text As String, ByRef app_class As String)
Const MAX_LENGTH = 1024Dim buf As String * MAX_LENGTH
Dim length As Long app_parent = GetParent(app_hWnd)
app_owner = GetWindowLong(app_hWnd, GWL_HWNDPARENT)
app_visible = IsWindowVisible(app_hWnd)
app_style = GetWindowLong(app_hWnd, GWL_STYLE) length = GetWindowText(app_hWnd, buf, MAX_LENGTH)
app_text = Left$(buf, length) length = GetClassName(app_hWnd, buf, MAX_LENGTH)
app_class = Left$(buf, length)
End SubPublic Function InstanceToWnd(ByVal target_pid As Long) As Long
Dim app_hWnd As Long
Dim app_parent As Long
Dim app_owner As Long
Dim app_visible As Boolean
Dim app_style As Long
Dim app_text As String
Dim app_class As String
Dim wid As Single
Dim col_wid() As Single
Dim r As Integer
Dim c As Integer
Dim test_pid As Long
Dim test_thread_id As Long GetWindowInfo app_hWnd, app_parent, app_owner, _
app_visible, app_style, app_text, app_class app_hWnd = GetTopWindow(0)
r = 1
Do While app_hWnd <> 0
' Get information about this window.
GetWindowInfo app_hWnd, app_parent, app_owner, _
app_visible, app_style, app_text, app_class ' See if this window is interesting.
If app_visible And _
app_parent = 0 And _
app_owner = 0 And _
Len(app_text) > 0 And _
Left$(app_text, 8) <> "VBBubble" And _
(Left$(app_class, 7) <> "Progman" Or _
(app_style And WS_OVERLAPPEDWINDOW) <> 0) _
Then
If GetParent(app_hWnd) = 0 Then
' This is a top-level window. See if
' it has the target instance handle.
test_thread_id = _
GetWindowThreadProcessId(app_hWnd, _
test_pid) If test_pid = target_pid Then
' This is the target.
InstanceToWnd = app_hWnd
Exit Do
End If
End If
r = r + 1
End If app_hWnd = GetNextWindow(app_hWnd, GW_HWNDNEXT)
Loop
End Function下面的好用的启动程序(用findwindow方法,不用sleep有时不能得到hwnd)
Dim cds As COPYDATASTRUCT
Dim buf(1 To 255) As Byte
Dim i As Long
Dim A As String
''''''''''''''''''''''''''''''''''''''''''''''''
Dim res&
sinfo.cb = Len(sinfo)
sinfo.lpReserved = vbNullString
sinfo.lpDesktop = vbNullString
sinfo.lpTitle = vbNullString
sinfo.dwFlags = 0
Label1.Caption = "ÕýÔÚÆô¶¯³ÌÐò"
Label1.Refresh
' CreateProcessº¯Êý£¬ÓÃÓÚ´´½¨Ò»¸öеĽø³Ì
'res = CreateProcess("Target.exe", vbNullString, ByVal 0&, ByVal 0&, 1&, NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, sinfo, pinfo)
res = CreateProcess(vbNullString, App.Path & "\Target.exe " & strTitle, ByVal 0&, ByVal 0&, 1&, NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, sinfo, pinfo)
'MsgBox res
If res Then
Label1.Caption = "³ÌÐòÕýÔÚÔËÐÐ"
Else
Label1.Caption = "³ÌÐòÔËÐÐerr"
End If
'ThWnd = pinfo.hProcess
A:
Sleep (100)
'MsgBox pinfo.hProcess & " " & pinfo.dwProcessID
'''''''''''''''''''''''''''''''''''''''''''''''
' Get the hWnd of the target application
ThWnd = FindWindow(vbNullString, strTitle)
Static ii As Integer
If ThWnd = 0 Then
ii = ii + 1
If ii < 100 Then
GoTo A:
End If
MsgBox strTitle & " ûÓÐÔËÐÐ"
Exit Sub
End If
' 'l MsgBox ThWnd
'ThWnd = pinfo.hProcess
res = CloseHandle(pinfo.hProcess)
'' a$ = "It Works!"
'' ' Copy the string into a byte array, converting it to ASCII
'' Call CopyMemory(buf(1), ByVal a$, Len(a$))
'' cds.dwData = 1
'' cds.cbData = Len(a$) + 1
'' cds.lpData = VarPtr(buf(1))
'' i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)
Dim h_wnd As Long
Dim buf As String
Dim buf_len As Long
Dim cds As COPYDATASTRUCT
Dim i As Long
Dim A As String
''''''''''''''''''''''''''''''''''''''''''''''''
Dim res&
sinfo.cb = Len(sinfo)
sinfo.lpReserved = vbNullString
sinfo.lpDesktop = vbNullString
sinfo.lpTitle = vbNullString
sinfo.dwFlags = 0
Label1.Caption = "ÕýÔÚÆô¶¯³ÌÐò"
Label1.Refresh
' CreateProcessº¯Êý£¬ÓÃÓÚ´´½¨Ò»¸öеĽø³Ì
'res = CreateProcess("Target.exe", vbNullString, ByVal 0&, ByVal 0&, 1&, NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, sinfo, pinfo)
res = CreateProcess(vbNullString, App.Path & "\Target.exe " & strTitle, ByVal 0&, ByVal 0&, 1&, NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, sinfo, pinfo) m_Pid = pinfo.dwProcessID
' Start the program.
' m_Pid = Shell(Text1.Text, vbNormalFocus)
If m_Pid = 0 Then
MsgBox "Error starting program"
Exit Sub
End If ' Get the window handle.
Sleep (100)
pCurrentPlayerHandle = InstanceToWnd(m_Pid)
MsgBox pCurrentPlayerHandle
ThWnd = pCurrentPlayerHandle
If ThWnd = 0 Then
MsgBox strTitle & " ûÓÐÔËÐÐ"
Exit Sub
End If
'SetWindowText pCurrentPlayerHandle, "The handle to Notepad is " ' & CStr(pCurrentPlayerHandle & vbNullChar)
' Display the program's caption.
buf = Space$(256)
buf_len = GetWindowText(pCurrentPlayerHandle, buf, Len(buf))
buf = Left$(buf, buf_len)
MsgBox buf
有两个与我的接收程序有关
一个是以我Target.exe文件名一致的,
000E05DC "Target"
另一个是与我的窗体同名(FindWindow 中用的窗体名)
000609EE "Target02"但是他们的Process ID,Thread ID 相同都是下面数值:
Process ID:00000720
Thread ID :00000520如果我用FindWindow的方法查找"Target02",得到的是000609EE
如果我用test_thread_id = _
GetWindowThreadProcessId(app_hWnd, _
test_pid)
方法得到的是000E05DC为什么不同呢。