顯示具有 Visual Basic 標籤的文章。 顯示所有文章
顯示具有 Visual Basic 標籤的文章。 顯示所有文章

2008年7月15日 星期二

Check Keyboard & Mouse Hook #3

打開VB新建一個項目,然後創建一個窗體和一個模塊,此程序已調試過,但是要注意的是在寫鉤子函數的過程,請在每次 RUN之前進行保存,這些API程序超越了VB的編譯環境,因為VB環境和這些API函數同屬系統級,因此它無法管理這些API,一旦出現問題,整個VB 環境會在毫無預知的情況下造成全線崩潰的局面。
正在裝載數據……

窗體中的代碼:窗體中的程序:
Option Explicit
Private Const WH_KEYBOARD_LL = 13&

Private Sub cmdExit_Click()
End
End Sub
Public Sub HookKeyboard()
KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf KeyboardCallback, _
App.hInstance, 0&)
'WH_KEYBOARD_LL:攔截類型
'AddressOf KeyboardCallback:掛接函數鏈的首地址
'App.hInstance:程序本身的句柄
'0,表示全局攔截,意思就是攔截所有窗口下的鍵盤輸入
End Sub

Private Sub Form_KeyPress(KeyAscii As Integer)
If KeyAscii = 9 Then
MsgBox "你按下了TAB鍵!", vbOKOnly + vbInformation, "提示"
End If
If KeyAscii = 13 Then
MsgBox "你按下了ENTER鍵!", vbOKOnly + vbInformation, "提示"
End If
If KeyAscii = 97 Then
MsgBox "你按下了a鍵!", vbOKOnly + vbInformation, "提示"
End If
If KeyAscii = 65 Then
MsgBox "你按下了A鍵!", vbOKOnly + vbInformation, "提示"
End If
End Sub
Private Sub Form_Load()
Call HookKeyboard
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call UnhookKeyboard
End Sub

模塊中的代碼:
Option Explicit
'通知Windows進行鉤子操作並定義鉤子函數
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
'idHook:攔截類型 lpfn:掛接函數鏈的首地址指針
'hmod:創建鉤子函數實體的句柄,即程序本身的句柄
'dwThreadId:為監控代碼,0表示全局監控,dwThreadId用於線程鉤子VB中可以設置為App.ThreadID。

Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
'釋放鉤子
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, _
pSource As Any, ByVal cb As Long)
'將內存裡的某一塊數據pSource拷貝到另一個地址pDest,cb表示拷貝內容的字節大小

Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _
ByVal nCode As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
'掛鉤函數攔截了某條消息後,由CallNextHookEx決定是否將這些消息送還給Windows系統

Private Type KBDLLHOOKSTRUCT '鍵盤鉤子的結構體
vkCode As Long '虛擬鍵碼
scanCode As Long '掃瞄碼
flags As Long '功能鍵狀態
time As Long
dwExtraInfo As Long
End Type

Public KeyboardHandle As Long '鍵盤鉤子函數句柄
Private Const HC_ACTION = 0
Private Const LLKHF_EXTENDED = &H1
Private Const LLKHF_INJECTED = &H10
Private Const LLKHF_ALTDOWN = &H20
Private Const LLKHF_UP = &H80
Public Const VK_A = &H41
Public Const VK_ENTER = &HD
Public Const VK_TAB = &H9
Public Const VK_CONTROL = &H11
Public Const VK_ESCAPE = &H1B
Public Const VK_DELETE = &H2E

'鉤子函數的核心
Public Function KeyboardCallback(ByVal Code As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
'Code 表示攔截層次,之前我們已經說過,如果Code為0,則攔截所有窗口的鍵盤輸入
'wParam 表示是何種Windows消息
'lParam表示某條Windows消息的具體內容的指針,它實際指向存儲那個內容的內存地址

Static Hookstruct As KBDLLHOOKSTRUCT '定義一個局部靜態結構體實例
If (Code = HC_ACTION) Then '鑑別Windows的消息來源
Call CopyMemory(Hookstruct, ByVal lParam, Len(Hookstruct))
If (IsHooked(Hookstruct)) Then '過濾消息
KeyboardCallback = 1
Exit Function
End If
End If
KeyboardCallback = CallNextHookEx(KeyboardHandle, Code, wParam, lParam)
'將消息釋放,用CallNextHookEx交還給系統
End Function
Public Function IsHooked(ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
'If (KeyboardHook Is Nothing) Then
If KeyboardHandle = 0 Then
IsHooked = False
Exit Function
End If
'有時候CopyMemory也會發生意想不到的事情,所以,當KeyboardHook = Nothing (無值)的情況下,退出,略過該函數,以防不可預知的錯誤。
If (Hookstruct.vkCode = VK_TAB) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then '屏蔽ALT+TAB鍵組合
IsHooked = True
Exit Function
End If
'以上攔截了Alt+Tab的鍵盤組合,並將IsHooked返回True(就是1),表示本次按鍵確實符合了過濾原則,應該吞吃掉。
If (Hookstruct.vkCode = VK_ENTER) Then '屏蔽ENTER鍵
IsHooked = True
Exit Function
End If
If (Hookstruct.vkCode = VK_A) Then '屏蔽A和a鍵
IsHooked = True
Exit Function
End If
End Function

Public Sub UnhookKeyboard() '釋放鉤子函數
'If (Hooked) Then
Call UnhookWindowsHookEx(KeyboardHandle)
'End If
End Sub

Check Keyboard & Mouse Hook #2

寫全局鉤子
鎖定鍵盤和鼠標的鉤子
DLL端
// HOOK.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "HOOK.h"
#include "mmsystem.h"


#define _WIN32_WINNT 0x0500

#include
#include


HINSTANCE hInstance;
HHOOK hhkKeyboard;
HHOOK hhMouseHook;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
hInstance=(HINSTANCE)hModule;
return TRUE;
}


// This is an example of an exported variable
HOOK_API int nHOOK=0;

// This is an example of an exported function.
HOOK_API int fnHOOK(void)
{
return 42;
}

// This is the constructor of a class that has been exported.
// see HOOK.h for the class definition
CHOOK::CHOOK()
{
return;
}

LRESULT LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//可以加入一些釋放鍵盤的代碼

}

LRESULT LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//可以加入一些釋放鼠標的代碼
}

HOOK_API BOOL EnableKeyboardCapture()//設定鉤子用來鎖定鍵盤鼠標
{
if (!(hhkKeyboard=SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)LowLevelKeyboardProc, hInstance, 0)))
return FALSE;
if (!(hhMouseHook=SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LowLevelMouseProc, hInstance, 0)))
return FALSE;;
return TRUE;
}

HOOK_API BOOL DisableKeyboardCapture()//釋放鍵盤和鼠標
{
UnhookWindowsHookEx(hhMouseHook);
return UnhookWindowsHookEx(hhkKeyboard);
}





###################################################################


DLL端編譯器(VC6)C/C++屬性頁加入環境變量HOOK_EXPORTS
//頭文件定義
HOOK.h
------------------------------------------------------------
#ifdef HOOK_EXPORTS
#define HOOK_API __declspec(dllexport)
#else
#define HOOK_API __declspec(dllimport)
#endif

HOOK_API BOOL EnableKeyboardCapture();
HOOK_API BOOL DisableKeyboardCapture();
// This class is exported from the HOOK.dll
class HOOK_API CHOOK {
public:
CHOOK(void);
// TODO: add your methods here.
};

extern HOOK_API int nHOOK;

HOOK_API int fnHOOK(void);



應用程序端只要加入HOOK.H和HOOK.lib就行了,然後按自己要求調用

EnableKeyboardCapture();
DisableKeyboardCapture();

最後提醒一句,在沒有加入釋放鍵盤鼠標的代碼前,不要編譯運行,否則後果自負

Check Keyboard & Mouse Hook #1

如果你不需要屏蔽Ctrl+Alt+Del組合鍵,可以使用低級鍵盤鉤子(WH_KEYBOARD_LL)與低級鼠標鉤子(WH_MOUSE_LL),這兩種消息鉤子的好處是不需要放在動態鏈接庫中就可以作全局鉤子,將鍵盤消息與鼠標消息截獲.

unit uHookKeyAndMouse;
{ 該單元利用WH_KEYBOARD_LL與WH_MOUSE_LL兩種類型的鉤子分別截獲鍵盤消息與鼠標消息}
{ 由於這裡只是需要將消息屏蔽,故只需對鉤子函數的返回結果設為1即可. }
{ 提供兩個函數StartHookKeyMouse與StopHookKeyMouse兩個函數. }

interface

uses
Windows, Messages, SysUtils;

const
WH_KEYBOARD_LL =13;
WH_MOUSE_LL =14;

procedure StartHookKeyMouse;
procedure StopHookKeyMouse;

implementation

var
hhkLowLevelKybd:HHook=0;
hhkLowLevelMouse:HHook=0;

function LowLevelKeyboardProc(nCode:Integer; WParam:WPARAM; LParam:LPARAM):LRESULT; stdcall;
begin
Result:=1;
if nCode<>0 then Result:=CallNextHookEx(0,nCode,WParam,LParam);
end;

function LowLevelMouseProc(nCode:Integer; WParam:WPARAM; LParam:LPARAM):LRESULT; stdcall;
begin
Result:=1;
if nCode<>0 then Result:=CallNextHookEx(0,nCode,WParam,LParam);
end;

procedure StartHookKeyMouse;
begin
if hhkLowLevelKybd = 0 then
begin
hhkLowLevelKybd := SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, Hinstance, 0);
end;
if hhkLowLevelMouse = 0 then
begin
hhkLowLevelMouse:=SetWindowsHookEx(WH_MOUSE_LL,LowlevelMouseProc,HInstance,0);
end;
end;

procedure StopHookKeyMouse;
begin
if hhkLowLevelKybd <> 0 then
begin
UnhookWindowsHookEx(hhkLowLevelKybd);
hhkLowLevelKybd:=0;
end;
if hhkLowLevelMouse <> 0 then
begin
UnHookWindowsHookEx(hhkLowLevelMouse);
hhkLowLevelMouse:=0;
end;
end;

initialization
hhkLowLevelKybd:=0;
hhkLowLevelMouse:=0;
finalization
if hhkLowLevelKybd <> 0 then UnhookWindowsHookEx(hhkLowLevelKybd);
if hhkLowLevelMouse <> 0 then UnhookWindowsHookEx(hhkLowLevelMouse);
end.


來自:conworld, 時間:2005-2-24 16:06:31, ID:2996263
高手終於出現了,謝謝
你的方法確實實現了鎖定鼠標,但是我想達到的效果是:
1.鎖定鍵盤
2.鼠標只能在我的程序窗口中操作
謝謝


來自:smokingroom, 時間:2005-2-24 17:01:12, ID:2996381
要求2(鼠標只能在我的程序窗口中操作)的實現:
修改LowLevelMouseProc過程如下:

type
PMSLLHOOKSTRUCT=^MSLLHOOKSTRUCT;
MSLLHOOKSTRUCT = record
pt:TPoint;
mouseData:DWORD;
flags:DWORD;
time:DWORD;
dwExtraInfo:DWORD;
end;

var
MouseRect:TRect; //這是你需要限制的Mouse活動範圍.

function LowLevelMouseProc(nCode:Integer; WParam:WPARAM; LParam:LPARAM):LRESULT; stdcall;
var
p:PMSLLHOOKSTRUCT;
begin
Result:=0;
if nCode=HC_ACTION then
begin
p:=PMSLLHOOKSTRUCT(LParam);
if (p.pt.X <> MouseRect.Right) or
(p.pt.Y <> MouseRect.Bottom) then
Result:=1;
end else
if nCode<>0 then Result:=CallNextHookEx(0,nCode,WParam,LParam);
end;

附取得MouseRect的代碼,假定你的主窗體體為MainFrm
MouseRect:=MainFrm.ClientRect;
MouseRect.TopLeft:=MainFrm.ClientToScreen(MouseRect.TopLeft);
MouseRect.BottomRight:=MainFrm.ClientToScreen(MouseRect.BottomRight);


另在Result:=1之前加多一個ClipCursor(@MouseRect)效果會更好,可以有效解決當按下Ctrl+Alt+Del後將Mouse移出窗體後,Mouse失效的情況.
if (p.pt.X <> MouseRect.Right) or
(p.pt.Y <> MouseRect.Bottom) then
begin
ClipCursor(@MouseRect)
Result:=1;
end

Check Keyboard Hook #1

Implements IWindowsHook

Private Sub Form_Load()
InstallHook Me, WH_KEYBOARD
End Sub

Private Sub Form_QueryUnload( _
Cancel As Integer, UnloadMode As Integer)
RemoveHook Me, WH_KEYBOARD
End Sub

Private Function IWindowsHook_HookProc( _
ByVal eType As EHTHookTypeConstants, _
ByVal nCode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long, _
bConsume As Boolean _
) As Long

If KeyBoardlParam(lParam).KeyDown Then
If Me.ActiveControl is Text1 Then
txtTest.SelText = " "
bConsume = True
End If
End If
End Function

Kill All Program

bs 實現瞬間關閉多個系統進程
作者:JiaJia 日期:2007-08-05
字體大小: 小 中 大
程序利用 vbs 的wmi 、scripting.filesystemobject、shell.application、scripting.dictionary、 wscript.shell的相關功能功能實現將當前進程列表顯示在一個文本文件中,通過用戶界面的選擇,確定需要瞬間中斷的進程列表,然後中斷之。程序試驗環境為 windows xp_sp2,主要針對系統存在多個需要中斷進程的情況下,瞬間成批中斷進程。
'----------------------------------------------------------------------------------
On Error Resume next
Set fs=CreateObject("scripting.filesystemobject")
Set os=CreateObject("wscript.shell")
Set os0=createobject("shell.application")
Set d0=CreateObject("scripting.dictionary")
Set wmi=GetObject("winmgmts:\\.")
Set pro_s=wmi.instancesof("win32_process")

'-------------創建臨時文本文件文件,把當前進程輸入該文本文件之中並通過記事本打開之
'---------同時把進程對應序號 和 pid 傳遞給dictionary(d0)一份
filename=fs.GetTempName
set f1=fs.CreateTextFile(filename,True)
msg="序號"&vbTab&"名稱"&vbTab&"PID"&vbTab&"程序文件"&vbtab&now&Chr(10)
f1.Writeline(msg)
n=1
For Each p In pro_s
f1.WriteLine(n&". "&p.name&" , "&p.handle&" , "&p.commandline&Chr(10))
d0.Add ""&n,Trim(p.handle)
n=n+1
Next
f1.Close
os0.MinimizeAll
os.Exec "notepad.exe "&filename
wscript.sleep 500

'--------------等待用戶輸入欲中斷的進程相關的序號列,確定之後關閉並刪除臨時文本文件
x=InputBox("請根據"&filename&"中的內容"+Chr(10)+ _
"選擇需要同時中斷的進程對應序號:"+Chr(10)+ _
"(序號之間用','間隔 例如:'1,3,5,7,11')","選擇")
os.AppActivate filename&" - 記事本"
os.SendKeys "%fx"
WScript.Sleep 500
fs.DeleteFile filename

'--------如果用戶取消了操作,就退出程序
If x="" then wscript.quit
'--------把用戶輸入的序號列中相關的序號傳遞給一個數組 xs
xs=Split(x,",",-1,1)
'-----------對用戶輸入的序號列進行校對,將重複序號標記為 -2,計算實際序號個數
For i=0 to ubound(xs) '---利用雙重循環將重複輸入的內容保留一份,其他的標記為-1
for n=0 to ubound(xs)
if n=i then
n=n+1
if n>ubound(xs) then exit for
end if
if Trim(xs(n))=Trim(xs(i)) or _
Trim(xs(n))="" Then
xs(n)="-1"
end If
next
Next

w=0 '----把不真實可用的序號剔除並計算出其個數
For i=0 To UBound(xs)
If d0.Exists(xs(i))=False Then
xs(i)="-2"
w=w+1
End If
Next

w=(UBound(xs)+1-w) '---得出可用的序號個數
'------------如果序列中沒有輸入任何序號就退出程序
If w=0 Then
MsgBox "需要中斷的進程列表為空!"
WScript.Quit
End If

'-------------根據用戶輸入信息中斷相應進程
m=0
For i=0 To UBound(xs)
If xs(i) <> "-2" then '---只有真實可用的序號才參與循環
For Each p In pro_s
If Trim(p.handle)=trim(d0(xs(i))) Then '---如果進程pid號碼正是需要中斷的就嘗試中斷
p_name=p.name
pd=p.terminate()
If pd=0 Then '---判斷中斷進程的嘗試是否成功
msg=p_name&" 進程中斷成功!"
m=m+1
Else
msg=p_name&" 進程中斷失敗!"
End If
os.popup msg,1,"通知",64+0
End If
Next
end if
Next

os.popup w&"個目標進程,已經中斷了"&m&"個" ,5,"通知",64+0
WScript.quit