许多人包括我自己,对於window与process或Thread间的对应,常感困扰,我就目前所知者,大概的介绍一下:一个Process有自己4GB的位址空间,这个观念比较容易接受,但是它却不是执行程式的单位,真正执行程式者是Thread,每个Process被Create时,便会有一个主thread 来执行它,我们又可以Create其他的Thread来执行程式,假设现在就有两个thread於这个Process了,那麽,这两个Thread原则上是共用Process的同一个位址空间,例如:背景列印,但是至少有两个Thread在做事,它的好处不用说明太多大家都可以明白,但它同时也会有其他问题(如同步、如果一个thread一个不小心当了,那有可能会使整个Process死掉),这些不在讨论范围。而window呢,它一定有一个thread来执行它,但一个Thread却可以有不只一个的 Windows或根本没有。另外,一个Process有一个的唯一的Process ID而每个Thread也有唯一的ThreadID,而控制Process 则大多透过Process Handle(hProcess)而非 Process ID,正如透过hWnd来控制Window一样。如同前面所言,一个window有一个Thread在执行它,那该如何取得呢?请用 Declare Function GetWindowThreadProcessId Lib "user32" _ (ByVal hwnd As Long, lpdwProcessId As Long) As Long 这个function传入一个hwnd而取得Process ID(其第二个叁数),而传回值是 ThreadID。而使用OpenProcess()来取得Process Handle,底下程式的目的是取得 Window ClassName, 与Window Title,我们搜寻window时,常使用FindWindow() 但这个function传入的叁数第一个便是Window ClassName,但我们经常不知道 ClassName透过它,我们可轻易来得知,进而做许多的控制。 程式使用方式: 1.先将想查询的window叫出,放在桌面上 2.执行本程式,把不必要的window关掉,直到想查询的window看得见(不必全部) 3.在form1的Command1上按下mouse的右键不要放掉,这时会看到mouse变问号加箭头 而且form1不见了,代表您可以拖拉mouse了。 4.移到想查询的window上面,放掉mouse,而後form1再度出现,上有所要的资讯
一个form , 一个ommandBox, 2 labels
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, al X As Long, ByVal Y As Long, _
ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, _
ByVal yPoint 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 Long
Private Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, _
ByVal uExitCode 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 FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Const HWND_TOP = 0
Const HWND_BOTTOM = 1
Const SWP_NOSIZE = &H1
Const SWP_NOMOVE = &H2
Const PROCESS_QUERY_INFORMATION = &H400
Private TitleName As String
Private ClassName As String
Private hProcess As Long
Private Candisplay As Boolean
Private Sub Command1_MouseDown(Button As Integer, Shift As Integer,
X As Single, Y As Single)
Dim aa As Long
If Button = vbRightButton Then
将window设定成在底层
aa = SetWindowPos(Me.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE)
Me.MousePointer = vbArrowQuestion
End If
End Sub
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single,
Y As Single)
Dim aa As Long
Dim pt As POINTAPI
Dim hwnd5 As Long
Dim str5 As String
Dim len5 As Long
Dim thrid As Long, pid As Long
If Button = vbRightButton Then
设定window到上层
aa = SetWindowPos(Me.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE)
Me.MousePointer = vbDefault
取得mouse目前的座标,不能用mouseup Event的x,y因那是相对於form的座标
aa = GetCursorPos(pt)
取得pt所在座标,是落在那一个window上面
hwnd5 = WindowFromPoint(pt.X, pt.Y)
len5 = 256
ClassName = String(255, 0)
取得该window的Class name
aa = GetClassName(hwnd5, ClassName, len5)
ClassName = Left(ClassName, aa)
len5 = 256
TitleName = String(255, 0)
取得该window的title
aa = GetWindowText(hwnd5, TitleName, len5)
TitleName = Left(TitleName, aa)
依hwnd取得相对应的threadID(thrid), ProcessID(pid)
thrid = GetWindowThreadProcessId(hwnd5, pid)
取得Process Handle
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
有了hProcess那可做事可多啦,例如:可侦测 它何时结束,或强制它结束等等
Call TerminateProcess(hProcess, 38) 最好别这麽做,否则,嘿嘿,你自己试
Label1.Caption = " Title = " + TitleName
Label2.Caption = "Calss Name = " + ClassName
End If
End Sub