新聞| | PChome| 登入
2007-10-25 23:02:28 | 人氣377| 回應0 | 上一篇 | 下一篇
推薦 0 收藏 0 轉貼0 訂閱站台

嘗試尋找電腦中執行的程式(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

                                                        

台長: Kenny
人氣(377) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: 程式設計 |
此分類下一篇:如何設定螢幕顏色數
此分類上一篇:在vb中叫出控制台Item的內容

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文