日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

按鍵精靈的原理和編寫方法(1)

 quasiceo 2013-11-30

按鍵精靈的原理和編寫方法(1)  

2009-08-14 16:27:40|  分類: 默認(rèn)分類 |字號 訂閱

按鍵精靈是一類很普遍的游戲插件,wow raid過程中部分職業(yè)的某些操作就需要此類插件(文俊的牧師號在打某些BOSS時驅(qū)散用到過)。類似的插件無非是用程序來模擬重復(fù)性的鍵盤動作。

游戲中進行鍵盤操作的程序可以理解為:

按下某鍵——鍵盤驅(qū)動程序?qū)⒋耸录鬟f給操作系統(tǒng)——操作系統(tǒng)將此事件插入消息隊列——此消息被發(fā)送到當(dāng)前活動窗口。

按照這個過程來理解程序,剩下的只不過要將抽象化的語句翻譯成代碼。當(dāng)然很多過程編程工具(.NET)會自動處理,而不需你去理會。(如如何插入消息隊列,消息隊列的管理,無用對象的釋放)。

第一個問題,按下如何用程序來模擬在鍵盤上按下某鍵。

日常操作中,當(dāng)用戶在鍵盤上按下某個按鍵時,鍵盤內(nèi)芯片會檢測到這個動作,并將這個信號傳遞給計算機。對于每個按鍵,鍵盤分配給它不同的編碼,稱做鍵盤掃描碼。當(dāng)敲擊鍵盤時,底層上實際傳遞給計算機消息隊列的是該按鍵的鍵盤掃描碼,所以知道了欲按鍵的掃描碼,就可以將該信息傳遞給電腦,從而達到模擬按鍵的功能。

第二個問題,鍵盤驅(qū)動程序如何把此事件傳遞給操作系統(tǒng)。

解決第一個問題的關(guān)鍵是必須知道按鍵的鍵盤掃描碼,但是僅僅知道鍵盤掃描碼不夠。因為操作系統(tǒng)需要得到的信息的并不是鍵盤掃描碼。因為鍵盤掃描碼是跟具體的硬件相關(guān)的,同一個鍵在不同鍵盤上的掃描碼有可能不同。鍵盤控制器將這個掃描碼傳給計算機,然后交給鍵盤驅(qū)動程序。鍵盤驅(qū)動程序會完成相關(guān)的工作,并把這個掃描碼轉(zhuǎn)換為鍵盤虛擬碼。鍵盤虛擬碼是針對鍵盤掃描碼的非通用性所提出。盡管出于硬件原因,同一個按鍵可能有不同的掃描碼,但是無論什么鍵盤,同一個按鍵的虛擬碼總是相同的,這樣程序就可以識別了。簡單點說,虛擬碼就是我們經(jīng)??梢钥吹降南馰K_A,VK_B這樣的常數(shù),比如鍵a的虛擬碼(字母大小寫雖然是同一個鍵,但是虛擬碼不同)是&H61(即十進制的97,一般用16進制來表示虛擬碼)。當(dāng)鍵盤驅(qū)動程序把掃描碼轉(zhuǎn)換為虛擬碼后,會把這個鍵盤操作的掃描碼和虛擬碼還有其它信息一起傳遞給操作系統(tǒng)。

操作系統(tǒng)在得到這個信息后,會對消息進行封裝,然后把這個鍵盤消息插入到消息列隊(這個過程則不需要我們理會)。最后,這個鍵盤消息最終會被送到當(dāng)前的活動窗口那里,活動窗口所在的應(yīng)用程序接收到這個消息后,就知道鍵盤上哪個鍵被按下,也就可以根據(jù)按鍵決定該作出什么響應(yīng)返回給用戶了。 

明白整個過程后,然后就可以進行編程實現(xiàn)模擬鍵盤按鍵操作了。最直接的模擬方法是:直接偽造一個鍵盤消息發(fā)給目標(biāo)程序。因為鍵盤信息最終發(fā)送的目標(biāo)程序而引起目標(biāo)程序的響應(yīng)。

WINDOWS提供了消息函數(shù)(API函數(shù)(非托管函數(shù))),這里要用到的主要是:

PostMessage(將一條消息投遞到指定窗口的消息隊列),

SendMessage(調(diào)用一個窗口的窗口函數(shù),將一條消息發(fā)給那個窗口),

PostMessage函數(shù)和SendMessage函數(shù)的聲明一樣,均能向目標(biāo)程序發(fā)送消息,所不同的返回值不同。

Declare Function PostMessage& Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any)

Declare Function SendMessage& Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any)
     若成功發(fā)送信息,PostMessage函數(shù)的返回值為TURE,SendMessage函數(shù)的返回值則根據(jù)發(fā)送的信息有不同的返回值(http://11wuqingchao.blog.163.com/blog/static/33425622200932452146648/edit/)。這里只需向目標(biāo)程序發(fā)送按鍵信息,而不需要根據(jù)該信息的返回值進行下一步操作,所以用PostMessage函數(shù)。PostMessage函數(shù)的參數(shù)的含義跟SendMessage函數(shù)大致相同。這里主要用到的WMsg參數(shù)的常量見(http://11wuqingchao.blog.163.com/blog/static/3342562220093333317338/edit/

可以用到的常量很多,這里要用到以下幾個:

WM_KEYDOW   按下一個鍵

WM_KEYUP       釋放一個鍵

WM_SYSKEYDOWN  當(dāng)用戶按住ALT鍵同時按下其它鍵時提交此消息給擁有焦點的窗口

WM_SYSKEYUP        當(dāng)用戶釋放一個鍵同時ALT 鍵還按著時提交此消息給擁有焦點的窗口

PostMessage函數(shù)還有2個參數(shù),WParam,IParam。在一個鍵盤消息中,前一個參數(shù)的意義較為簡單,表示欲模擬的按鍵的虛擬碼(如按鍵A的的虛擬碼為VK_A,欲模擬這個按鍵時,WParam的值即為VK_A)。而后一個參數(shù)的則較為復(fù)雜,因為它包含了多個信息,一般的模擬過程中可以把它設(shè)置為0,但如果你想要模擬更真實,那么有必要對這個參數(shù)進行設(shè)置。lParam 是一個long類型的參數(shù),內(nèi)存中占4個字節(jié),二進制格式為

00000000 00000000 00000000 00000000  該參數(shù)的的0-15(從右往左的16位)位表示鍵的發(fā)送次數(shù)等擴展信息,16-23位為按鍵的掃描碼,24-31位表示是按下鍵還是釋放鍵。此參數(shù)一般寫成16進制格式,即為

&H00 00 00 00 ,第0-15位一般為&H0001,如果是按下鍵,那么24-31位為&H00,釋放鍵那么24-31位則為&HC0,16-23位的掃描碼的得到需要用到一個API函數(shù)MapVirtualKey,這個函數(shù)可以將虛擬碼轉(zhuǎn)換為掃描碼,或?qū)呙璐a轉(zhuǎn)換為虛擬碼,還可以把虛擬碼轉(zhuǎn)換為對應(yīng)字符的ASCII碼。 

MapVirtualKey的聲明如下:

Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Long, ByVal wMapType As Long) As Long, 其中,

wCode  類型為Long,欲轉(zhuǎn)換的源字符或掃描碼

wMapType  類型為Long,控制映射類型,取值為0,1,2,0表示wCode是個虛擬鍵碼。函數(shù)返回相應(yīng)的掃描碼,1表示wCode是個掃描碼。函數(shù)返回相應(yīng)的虛擬鍵碼,2表示wCode是個虛擬鍵碼。函數(shù)返回相應(yīng)的ASCII值(未加Shift組合鍵)。

函數(shù)返回值為Long型,其結(jié)果取決于wMapType參數(shù)

如下函數(shù)是利用MapVirtualKey函數(shù)得到一個虛擬按鍵的掃描碼,進而構(gòu)造IParam參數(shù),從而向記事本模擬發(fā)送一個A

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
    ByVal hWnd1 As Long, ByVal hWnd2 As Long, _
    ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
 Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
    ByVal hWnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, lParam As Any) As Long
Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" ( _
    ByVal wCode As Long, ByVal wMapType As Long) As Long
 Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101
Private Const WM_CHAR = &H102
Private Const VK_A = &H41

Function MakeIParam(Byval VirtualKey as long,Byval Flag as long) As Long

'VirtualKey表示按鍵虛擬碼,F(xiàn)lag表示按下鍵還是釋放鍵。

Dim s As String

Dim FirstByte As string

If Flag=WM_KEYDOWN Then

    FirstByte="00"    '用來表示IParam的第24位至31位,先用字符串儲存,后轉(zhuǎn)換為16進制

Else

    FirstByte="C0"

EndIf

Dim ScanCode As long

ScanCode=MapVirtuealKey(VIrtualKey,0) '使用API函數(shù)前需先聲明

Dim SecondByte as string  

SecondByte=Right("00"&Hex(ScanCode),2)  '用來表示IParam的第16位至23位

s=FirstByte&SecondByte&"0001"

MakeIParam=Val("&H"&s)

End Function

Private Sub Form_Load()
Dim hWnd&
Dim hEdit&
hWnd = FindWindow("notepad", "無標(biāo)題 - 記事本")
hEdit = FindWindowEx(hWnd, 0, "Edit", vbNullString)

If hWnd = 0 Or hEdit = 0 Then
  MsgBox "donot find,sorry!"
Else
  PostMessage hEdit, WM_CHAR, Asc("A"), MakeIparam(VK_A, WM_KEYDOWN) '輸入字符A
End If
End Sub

FindWindow 和FindWindowEx函數(shù)用來查找記事本編輯框的句柄。(句柄可以解釋為系統(tǒng)分配給每個資源的唯一標(biāo)識)這種方法通過局部鍵盤消息來模擬按鍵,它可以實現(xiàn)后臺按鍵,也就是說他對你的前臺操作不會有什么影響。比如,你可以用這個方法做個程序在游戲中模擬按鍵來不斷地執(zhí)行某些重復(fù)的操作,無論目標(biāo)程序是否獲得焦點都沒有影響,這就是后臺模擬按鍵的原理。

當(dāng)然模擬按鍵的方法不止一種!

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多