XiaoHui.Net 笑汇程序员论坛Visual Basic 讨论区

   尝试寻找电脑中执行的程序(EnumWindows)


页: [1]

wzf_sky2007-11-5 08:55
尝试寻找电脑中执行的程序(EnumWindows)

尝试寻找电脑中执行的程序(EnumWindows)

来源:cww

其实,这只是找一下没有Parent且为Top-Level的可见视窗,主要用EnumWindows来巡行
萤幕上的视窗,而这个Function不会找Windows,而且需一个EnumWindowsProc callback
function,这个EnumWindowsProc 传回1时,表示继续巡行,直到没有符合条件的Window
才结束,若传回0表示立即停止巡行,而结束EnumWindows的呼叫。

另有一件头大的事,一个Process可能会包含有许多Windows,这些Widnows有些可见,有
不可见,用IsWindowVisible可去除不可见的Window;但如果一个Process有两个Top-Level
且可见的Window(如:VB中一个Project有两个Form,且同时出现时),我们要找的是
Process而非Window,所以这种情况我们要将其中一个去除,只留下一个。而EmunWindowsProc
传给我们的是hWnd,所以我们使用GetWindowThreadProcessId来取得ProcessID,同一个
ProcessID代表是相同的Process,我们记录这些ProcessID,而且相同的ProcessID只能记
录一次,而且在记录ProcessID时顺带将该Window的Title也记录下来,若没有Title则记
录ClassName。要完成这个动作,我选用Collection来做。

注:
    1.这只是取得电脑上正常,且有Window的Process,有一些奇特的Process它可没有
      那麽容易就可以取得,而且我也不知该如何取得,您所表列的Process,可以和
      Window按ctl-alt-delete所列出的Process表列做一比较。
    2.主要是介绍EnumWindows的运用

'以下在.Bas
Option Explicit
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long

Public coll As New Collection
'hWnd是Window传给我们的Window handle,而lParam是我们呼叫EnumWindows()时的第
'二个叁数值,在这个例子中,我们传0进来,所以lParam一直是0
Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean
    Dim S As String, pid As Long
     If GetParent(hwnd) = 0 Then
       '读取 hWnd 的视窗标题
       S = String(80, 0)
       Call GetWindowText(hwnd, S, 80)
       S = Left(S, InStr(S, Chr(0)) - 1)
       Call GetWindowThreadProcessId(hwnd, pid)
       '当没有标题的hWnd之pid被加入Coll的Collection时,若pid重覆会有错,我们不管它
       On Error Resume Next
       If Len(S) = 0 Then
          '没有标题,则记录Class Name
          S = String(255, 0)
          Call GetClassName(hwnd, S, 255)
          S = Left(S, InStr(S, Chr(0)) - 1)
          coll.Add "-!@" + S, Str(pid) 'key 为Pid
       Else
          '如果相同的pid记录两次,便会产生err, 而去执行errh的程序
          On Error GoTo errh
          If IsWindowVisible(hwnd) Then
             coll.Add S, Str(pid)
          End If
       End If
    End If
    EnumWindowsProc = True ' 表示继续列举 hWnd
    Exit Function
errh:
    '如果先前coll 记录key=pid的 那个Item记录的是ClassName,则Item以Window
    '的Title来取代
    If Mid(coll.Item(Str(pid)), 1, 3) = "-!@" Then '表示先前以ClassName记录
       coll.Remove (Str(pid))
       coll.Add S, Str(pid)
    End If
    EnumWindowsProc = True ' 表示继续列举 hWnd
End Function

'以下在form,需一个Command1, 一个ListBox
Private Sub Command1_Click()
   Dim co As Variant
    List1.Clear
    Call EnumWindows(AddressOf EnumWindowsProc, 0&)
    For Each co In coll
        If Mid(co, 1, 3) = "-!@" Then
           co = "Class Name:" + Mid(co, 4)
        End If
        List1.AddItem co
    Next
End Sub









查看完整版本: 尝试寻找电脑中执行的程序(EnumWindows)