用FindWindow找到窗口句柄,再用Sendmessage将其关闭!

解决方案 »

  1.   

    看看我的问题,句柄已经找到,用了几个API都不能成功关闭。
      

  2.   

    看看在CSDN找到的这篇有用吗??
      
        外部檔案的執行及終止
     
     請問VB5是用shell來執行外部檔案,那執行後,要怎樣用VB的語法來終止此檔案的執行呢!?老怪答:Dim FHandle As Variant '(儲存視窗代碼的變數Private Sub Command1_Click()
    FHandle = Shell("C:\WIND98\CALC.EXE", 1) '(開啟外部執行檔)
    End SubPrivate Sub Command2_Click()
    AppActivate FHandle '讓先前開啟的視窗取得焦點。
    SendKeys "%{f4}", True '送出 [Alt]+[F4] Windows 系統的關閉組合鍵。
    End Sub改寫成能處理錯誤的呼叫函數則如下:開啟 Windows 應用程式
    'varAppName 是程式路徑及名稱之傳遞參數
    'varWinState 是應用程式視窗開啟狀態,設定方式請參考 Shell
    '的 WindowsStyle 說明
    Private Function OpenApp(ByVal varAppName As String, _
    Optional ByVal varWinState As Integer)
    '傳回應用程式之視窗代碼
    Dim varWinTitle As Variant'錯誤處理
    On Error GoTo OpenAppErrvarWinTitle = Shell(varAppName, varWinState)
    OpenApp = varWinTitle
    Exit FunctionOpenAppErr:
    Select Case Err.Number
    Case 53
    MsgBox "程式路徑或名稱錯誤", vbOKOnly, "開啟應用程式"
    End Select
    End Function'關閉 Windows 應用程式
    'varWinTitle 是開啟程式時 Windows 系統給的代碼
    Private Sub CloseApp(ByVal varWinTitle As Variant)'錯誤處理
    On Error GoTo CloseAppErrAppActivate varWinTitle
    '用 SendKeys 陳述模擬鍵盤 [ALT]+[F4]
    SendKeys "%{F4}"
    Exit SubCloseAppErr:
    Select Case Err.Number
    Case 5
    MsgBox "程式視窗已被關閉", vbOKOnly, "關閉應用程式"
    End Select
    End Sub'上面是改寫 Shell 和 AppActivate 的兩個函數,呼叫方式如下:'宣告一個儲存視窗代碼的變數
    Private WinTitle As Variant'開程式
    Private Sub Command1_Click()
    Dim AppName As StringAppName = "你的程式路徑及名稱"
    WinTitle = OpenApp(AppName)
    End Sub'關程式
    Private Sub Command2_Click()
    CloseApp WinTitle
    End Sub 
       
     
      
     
    ShellExecute能不能也这样类似得处理?
      

  3.   

    这种方法对多媒体类的程序好像不管用,我的视频采集程序正在工作时如果按
    ALT+F4方式关闭就会出现内存不能读错误。这是为何呀,急死我了
      

  4.   

    不行呀
    enumchildwindows这个API如何用?谁有例子
    我的视频采集程序上有一个退出按钮,只有按退出按钮或CTRL+ALT+DEL组合键结束进程才能正常关闭。
    那位大侠能解决此问题另外开问题奖励200分。
      

  5.   

    新思路,我在视频采集程序的退出按钮上设置一个快捷键ALT+X就可以安全退出。
    现在我该如何向窗体发送ALT+X这个组合键,我没做过,应该不是很难。
    第一个提供正确答案的这里的100分全是你的。
      

  6.   

    先在你的程序中激活采集程序,然后用sendkeys,看如下示例:SendKeys 语句示例
    本示例使用 Shell 函数来运行 Microsoft Windows 所附的计算器程序;然后使用 SendKeys 语句来按下计算器的某些数字键,最后退出计算器。(若要观察示例运行过程,可将示例粘贴到过程中,再运行过程即可。因为 AppActivate 会将焦点转移到计算器应用程序,故本示例不能以单步方式来运行。)。Dim ReturnValue, I
    ReturnValue = Shell("Calc.EXE", 1)   ' 运行计算器。
    AppActivate ReturnValue    ' 激活计算器。
    For I = 1 To 100   ' 设置计数循环。
       SendKeys I & "{+}", True   ' 按下按键给计算器
    Next I   ' 将所有 I 值相加。
    SendKeys "=", True   ' 取得总合。
    SendKeys "%{F4}", True   ' 按 ALT+F4 关闭计算器。
      

  7.   

    你的只要sendkeys "%X",true  就可以了,具体用法还可以看看msdn有关内容。
      

  8.   

    请尝试改一下次序,把setparent retval,me.hwnd 这句放到CmdQuit_Click()里,别的不改。
      

  9.   

    appativate returnvalue 提示无效的过程调用或参数
      

  10.   

    在CmdQuit_Click()里别的什么也不用写,就把SetParent retval,me.hwnd 加上去,看行吗? 那个retval要是全局变量要不,既然你得到了captureUp.exe的句柄,你可以用得到的这个句柄,再调用一次FindWindowEx(retval, 0, vbNullString, "退出按钮的caption"),其返回值就是该退出按钮的句柄,也不需要用什么EnumChildWindows的。利用得到的该句柄,发送BM_CLICK消息
    SendMessage(退出按钮句柄,&HF5,0,0)
    试试看?
      

  11.   

    麻烦,
    根据一开始的思路,
    直接用PostQuitMessage
    或用PostMessage发送WM_QUIT不就行了?
    再说,为什么你要SetParent?
    如在不同的进程或许可用PostThreadMessage尝试,注意要获得ThreadID,而不是你已得到的Handle。
    建议找API-Guide看看。
      

  12.   

    还有
    SetParent是不是最后要还原
      

  13.   

    请确认是否的确得到了captureUp.exe的句柄,可以加上debug.print看看在CmdQuit_Click()里才查找该句柄:
    private sub CmdQuit_Click()retval=findwindow(vbnullstring,"captureup")   
    setparent retval,me.hwndend sub
      

  14.   

    '==============================
    '以下在窗体中
    '==============================
    Option ExplicitPrivate Declare Function FindWindow Lib "user32" _
        Alias "FindWindowA" _
       (ByVal lpClassName As String, _
        ByVal lpWindowName As String) As Long
    Private Declare Function SetParent Lib "user32" _
       (ByVal hWndChild As Long, _
        ByVal hWndNewParent As Long) 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 Function EnumChildWindows Lib "user32" _
       (ByVal hWndParent As Long, _
        ByVal lpEnumFunc As Long, _
        ByVal lParam As Long) As LongPrivate Const WM_CLOSE = &H10
    Private RetVal As Long
    Private Sub Command1_Click()
       Shell "calc.exe", vbNormalFocus
       RetVal = FindWindow(vbNullString, "计算器")
       SetParent RetVal, Me.hWnd
    End Sub
    Private Sub Command2_Click()
        '演示如何使用EnumChildWindows,此语句不是必需的。
        Call EnumChildWindows(Me.hWnd, AddressOf EnumChildProc, 0)
            
        '也许是你写错了,应是WM_CLOSE而非MW_CLOSE,
        '建议在所有模块中都加上Option Explicit语句
        Call SendMessage(RetVal, WM_CLOSE, 0, 0)
    End Sub
    '==============================
    '以下在模块中
    '==============================
    Option ExplicitPrivate Declare Function IsWindowVisible Lib "user32" _
       (ByVal hWnd As Long) As Long
    Private Declare Function GetWindowText Lib "user32" _
        Alias "GetWindowTextA" _
       (ByVal hWnd As Long, _
        ByVal lpString As String, _
        ByVal cch As Long) As LongPublic Function EnumChildProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
        Dim strWindowText As String * 128
      
        If IsWindowVisible(hWnd) Then
            Call GetWindowText(hWnd, strWindowText, 128)
            Debug.Print hWnd, Left(strWindowText, InStr(strWindowText, Chr(0)) - 1)
        End If
      
        EnumChildProc = True
    End Function
      
      

  15.   

    解铃还需系铃人,你用SHELLEXECUTE打开,当然还是用它关闭了。
    shellexecute me.hwnd,"close",app.path _ & "\captureUp.exe",VBNullstring,VBNullstring,1
    如果不行,你找到它的process id也可以把它关掉。
    另外以下例子是FOXAPI上面的,你自己慢慢看吧。
    'Example Name:EnumWindows and EnumChildWindows Callbacks  '------------------------------------------------------------------------------
    '
    ' BAS Moduel Code
    '
    '------------------------------------------------------------------------------
    Option Explicit Private Const LVIF_INDENT As Long = &H10
    Private Const LVIF_TEXT As Long = &H1
    Private Const LVM_FIRST As Long = &H1000
    Private Const LVM_SETITEM As Long = (LVM_FIRST + 6)Private Type LVITEM
       mask As Long
       iItem As Long
       iSubItem As Long
       state As Long
       stateMask As Long
       pszText As String
       cchTextMax As Long
       iImage As Long
       lParam As Long
       iIndent As Long
    End TypePublic Declare Function EnumWindows Lib "user32" _
      (ByVal lpEnumFunc As Long, _
       ByVal lParam As Long) As Long
       
    Public Declare Function EnumChildWindows Lib "user32" _
      (ByVal hWndParent As Long, _
       ByVal lpEnumFunc As Long, _
       ByVal lParam As Long) As LongPrivate Declare Function GetWindowTextLength Lib "user32" _
        Alias "GetWindowTextLengthA" _
       (ByVal hwnd As Long) As Long
        
    Private Declare Function GetWindowText Lib "user32" _
        Alias "GetWindowTextA" _
       (ByVal hwnd As Long, _
        ByVal lpString As String, _
        ByVal cch As Long) As Long
        
    Private Declare Function GetClassName Lib "user32" _
        Alias "GetClassNameA" _
       (ByVal hwnd As Long, _
        ByVal lpClassName As String, _
        ByVal nMaxCount As Long) As LongPrivate Declare Function IsWindowVisible Lib "user32" _
       (ByVal hwnd As Long) As Long
       
    Private Declare Function GetParent Lib "user32" _
       (ByVal hwnd As Long) As LongPrivate Declare Function SendMessage Lib "user32" _
       Alias "SendMessageA" _
      (ByVal hwnd As Long, _
       ByVal wMsg As Long, _
       ByVal wParam As Long, _
       lParam As Any) As Long
    Public Function EnumWindowProc(ByVal hwnd As Long, _
                                   ByVal lParam As Long) As Long
       
      'working vars
       Dim nSize As Long
       Dim sTitle As String
       Dim sClass As String
       
       Dim sIDType As String
       Dim itmX As ListItem
       Dim nodX As Node
       
      'eliminate windows that are not top-level.
       If GetParent(hwnd) = 0& And _
          IsWindowVisible(hwnd) Then
          
         'get the window title / class name
          sTitle = GetWindowIdentification(hwnd, sIDType, sClass)     'add to the listview
          Set itmX = Form1.ListView1.ListItems.Add(Text:=sTitle, Key:=CStr(hwnd) & "h")
          itmX.SmallIcon = Form1.ImageList1.ListImages("parent").Key
          itmX.SubItems(1) = CStr(hwnd)
          itmX.SubItems(2) = sIDType
          itmX.SubItems(3) = sClass
          
       End If
       
      'To continue enumeration, return True
      'To stop enumeration return False (0).
      'When 1 is returned, enumeration continues
      'until there are no more windows left.
       EnumWindowProc = 1
       
    End Function
    Private Function GetWindowIdentification(ByVal hwnd As Long, _
                                             sIDType As String, _
                                             sClass As String) As String   Dim nSize As Long
       Dim sTitle As String  'get the size of the string required
      'to hold the window title
       nSize = GetWindowTextLength(hwnd)
       
      'if the return is 0, there is no title
       If nSize > 0 Then
       
          sTitle = Space$(nSize + 1)
          Call GetWindowText(hwnd, sTitle, nSize + 1)
          sIDType = "title"
          
          sClass = Space$(64)
          Call GetClassName(hwnd, sClass, 64)
       
       Else
       
         'no title, so get the class name instead
          sTitle = Space$(64)
          Call GetClassName(hwnd, sTitle, 64)
          sClass = sTitle
          sIDType = "class"
       
       End If
       
       GetWindowIdentification = TrimNull(sTitle)End Function
    Public Function EnumChildProc(ByVal hwnd As Long, _
                                  ByVal lParam As Long) As Long
       
      'working vars
       Dim sTitle As String
       Dim sClass As String
       Dim sIDType As String
       Dim itmX As ListItem  'get the window title / class name
       sTitle = GetWindowIdentification(hwnd, sIDType, sClass)  'add to the listview
       Set itmX = Form2.ListView1.ListItems.Add(Text:=sTitle)
       itmX.SmallIcon = Form2.ImageList1.ListImages("child").Key
       itmX.SubItems(1) = CStr(hwnd)
       itmX.SubItems(2) = sIDType
       itmX.SubItems(3) = sClass
          
       Listview_IndentItem Form2.ListView1.hwnd, CLng(itmX.Index), 1
       
       EnumChildProc = 1
       
    End Function
    Private Function TrimNull(startstr As String) As String  Dim pos As Integer  pos = InStr(startstr, Chr$(0))
      
      If pos Then
          TrimNull = Left$(startstr, pos - 1)
          Exit Function
      End If
      
     'if this far, there was
     'no Chr$(0), so return the string
      TrimNull = startstr
      
    End Function
    Private Sub Listview_IndentItem(hwnd As Long, _
                                    nItem As Long, _
                                    nIndent As Long)   Dim LV As LVITEM  'if nIndent indicates that indentation
      'is requested nItem is the item to indent
       If nIndent > 0 Then
          
          With LV
            .mask = LVIF_INDENT
            .iItem = nItem - 1 'have to subtract 1
            .iIndent = nIndent
          End With
          
          Call SendMessage(hwnd, LVM_SETITEM, 0&, LV)
          
       End If
           
    End Sub
    '--end block--'
    '------------------------------------------------------------------------------
    '
    ' Form Code
    '
    '------------------------------------------------------------------------------
    Option ExplicitPrivate Sub Command1_Click()   ListView1.ListItems.Clear
       Call EnumWindows(AddressOf EnumWindowProc, &H0)End Sub
    Private Sub Form_Load()   Me.Move (Screen.Width - Me.Width) / 2, (Screen.Height - Me.Height) / 2End Sub
    Private Sub ListView1_DblClick()   Dim hwndSelected As Long
       
       hwndSelected = Val(ListView1.SelectedItem.Key)
       
       Load Form2
       Call Form2.EnumSelectedWindow(ListView1.SelectedItem.Text, hwndSelected)
       
    End Sub
    '--end block--'
     
     
     Form2 Code 
      
    Add the following code to Form2: --------------------------------------------------------------------------------
     
    Option ExplicitPublic Sub EnumSelectedWindow(sItem As String, hwnd As Long)
     
       ListView1.ListItems.Clear
       ListView1.ListItems.Add Text:=sItem, SmallIcon:="parent"
       
       Call EnumChildWindows(hwnd, AddressOf EnumChildProc, &H0)
       
       Me.Show vbModal
       
    End Sub
    Private Sub Form_Load()   Me.Move (Screen.Width - Me.Width) / 2, (Screen.Height - Me.Height) / 2
       
    End Sub
      

  16.   

    '我的程序相关部分就这些了
    Private Sub Form_Load() 初始化
        Vedio_X = 330
        Vedio_Y = -20
        Vedio_Width = 460
        Vedio_Height = 340
        
            ShellExecute Me.hwnd, "open", App.Path & "\CaptureUp.exe", vbNullString, vbNullString, 1
            'RetVal = FindWindow(vbNullString, "")
            Do
                RetVal = FindWindow(vbNullString, "CaptureUp")
                DoEvents
            Loop Until RetVal > 0
            SetParent RetVal, Me.hwnd
            
            SetWindowPos RetVal, HWND_NOTOPMOST, Vedio_X, Vedio_Y, Vedio_Width, Vedio_Height, SWP_NOMOVE
            Sleep 1000
            SetWindowPos Me.Picture5.hwnd, HWND_TOPMOST, Vedio_X, Vedio_Y, Vedio_Width, Vedio_Height, SWP_NOMOVE
    End SubPrivate Sub Option1_Click()   'checkbox切换显示
        If Option1.Value = 1 Then
            SetWindowPos Me.Picture5.hwnd, HWND_NOTOPMOST, Vedio_X, Vedio_Y, Vedio_Width, Vedio_Height, SWP_NOMOVE
            SetWindowPos RetVal, HWND_TOPMOST, Vedio_X, Vedio_Y, Vedio_Width, Vedio_Height, SWP_NOMOVE
     
        Else
            SetWindowPos RetVal, HWND_NOTOPMOST, Vedio_X, Vedio_Y, Vedio_Width, Vedio_Height, SWP_NOMOVE
            SetWindowPos Me.Picture5.hwnd, HWND_TOPMOST, Vedio_X, Vedio_Y, Vedio_Width, Vedio_Height, SWP_NOMOVE
     End If
    End SubPrivate Sub Command1_Click()   '退出
        Dim dwProcessId As Long
        dwProcessId = FindWindow("Progman", vbNullString)
        SetParent RetVal, dwProcessId    SendKeys "%{F4}", True
        Sleep 1000
        Beep
        MsgBox "即将退出本系统,请点击确定后,稍后....", vbOKOnly + vbExclamation, " 退出"
        Sleep 1000     End
    End Sub
      

  17.   

    你在退出程序部分加上
    Call ShellExecute(Me.hWnd, "Close",App.Path _ & "\CaptureUp.exe","" , "", 4)
    试一下