Option Explicit Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Sub Form_Load() Dim WordApp As Word.Application Dim WordDoc As Word.Document Set WordApp = New Word.Application Set WordDoc = WordApp.Documents.Add WordApp.Visible = True Call SetParent(FindWindow("OpusApp", vbNullString), Me.Picture1.hWnd) WordApp.WindowState = wdWindowStateMaximizeEnd Sub 窗体内一个大的Picture1
给你一个好点的, 模块代码: Option ExplicitPublic Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _ ByVal wCmd As Long) As Long Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 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 GetWindowThreadProcessId Lib "user32" _ (ByVal hwnd As Long, lpdwprocessid As Long) As Long Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long'Public Const WM_CLOSE = &H10 Public Const GW_HWNDNEXT = &H2 Function ProcIDFromWnd(ByVal hwnd As Long) As Long Dim idProc As Long GetWindowThreadProcessId hwnd, idProc ProcIDFromWnd = idProc End Function Function GetWinHandle(hInstance As Long, ByRef RetArr As Variant, Optional ByVal bExit As Boolean = True) As Long Dim tempHwnd As Long, RetCount As Long tempHwnd = FindWindow(vbNullString, vbNullString) RetCount = 0 Do Until tempHwnd = 0 If GetParent(tempHwnd) = 0 Then If hInstance = ProcIDFromWnd(tempHwnd) Then GetWinHandle = tempHwnd ReDim Preserve RetArr(RetCount) As Long RetArr(RetCount) = tempHwnd RetCount = RetCount + 1 If bExit Then Exit Do End If End If End If tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT) Loop End Function 窗体代码:放一个按钮上去 Command1 Private Sub Command1_Click() Dim hInst As Long ' Instance handle from Shell function. Dim hWndApp As Long ' Window handle from GetWinHandle. Dim buffer As String ' Holds caption of Window. Dim numChars As Integer ' Count of bytes returned. Dim hWndArr() As Long Dim i As Long ' Shell to an application hInst = Shell("C:\Program Files\Microsoft Office\Office10\winword.EXE",1)'启动Word ' Begin search for handle Call GetWinHandle(hInst, hWndArr(), False) For i = 0 To UBound(hWndArr) - 1 If hWndArr(i) <> 0 Then ' Init buffer buffer = Space$(128) ' Get caption of window numChars = GetWindowText(hWndArr(i), buffer, Len(buffer)) 'MsgBox numChars ' Display window's caption 'MsgBox "You shelled to the Application: " & Left$(buffer, numChars) Dim WinWnd As Long '从Caption关闭程序,pid也行 WinWnd = FindWindow(vbNullString, Trim(Left$(buffer, numChars))) If WinWnd <> 0 Then SetParent WinWnd, Me.hwnd 'MsgBox WinWnd 'PostMessage WinWnd, WM_CLOSE, 0&, 0& ' Else ' MsgBox "No window of that name exists." End If End If Next i End Sub///几点情况没注意到 这样给你解释吧,对于函数 Function GetWinHandle(hInstance As Long, ByRef RetArr As Variant, Optional ByVal bExit As Boolean = True) As Long 像Word,Excel一些多文档,多窗口程序调用的时候试着把bExit设为 false,那么返回的结果就保存到RetArr数组里面了,调用方法见给你的例子.还有一点点没完成,对于Notepad,计算器等一样的程序就把bExit设为True,这样循环比较次数少,算法复杂度低,结果还是在RetArr中返回,不过,RetArr只有一个值,而前者有多个. 实质上是:在函数中使用FindWindow和GetWindow取到的是当前Windows中所有的句柄,而可能多个句柄对应一个PID,PID是唯一的(当然,好象有不唯一的情况,不去考虑),你的Word启动返回一个Pid,通过比较PID找到WORD的句柄,然后设置父窗体,其他句柄造成的PID与WORD相同的情况,其位置均在WORD上.就是说 所有不同句柄造成相同PID,其中必有一个"父句柄",其他句柄的位置都在该父句柄上 呵呵,不知道说清楚了没
setparent(findwindow("OpusApp","文档 1 - Microsoft Word"),me.hwnd)
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Sub Form_Load()
Dim WordApp As Word.Application
Dim WordDoc As Word.Document
Set WordApp = New Word.Application
Set WordDoc = WordApp.Documents.Add
WordApp.Visible = True
Call SetParent(FindWindow("OpusApp", vbNullString), Me.Picture1.hWnd)
WordApp.WindowState = wdWindowStateMaximizeEnd Sub
窗体内一个大的Picture1
改后面的参数就ok了
模块代码:
Option ExplicitPublic Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
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 GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, lpdwprocessid As Long) As Long
Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long'Public Const WM_CLOSE = &H10
Public Const GW_HWNDNEXT = &H2
Function ProcIDFromWnd(ByVal hwnd As Long) As Long
Dim idProc As Long
GetWindowThreadProcessId hwnd, idProc
ProcIDFromWnd = idProc
End Function
Function GetWinHandle(hInstance As Long, ByRef RetArr As Variant, Optional ByVal bExit As Boolean = True) As Long
Dim tempHwnd As Long, RetCount As Long
tempHwnd = FindWindow(vbNullString, vbNullString)
RetCount = 0
Do Until tempHwnd = 0
If GetParent(tempHwnd) = 0 Then
If hInstance = ProcIDFromWnd(tempHwnd) Then
GetWinHandle = tempHwnd
ReDim Preserve RetArr(RetCount) As Long
RetArr(RetCount) = tempHwnd
RetCount = RetCount + 1
If bExit Then
Exit Do
End If
End If
End If
tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
Loop
End Function
窗体代码:放一个按钮上去 Command1
Private Sub Command1_Click()
Dim hInst As Long ' Instance handle from Shell function.
Dim hWndApp As Long ' Window handle from GetWinHandle.
Dim buffer As String ' Holds caption of Window.
Dim numChars As Integer ' Count of bytes returned.
Dim hWndArr() As Long
Dim i As Long
' Shell to an application
hInst = Shell("C:\Program Files\Microsoft Office\Office10\winword.EXE",1)'启动Word
' Begin search for handle
Call GetWinHandle(hInst, hWndArr(), False)
For i = 0 To UBound(hWndArr) - 1
If hWndArr(i) <> 0 Then
' Init buffer
buffer = Space$(128)
' Get caption of window
numChars = GetWindowText(hWndArr(i), buffer, Len(buffer))
'MsgBox numChars
' Display window's caption
'MsgBox "You shelled to the Application: " & Left$(buffer, numChars)
Dim WinWnd As Long
'从Caption关闭程序,pid也行
WinWnd = FindWindow(vbNullString, Trim(Left$(buffer, numChars)))
If WinWnd <> 0 Then
SetParent WinWnd, Me.hwnd
'MsgBox WinWnd
'PostMessage WinWnd, WM_CLOSE, 0&, 0&
' Else
' MsgBox "No window of that name exists."
End If
End If
Next i
End Sub///几点情况没注意到
这样给你解释吧,对于函数
Function GetWinHandle(hInstance As Long, ByRef RetArr As Variant, Optional ByVal bExit As Boolean = True) As Long
像Word,Excel一些多文档,多窗口程序调用的时候试着把bExit设为 false,那么返回的结果就保存到RetArr数组里面了,调用方法见给你的例子.还有一点点没完成,对于Notepad,计算器等一样的程序就把bExit设为True,这样循环比较次数少,算法复杂度低,结果还是在RetArr中返回,不过,RetArr只有一个值,而前者有多个.
实质上是:在函数中使用FindWindow和GetWindow取到的是当前Windows中所有的句柄,而可能多个句柄对应一个PID,PID是唯一的(当然,好象有不唯一的情况,不去考虑),你的Word启动返回一个Pid,通过比较PID找到WORD的句柄,然后设置父窗体,其他句柄造成的PID与WORD相同的情况,其位置均在WORD上.就是说 所有不同句柄造成相同PID,其中必有一个"父句柄",其他句柄的位置都在该父句柄上
呵呵,不知道说清楚了没