青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

讓VB菜鳥(niǎo)最快寫(xiě)出自己的外掛.通殺所有游戲.呵呵.

這年頭,在這個(gè)論壇里面已經(jīng)沒(méi)有什么技術(shù)貼了...呵呵~發(fā)一篇驚天地,泣鬼神的帖子.當(dāng)然這個(gè)只是模擬鍵盤(pán)的終極模擬.呵呵~
????? 鍵盤(pán)是我們使用計(jì)算機(jī)的一個(gè)很重要的輸入設(shè)備了,即使在鼠標(biāo)大行其道的今天,很多程序依然離不開(kāi)鍵盤(pán)來(lái)操作。但是有時(shí)候,一些重復(fù)性的,很繁瑣的鍵盤(pán)操作 總會(huì)讓人疲憊,于是就有了用程序來(lái)代替人們按鍵的方法,這樣可以把很多重復(fù)性的鍵盤(pán)操作交給程序來(lái)模擬,省了很多精力,按鍵精靈就是這樣的一個(gè)軟件。那么 我們?cè)鯓硬拍苡肰B來(lái)寫(xiě)一個(gè)程序,達(dá)到與按鍵精靈類(lèi)似的功能呢?那就讓我們來(lái)先了解一下windows中響應(yīng)鍵盤(pán)事件的機(jī)制。
????當(dāng)用戶按下 鍵盤(pán)上的一個(gè)鍵時(shí),鍵盤(pán)內(nèi)的芯片會(huì)檢測(cè)到這個(gè)動(dòng)作,并把這個(gè)信號(hào)傳送到計(jì)算機(jī)。如何區(qū)別是哪一個(gè)鍵被按下了呢?鍵盤(pán)上的所有按鍵都有一個(gè)編碼,稱作鍵盤(pán)掃 描碼。當(dāng)你按下一個(gè)鍵時(shí),這個(gè)鍵的掃描碼就被傳給系統(tǒng)。掃描碼是跟具體的硬件相關(guān)的,同一個(gè)鍵,在不同鍵盤(pán)上的掃描碼有可能不同。鍵盤(pán)控制器就是將這個(gè)掃 描碼傳給計(jì)算機(jī),然后交給鍵盤(pán)驅(qū)動(dòng)程序。鍵盤(pán)驅(qū)動(dòng)程序會(huì)完成相關(guān)的工作,并把這個(gè)掃描碼轉(zhuǎn)換為鍵盤(pán)虛擬碼。什么是虛擬碼呢?因?yàn)閽呙璐a與硬件相關(guān),不具有 通用性,為了統(tǒng)一鍵盤(pán)上所有鍵的編碼,于是就提出了虛擬碼概念。無(wú)論什么鍵盤(pán),同一個(gè)按鍵的虛擬碼總是相同的,這樣程序就可以識(shí)別了。簡(jiǎn)單點(diǎn)說(shuō),虛擬碼就 是我們經(jīng)??梢钥吹降南馰K_A,VK_B這樣的常數(shù),比如鍵A的虛擬碼是65,寫(xiě)成16進(jìn)制就是&H41,注意,人們經(jīng)常用16進(jìn)制來(lái)表示虛擬 碼。當(dāng)鍵盤(pán)驅(qū)動(dòng)程序把掃描碼轉(zhuǎn)換為虛擬碼后,會(huì)把這個(gè)鍵盤(pán)操作的掃描碼和虛擬碼還有其它信息一起傳遞給操作系統(tǒng)。然后操作系統(tǒng)則會(huì)把這些信息封裝在一個(gè)消 息中,并把這個(gè)鍵盤(pán)消息插入到消息列隊(duì)。最后,要是不出意外的話,這個(gè)鍵盤(pán)消息最終會(huì)被送到當(dāng)前的活動(dòng)窗口那里,活動(dòng)窗口所在的應(yīng)用程序接收到這個(gè)消息 后,就知道鍵盤(pán)上哪個(gè)鍵被按下,也就可以決定該作出什么響應(yīng)給用戶了。這個(gè)過(guò)程可以簡(jiǎn)單的如下表示:
用戶按下按鍵-----鍵盤(pán)驅(qū)動(dòng)程序?qū)⒋耸录鬟f給操作系統(tǒng)-----操作系統(tǒng)將鍵盤(pán)事件插入消息隊(duì)列-----鍵盤(pán)消息被發(fā)送到當(dāng)前活動(dòng)窗口
明白了這個(gè)過(guò)程,我們就可以編程實(shí)現(xiàn)在其中的某個(gè)環(huán)節(jié)來(lái)模擬鍵盤(pán)操作了。在VB中,有多種方法可以實(shí)現(xiàn)鍵盤(pán)模擬,我們就介紹幾種比較典型的。

1.局部級(jí)模擬

???? 從上面的流程可以看出,鍵盤(pán)事件是最終被送到活動(dòng)窗口,然后才引起目標(biāo)程序響應(yīng)的。那么最直接的模擬方法就是:直接偽造一個(gè)鍵盤(pán)消息發(fā)給目標(biāo)程序。哈哈, 這實(shí)在是很簡(jiǎn)單,windows提供了幾個(gè)這樣的API函數(shù)可以實(shí)現(xiàn)直接向目標(biāo)程序發(fā)送消息的功能,常用的有SendMessage和 PostMessage,它們的區(qū)別是PostMessage函數(shù)直接把消息仍給目標(biāo)程序就不管了,而SendMessage把消息發(fā)出去后,還要等待目 標(biāo)程序返回些什么東西才好。這里要注意的是,模擬鍵盤(pán)消息一定要用PostMessage函數(shù)才好,用SendMessage是不正確的(因?yàn)槟M鍵盤(pán)消 息是不需要返回值的,不然目標(biāo)程序會(huì)沒(méi)反應(yīng)),切記切記!PostMessage函數(shù)的VB聲明如下:
Declare?Function?PostMessage?Lib?"user32"?Alias?"PostMessageA"?(ByVal?hwnd?As?Long,?ByVal?wMsg?As?Long,?ByVal?wParam?As?Long,?lParam?As?Any)?As?Long
參數(shù)hwnd?是你要發(fā)送消息的目標(biāo)程序上某個(gè)控件的句柄,參數(shù)wMsg?是消息的類(lèi)型,表示你要發(fā)送什么樣的消息,最后wParam?和lParam?這兩個(gè)參數(shù)是隨消息附加的數(shù)據(jù),具體內(nèi)容要由消息決定。
再來(lái)看看wMsg?這個(gè)參數(shù),要模擬按鍵就靠這個(gè)了。鍵盤(pán)消息常用的有如下幾個(gè):
WM_KEYDOWN?????表示一個(gè)普通鍵被按下
WM_KEYUP???????表示一個(gè)普通鍵被釋放
WM_SYSKEYDOWN??表示一個(gè)系統(tǒng)鍵被按下,比如Alt鍵
WM_SYSKEYUP????表示一個(gè)系統(tǒng)鍵被釋放,比如Alt鍵
如 果你確定要發(fā)送以上幾個(gè)鍵盤(pán)消息,那么再來(lái)看看如何確定鍵盤(pán)消息中的wParam?和lParam?這兩個(gè)參數(shù)。在一個(gè)鍵盤(pán)消息中,wParam?參數(shù)的 含義較簡(jiǎn)單,它表示你要發(fā)送的鍵盤(pán)事件的按鍵虛擬碼,比如你要對(duì)目標(biāo)程序模擬按下A鍵,那么wParam?參數(shù)的值就設(shè)為VK_A?,至于lParam? 這個(gè)參數(shù)就比較復(fù)雜了,因?yàn)樗硕鄠€(gè)信息,一般可以把它設(shè)為0,但是如果你想要你的模擬更真實(shí)一些,那么建議你還是設(shè)置一下這個(gè)參數(shù)。那么我們就詳細(xì) 了解一下lParam?吧。lParam?是一個(gè)long類(lèi)型的參數(shù),它在內(nèi)存中占4個(gè)字節(jié),寫(xiě)成二進(jìn)制就是 00000000?00000000?00000000?00000000??一共是32位,我們從右向左數(shù),假設(shè)最右邊那位為第0位(注意是從0而不是 從1開(kāi)始計(jì)數(shù)),最左邊的就是第31位,那么該參數(shù)的的0-15位表示鍵的發(fā)送次數(shù)等擴(kuò)展信息,16-23位為按鍵的掃描碼,24-31位表示是按下鍵還 是釋放鍵。大家一般習(xí)慣寫(xiě)成16進(jìn)制的,那么就應(yīng)該是&H00?00?00?00?,第0-15位一般為&H0001,如果是按下鍵,那 么24-31位為&H00,釋放鍵則為&HC0,那么16-23位的掃描碼怎么會(huì)得呢?這需要用到一個(gè)API函數(shù) MapVirtualKey,這個(gè)函數(shù)可以將虛擬碼轉(zhuǎn)換為掃描碼,或?qū)呙璐a轉(zhuǎn)換為虛擬碼,還可以把虛擬碼轉(zhuǎn)換為對(duì)應(yīng)字符的ASCII碼。它的VB聲明如 下:
Declare?Function?MapVirtualKey?Lib?"user32"?Alias?"MapVirtualKeyA"?(ByVal?wCode?As?Long,?ByVal?wMapType?As?Long)?As?Long
參 數(shù)wCode?表示待轉(zhuǎn)換的碼,參數(shù)wMapType?表示從什么轉(zhuǎn)換為什么,如果是虛擬碼轉(zhuǎn)掃描碼,則wMapType?設(shè)置為0,如果是虛擬掃描碼轉(zhuǎn) 虛擬碼,則wMapType?設(shè)置為1,如果是虛擬碼轉(zhuǎn)ASCII碼,則wMapType?設(shè)置為2.相信有了這些,我們就可以構(gòu)造鍵盤(pán)事件的 lParam參數(shù)了。下面給出一個(gè)構(gòu)造lParam參數(shù)的函數(shù):
Declare?Function?MapVirtualKey?Lib?"user32"?Alias?"MapVirtualKeyA"?(ByVal?wCode?As?Long,?ByVal?wMapType?As?Long)?As?Long

Function?MakeKeyLparam(ByVal?VirtualKey?As?Long,?ByVal?flag?As?Long)?As?Long
'參數(shù)VirtualKey表示按鍵虛擬碼,flag表示是按下鍵還是釋放鍵,用WM_KEYDOWN和WM_KEYUP這兩個(gè)常數(shù)表示
????Dim?s?As?String
????Dim?Firstbyte?As?String????'lparam參數(shù)的24-31位
????If?flag?=?WM_KEYDOWN??Then?'如果是按下鍵
????????Firstbyte?=?"00"
????Else
????????Firstbyte?=?"C0"???????'如果是釋放鍵
????End?If
????Dim?Scancode?As?Long
????'獲得鍵的掃描碼
????Scancode?=?MapVirtualKey(VirtualKey,?0)
????Dim?Secondbyte?As?String???'lparam參數(shù)的16-23位,即虛擬鍵掃描碼
????Secondbyte?=?Right("00"?&?Hex(Scancode),?2)
????s?=?Firstbyte?&?Secondbyte?&?"0001"??'0001為lparam參數(shù)的0-15位,即發(fā)送次數(shù)和其它擴(kuò)展信息
????MakeKeyLparam?=?Val("&H"?&?s)
End?Function

這 個(gè)函數(shù)像這樣調(diào)用,比如按下A鍵,那么lParam=MakeKeyLparam(VK_A,WM_KEYDOWN)?,很簡(jiǎn)單吧。值得注意的是,即使你 發(fā)送消息時(shí)設(shè)置了lParam參數(shù)的值,但是系統(tǒng)在傳遞消息時(shí)仍然可能會(huì)根據(jù)當(dāng)時(shí)的情況重新設(shè)置該參數(shù),那么目標(biāo)程序收到的消息中l(wèi)Param的值可能會(huì) 和你發(fā)送時(shí)的有所不同。所以,如果你很懶的話,還是直接把它設(shè)為0吧,對(duì)大多數(shù)程序不會(huì)有影響的,呵呵。
????好了,做完以上的事情,現(xiàn)在我們可以向目標(biāo)程序發(fā)送鍵盤(pán)消息了。首先取得目標(biāo)程序接受這個(gè)消息的控件的句柄,比如目標(biāo)句柄是12345,那么我們來(lái)對(duì)目標(biāo)模擬按下并釋放A鍵,像這樣:(為了簡(jiǎn)單起見(jiàn),lParam這個(gè)參數(shù)就不構(gòu)造了,直接傳0)
PostMessage?12345,WM_KEYDOWN,VK_A,0&???'按下A鍵
PostMessage?12345,WM_UP,VK_A,0&????????'釋放A鍵
好 了,一次按鍵就完成了?,F(xiàn)在你可以迫不及待的打開(kāi)記事本做實(shí)驗(yàn),先用FindWindowEx這類(lèi)API函數(shù)找到記事本程序的句柄,再向它發(fā)送鍵盤(pán)消息, 期望記事本里能詭異的自動(dòng)出現(xiàn)字符。可是你馬上就是失望了,咦,怎么一點(diǎn)反應(yīng)也沒(méi)有?你欺騙感情啊~~~~~~~~~~55555555555555?? 不是的哦,接著往下看啊。
一般目標(biāo)程序都會(huì)含有多個(gè)控件,并不是每個(gè)控件都會(huì)對(duì)鍵盤(pán)消息作出反應(yīng),只有把鍵盤(pán)消息發(fā)送給接受它的控件才會(huì)得到期望 的反應(yīng)。那記事本來(lái)說(shuō),它的編輯框其實(shí)是個(gè)edit類(lèi),只有這個(gè)控件才對(duì)鍵盤(pán)事件有反應(yīng),如果只是把消息發(fā)給記事本的窗體,那是沒(méi)有用的?,F(xiàn)在你找出記事 本那個(gè)編輯框的句柄,比如是54321,那么寫(xiě)如下代碼:
PostMessage?54321,WM_KEYDOWN,VK_F1,0&???'按下F1鍵
PostMessage?54321,WM_UP,VK_F1,0&????????'釋放F1鍵
怎么樣,是不是打開(kāi)了記事本的“幫助”信息?這說(shuō)明目標(biāo)程序已經(jīng)收到了你發(fā)的消息,還不錯(cuò)吧~~~~~~~~
可以馬上新問(wèn)題就來(lái)了,你想模擬向記事本按下A這個(gè)鍵,好在記事本里自動(dòng)輸入字符,可是,沒(méi)有任何反應(yīng)!這是怎么一回事呢?
原 來(lái),如果要向目標(biāo)程序發(fā)送字符,光靠WM_KEYDOWN和WM_UP這兩個(gè)事件還不行,還需要一個(gè)事件:WM_CHAR,這個(gè)消息表示一個(gè)字符,程序需 靠它看來(lái)接受輸入的字符。一般只有A,B,C等這樣的按鍵才有WM_CHAR消息,別的鍵(比如方向鍵和功能鍵)是沒(méi)有這個(gè)消息的,WM_CHAR消息一 般發(fā)生在WM_KEYDOWN消息之后。WM_CHAR消息的lParam參數(shù)的含義與其它鍵盤(pán)消息一樣,而它的wParam則表示相應(yīng)字符的ASCII 編碼(可以輸入中文的哦^_^),現(xiàn)在你可以寫(xiě)出一個(gè)完整的向記事本里自動(dòng)寫(xiě)入字符的程序了,下面是一個(gè)例子,并附有這些消息常數(shù)的具體值:
Declare?Function?PostMessage?Lib?"user32"?Alias?"PostMessageA"?(ByVal?hwnd?As?Long,?ByVal?wMsg?As?Long,?ByVal?wParam?As?Long,?lParam?As?Any)?As?Long
Declare?Function?MapVirtualKey?Lib?"user32"?Alias?"MapVirtualKeyA"?(ByVal?wCode?As?Long,?ByVal?wMapType?As?Long)?As?Long

Public?Const?WM_KEYDOWN?=?&H100
Public?Const?WM_KEYUP?=?&H101
Public?Const?WM_CHAR?=?&H102
Public?Const?VK_A?=?&H41?

Function?MakeKeyLparam(ByVal?VirtualKey?As?Long,?ByVal?flag?As?Long)?As?Long
????Dim?s?As?String
????Dim?Firstbyte?As?String????'lparam參數(shù)的24-31位
????If?flag?=?WM_KEYDOWN??Then?'如果是按下鍵
????????Firstbyte?=?"00"
????Else
????????Firstbyte?=?"C0"???????'如果是釋放鍵
????End?If
????Dim?Scancode?As?Long
????'獲得鍵的掃描碼
????Scancode?=?MapVirtualKey(VirtualKey,?0)
????Dim?Secondbyte?As?String???'lparam參數(shù)的16-23位,即虛擬鍵掃描碼
????Secondbyte?=?Right("00"?&?Hex(Scancode),?2)
????s?=?Firstbyte?&?Secondbyte?&?"0001"??'0001為lparam參數(shù)的0-15位,即發(fā)送次數(shù)和其它擴(kuò)展信息
????MakeKeyLparam?=?Val("&H"?&?s)
End?Function

Private?Sub?Form_Load()
????dim?hwnd?as?long
????hwnd?=?XXXXXX??'XXXXX表示記事本編輯框的句柄
????PostMessage?hwnd,WM_KEYDOWN,VK_A,MakeKeyLparam(VK_A,WM_KEYDOWN)??'按下A鍵
????PostMessage?hwnd,WM_CHAR,ASC("A"),MakeKeyLparam(VK_A,WM_KEYDOWN)??'輸入字符A
????PostMessage?hwnd,WM_UP,VK_A,MakeKeyLparam(VK_A,WM_UP)???????'釋放A鍵
End?Sub

這 就是通過(guò)局部鍵盤(pán)消息來(lái)模擬按鍵。這個(gè)方法有一個(gè)極大的好處,就是:它可以實(shí)現(xiàn)后臺(tái)按鍵,也就是說(shuō)他對(duì)你的前臺(tái)操作不會(huì)有什么影響。比如,你可以用這個(gè)方 法做個(gè)程序在游戲中模擬按鍵來(lái)不斷地執(zhí)行某些重復(fù)的操作,而你則一邊喝茶一邊與QQ上的MM們聊得火熱,它絲毫不會(huì)影響你的前臺(tái)操作。無(wú)論目標(biāo)程序是否獲 得焦點(diǎn)都沒(méi)有影響,這就是后臺(tái)模擬按鍵的原理啦~~~~


2.全局級(jí)模擬

????你會(huì)發(fā)現(xiàn),用上面的方法模擬按鍵并不 是對(duì)所有程序都有效的,有的程序啊,你向它發(fā)了一大堆消息,可是它卻一點(diǎn)反應(yīng)也沒(méi)有。這是怎么回事呢?這就要看具體的情況了,有些程序(特別是一些游戲) 出于某些原因,會(huì)禁止用戶對(duì)它使用模擬按鍵程序,這個(gè)怎么實(shí)現(xiàn)呢?比如可以在程序中檢查一下,如果發(fā)現(xiàn)自己不是活動(dòng)窗口,就不接受鍵盤(pán)消息?;蛘咦屑?xì)檢查 一下收到的鍵盤(pán)消息,你會(huì)發(fā)現(xiàn)真實(shí)的按鍵和模擬的按鍵消息總是有一些小差別,從這些小差別上,目標(biāo)程序就能判斷出:這是假的!是偽造的?。∫虼耍绻? PostMessage發(fā)送局部消息模擬按鍵不成功的話,你可以試一試全局級(jí)的鍵盤(pán)消息,看看能不能騙過(guò)目標(biāo)程序。
模擬全局鍵盤(pán)消息常見(jiàn)的可以有以下一些方法:
(1)?用API函數(shù)keybd_event,這個(gè)函數(shù)可以用來(lái)模擬一個(gè)鍵盤(pán)事件,它的VB聲明為:
Declare?Sub?keybd_event?Lib?"user32"?(ByVal?bVk?As?Byte,?ByVal?bScan?As?Byte,?ByVal?dwFlags?As?Long,?ByVal?dwExtraInfo?As?Long)
參數(shù)bVk表示要模擬的按鍵的虛擬碼,bScan表示該按鍵的掃描碼(一般可以傳0),dwFlags表示是按下鍵還是釋放鍵(按下鍵為0,釋放鍵為2),dwExtraInfo是擴(kuò)展標(biāo)志,一般沒(méi)有用。比如要模擬按下A鍵,可以這樣:
Const?KEYEVENTF_KEYUP?=?&H2
keybd_event?VK_A,?0,?0,?0???'按下A鍵
keybd_event?VK_A,?0,?KEYEVENTF_KEYUP,?0???'釋放A鍵
注意有時(shí)候按鍵的速度不要太快,否則會(huì)出問(wèn)題,可以用API函數(shù)Sleep來(lái)進(jìn)行延時(shí),聲明如下:
Declare?Sub?Sleep?Lib?"kernel32"?(ByVal?dwMilliseconds?As?Long)
參數(shù)dwMilliseconds表示延時(shí)的時(shí)間,以毫秒為單位。
那么如果要模擬按下功能鍵怎么做呢?比如要按下Ctrl+C實(shí)現(xiàn)拷貝這個(gè)功能,可以這樣:
keybd_event?VK_Ctrl,?0,?0,?0???'按下Ctrl鍵
keybd_event?VK_C,?0,?0,?0??????'按下C鍵
Sleep?500????????????'延時(shí)500毫秒
keybd_event?VK_C,?0,?KEYEVENTF_KEYUP,?0???'釋放C鍵
keybd_event?VK_Ctrl,?0,?KEYEVENTF_KEYUP,?0???'釋放Ctrl鍵
好 了,現(xiàn)在你可以試試是不是可以騙過(guò)目標(biāo)程序了,這個(gè)函數(shù)對(duì)大部分的窗口程序都有效,可是仍然有一部分游戲?qū)λa(chǎn)生的鍵盤(pán)事件熟視無(wú)睹,這時(shí)候,你就要用上 bScan這個(gè)參數(shù)了。一般的,bScan都傳0,但是如果目標(biāo)程序是一些DirectX游戲,那么你就需要正確使用這個(gè)參數(shù)傳入掃描碼,用了它可以產(chǎn)生 正確的硬件事件消息,以被游戲識(shí)別。這樣的話,就可以寫(xiě)成這樣:
keybd_event?VK_A,?MapVirtualKey(VK_A,?0),?0,?0???'按下A鍵
keybd_event?VK_A,?MapVirtualKey(VK_A,?0),?KEYEVENTF_KEYUP,?0???'釋放A鍵
以上就是用keybd_event函數(shù)來(lái)模擬鍵盤(pán)事件。除了這個(gè)函數(shù),SendInput函數(shù)也可以模擬全局鍵盤(pán)事件。SendInput可以直接把一條消息插入到消息隊(duì)列中,算是比較底層的了。它的VB聲明如下:
Declare?Function?SendInput?Lib?"user32.dll"?(ByVal?nInputs?As?Long,?pInputs?As?GENERALINPUT,?ByVal?cbSize?As?Long)?As?Long
參數(shù):?
nlnprts:定義plnputs指向的結(jié)構(gòu)的數(shù)目。
plnputs:指向INPUT結(jié)構(gòu)數(shù)組的指針。每個(gè)結(jié)構(gòu)代表插人到鍵盤(pán)或鼠標(biāo)輸入流中的一個(gè)事件。
cbSize:定義INPUT結(jié)構(gòu)的大小。若cbSize不是INPUT結(jié)構(gòu)的大小,則函數(shù)調(diào)用失敗。
返回值:函數(shù)返回被成功地插人鍵盤(pán)或鼠標(biāo)輸入流中的事件的數(shù)目。若要獲得更多的錯(cuò)誤信息,可以調(diào)用GetlastError函數(shù)。
備注:Sendlnput函數(shù)將INPUT結(jié)構(gòu)中的事件順序地插入鍵盤(pán)或鼠標(biāo)的輸入流中。這些事件與用戶插入的(用鼠標(biāo)或鍵盤(pán))或調(diào)用keybd_event,mouse_event,或另外的Sendlnput插人的鍵盤(pán)或鼠標(biāo)的輸入流不兼容。
嗯,這個(gè)函數(shù)用起來(lái)蠻復(fù)雜的,因?yàn)樗膮?shù)都是指針一類(lèi)的東西。要用它來(lái)模擬鍵盤(pán)輸入,先要構(gòu)造一組數(shù)據(jù)結(jié)構(gòu),把你要模擬的鍵盤(pán)消息裝進(jìn)去,然后傳給它。為了方便起見(jiàn),把它做在一個(gè)過(guò)程里面,要用的時(shí)候直接調(diào)用好了,代碼如下:
Declare?Function?SendInput?Lib?"user32.dll"?(ByVal?nInputs?As?Long,?pInputs?As?GENERALINPUT,?ByVal?cbSize?As?Long)?As?Long
Declare?Sub?CopyMemory?Lib?"kernel32"?Alias?"RtlMoveMemory"?(pDst?As?Any,?pSrc?As?Any,?ByVal?ByteLen?As?Long)
?Type?GENERALINPUT
???dwType?As?Long
???xi(0?To?23)?As?Byte
?End?Type

?Type?KEYBDINPUT
??wVk?As?Integer
??wScan?As?Integer
??dwFlags?As?Long
??time?As?Long
??dwExtraInfo?As?Long
?End?Type

Const?INPUT_KEYBOARD?=?1

Sub?MySendKey(bkey?As?Long)
'參數(shù)bkey傳入要模擬按鍵的虛擬碼即可模擬按下指定鍵
Dim?GInput(0?To?1)?As?GENERALINPUT
Dim?KInput?As?KEYBDINPUT
?KInput.wVk?=?bkey??'你要模擬的按鍵
?KInput.dwFlags?=?0?'按下鍵標(biāo)志
?GInput(0).dwType?=?INPUT_KEYBOARD
?CopyMemory?GInput(0).xi(0),?KInput,?Len(KInput)?'這個(gè)函數(shù)用來(lái)把內(nèi)存中KInput的數(shù)據(jù)復(fù)制到GInput
?KInput.wVk?=?bkey??
?KInput.dwFlags?=?KEYEVENTF_KEYUP??'?釋放按鍵
?GInput(1).dwType?=?INPUT_KEYBOARD?'?表示該消息為鍵盤(pán)消息
?CopyMemory?GInput(1).xi(0),?KInput,?Len(KInput)
'以上工作把按下鍵和釋放鍵共2條鍵盤(pán)消息加入到GInput數(shù)據(jù)結(jié)構(gòu)中
?SendInput?2,?GInput(0),?Len(GInput(0))????'把GInput中存放的消息插入到消息列隊(duì)
End?Sub

???? 除了以上這些,用全局鉤子也可以模擬鍵盤(pán)消息。如果你對(duì)windows中消息鉤子的用法已經(jīng)有所了解,那么你可以通過(guò)設(shè)置一個(gè)全局HOOK來(lái)模擬鍵盤(pán)消 息,比如,你可以用WH_JOURNALPLAYBACK這個(gè)鉤子來(lái)模擬按鍵。WH_JOURNALPLAYBACK是一個(gè)系統(tǒng)級(jí)的全局鉤子,它和 WH_JOURNALRECORD的功能是相對(duì)的,常用它們來(lái)記錄并回放鍵盤(pán)鼠標(biāo)操作。WH_JOURNALRECORD鉤子用來(lái)將鍵盤(pán)鼠標(biāo)的操作忠實(shí)地 記錄下來(lái),記錄下來(lái)的信息可以保存到文件中,而WH_JOURNALPLAYBACK則可以重現(xiàn)這些操作。當(dāng)然亦可以單獨(dú)使用 WH_JOURNALPLAYBACK來(lái)模擬鍵盤(pán)操作。你需要首先聲明SetWindowsHookEx函數(shù),它可以用來(lái)安裝消息鉤子:
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
先 安裝WH_JOURNALPLAYBACK這個(gè)鉤子,然后你需要自己寫(xiě)一個(gè)鉤子函數(shù),在系統(tǒng)調(diào)用它時(shí),把你要模擬的事件傳遞給鉤子參數(shù)lParam所指向 的EVENTMSG區(qū)域,就可以達(dá)到模擬按鍵的效果。不過(guò)用這個(gè)鉤子模擬鍵盤(pán)事件有一個(gè)副作用,就是它會(huì)鎖定真實(shí)的鼠標(biāo)鍵盤(pán),不過(guò)如果你就是想在模擬的時(shí) 候不會(huì)受真實(shí)鍵盤(pán)操作的干擾,那么用用它倒是個(gè)不錯(cuò)的主意。
3.驅(qū)動(dòng)級(jí)模擬

????如果上面的方法你都試過(guò)了,可是你發(fā)現(xiàn)目標(biāo)程序卻仍然頑固的不接受你模擬的消息,寒~~~~~~~~~還好,我還剩下最后一招,這就是驅(qū)動(dòng)級(jí)模擬:直接讀寫(xiě)鍵盤(pán)的硬件端口!
???? 有一些使用DirectX接口的游戲程序,它們?cè)谧x取鍵盤(pán)操作時(shí)繞過(guò)了windows的消息機(jī)制,而使用DirectInput.這是因?yàn)橛行┯螒驅(qū)?shí)時(shí) 性控制的要求比較高,比如賽車(chē)游戲,要求以最快速度響應(yīng)鍵盤(pán)輸入。而windows消息由于是隊(duì)列形式的,消息在傳遞時(shí)會(huì)有不少延遲,有時(shí)1秒鐘也就傳遞 十幾條消息,這個(gè)速度達(dá)不到游戲的要求。而DirectInput則繞過(guò)了windows消息,直接與鍵盤(pán)驅(qū)動(dòng)程序打交道,效率當(dāng)然提高了不少。因此也就 造成,對(duì)這樣的程序無(wú)論用PostMessage或者是keybd_event都不會(huì)有反應(yīng),因?yàn)檫@些函數(shù)都在較高層。對(duì)于這樣的程序,只好用直接讀寫(xiě)鍵 盤(pán)端口的方法來(lái)模擬硬件事件了。要用這個(gè)方法來(lái)模擬鍵盤(pán),需要先了解一下鍵盤(pán)編程的相關(guān)知識(shí)。
????在DOS時(shí)代,當(dāng)用戶按下或者放開(kāi)一個(gè)鍵 時(shí),就會(huì)產(chǎn)生一個(gè)鍵盤(pán)中斷(如果鍵盤(pán)中斷是允許的),這樣程序會(huì)跳轉(zhuǎn)到BIOS中的鍵盤(pán)中斷處理程序去執(zhí)行。打開(kāi)windows的設(shè)備管理器,可以查看到 鍵盤(pán)控制器由兩個(gè)端口控制。其中&H60是數(shù)據(jù)端口,可以讀出鍵盤(pán)數(shù)據(jù),而&H64是控制端口,用來(lái)發(fā)出控制信號(hào)。也就是,從& H60號(hào)端口可以讀此鍵盤(pán)的按鍵信息,當(dāng)從這個(gè)端口讀取一個(gè)字節(jié),該字節(jié)的低7位就是按鍵的掃描碼,而高1位則表示是按下鍵還是釋放鍵。當(dāng)按下鍵時(shí),最高 位為0,稱為通碼,當(dāng)釋放鍵時(shí),最高位為1,稱為斷碼。既然從這個(gè)端口讀數(shù)據(jù)可以獲得按鍵信息,那么向這個(gè)端口寫(xiě)入數(shù)據(jù)就可以模擬按鍵了!用過(guò) QbASIC4.5的朋友可能知道,QB中有個(gè)OUT命令可以向指定端口寫(xiě)入數(shù)據(jù),而INP函數(shù)可以讀取指定端口的數(shù)據(jù)。那我們先看看如果用QB該怎么寫(xiě) 代碼:
假如你想模擬按下一個(gè)鍵,這個(gè)鍵的掃描碼為&H50,那就這樣
OUT?&H64,&HD2???'把數(shù)據(jù)&HD2發(fā)送到&H64端口。這是一個(gè)KBC指令,表示將要向鍵盤(pán)寫(xiě)入數(shù)據(jù)
OUT?&H60,&H50???'把掃描碼&H50發(fā)送到&H60端口,表示模擬按下掃描碼為&H50的這個(gè)鍵
那么要釋放這個(gè)鍵呢?像這樣,發(fā)送該鍵的斷碼:
OUT?&H64,&HD2???'把數(shù)據(jù)&HD2發(fā)送到&H64端口。這是一個(gè)KBC指令,表示將要向鍵盤(pán)寫(xiě)入數(shù)據(jù)
OUT?&H60,(&H50?OR?&H80)???'把掃描碼&H50與數(shù)據(jù)&H80進(jìn)行或運(yùn)算,可以把它的高位置1,得到斷碼,表示釋放這個(gè)鍵
???? 好了,現(xiàn)在的問(wèn)題就是在VB中如何向端口寫(xiě)入數(shù)據(jù)了。因?yàn)樵趙indows中,普通應(yīng)用程序是無(wú)權(quán)操作端口的,于是我們就需要一個(gè)驅(qū)動(dòng)程序來(lái)幫助我們實(shí) 現(xiàn)。在這里我們可以使用一個(gè)組件WINIO來(lái)完成讀寫(xiě)端口操作。什么是WINIO?WINIO是一個(gè)全免費(fèi)的、無(wú)需注冊(cè)的、含源程序的 WINDOWS2000端口操作驅(qū)動(dòng)程序組件(可以到http://www.internals.com/上 去下載)。它不僅可以操作端口,還可以操作內(nèi)存;不僅能在VB下用,還可以在DELPHI、VC等其它環(huán)境下使用,性能特別優(yōu)異。下載該組件,解壓縮后可 以看到幾個(gè)文件夾,其中Release文件夾下的3個(gè)文件就是我們需要的,這3個(gè)文件是WinIo.sys(用于win?xp下的驅(qū)動(dòng)程序), WINIO.VXD(用于win?98下的驅(qū)動(dòng)程序),WinIo.dll(封裝函數(shù)的動(dòng)態(tài)鏈接庫(kù)),我們只需要調(diào)用WinIo.dll中的函數(shù),然后 WinIo.dll就會(huì)安裝并調(diào)用驅(qū)動(dòng)程序來(lái)完成相應(yīng)的功能。值得一提的是這個(gè)組件完全是綠色的,無(wú)需安裝,你只需要把這3個(gè)文件復(fù)制到與你的程序相同的 文件夾下就可以使用了。用法很簡(jiǎn)單,先用里面的InitializeWinIo函數(shù)安裝驅(qū)動(dòng)程序,然后就可以用GetPortVal來(lái)讀取端口或者用 SetPortVal來(lái)寫(xiě)入端口了。好,讓我們來(lái)做一個(gè)驅(qū)動(dòng)級(jí)的鍵盤(pán)模擬吧。先把winio的3個(gè)文件拷貝到你的程序的文件夾下,然后在VB中新建一個(gè)工 程,添加一個(gè)模塊,在模塊中加入下面的winio函數(shù)聲明:

Declare?Function?MapPhysToLin?Lib?"WinIo.dll"?(ByVal?PhysAddr?As?Long,?ByVal?PhysSize?As?Long,?ByRef?PhysMemHandle)?As?Long
Declare?Function?UnmapPhysicalMemory?Lib?"WinIo.dll"?(ByVal?PhysMemHandle,?ByVal?LinAddr)?As?Boolean
Declare?Function?GetPhysLong?Lib?"WinIo.dll"?(ByVal?PhysAddr?As?Long,?ByRef?PhysVal?As?Long)?As?Boolean
Declare?Function?SetPhysLong?Lib?"WinIo.dll"?(ByVal?PhysAddr?As?Long,?ByVal?PhysVal?As?Long)?As?Boolean
Declare?Function?GetPortVal?Lib?"WinIo.dll"?(ByVal?PortAddr?As?Integer,?ByRef?PortVal?As?Long,?ByVal?bSize?As?Byte)?As?Boolean
Declare?Function?SetPortVal?Lib?"WinIo.dll"?(ByVal?PortAddr?As?Integer,?ByVal?PortVal?As?Long,?ByVal?bSize?As?Byte)?As?Boolean
Declare?Function?InitializeWinIo?Lib?"WinIo.dll"?()?As?Boolean
Declare?Function?ShutdownWinIo?Lib?"WinIo.dll"?()?As?Boolean
Declare?Function?InstallWinIoDriver?Lib?"WinIo.dll"?(ByVal?DriverPath?As?String,?ByVal?Mode?As?Integer)?As?Boolean
Declare?Function?RemoveWinIoDriver?Lib?"WinIo.dll"?()?As?Boolean

'?------------------------------------以上是WINIO函數(shù)聲明-------------------------------------------

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

'-----------------------------------以上是WIN32?API函數(shù)聲明-----------------------------------------

再添加下面這個(gè)過(guò)程:
Sub?KBCWait4IBE()???'等待鍵盤(pán)緩沖區(qū)為空
Dim?dwVal?As?Long
??Do
??GetPortVal?&H64,?dwVal,?1
'這句表示從&H64端口讀取一個(gè)字節(jié)并把讀出的數(shù)據(jù)放到變量dwVal中
'GetPortVal函數(shù)的用法是GetPortVal?端口號(hào),存放讀出數(shù)據(jù)的變量,讀入的長(zhǎng)度
??Loop?While?(dwVal?And?&H2)
End?Sub
上面的是一個(gè)根據(jù)KBC規(guī)范寫(xiě)的過(guò)程,它的作用是在向鍵盤(pán)端口寫(xiě)入數(shù)據(jù)前等待一段時(shí)間,后面將會(huì)用到。
然后再添加如下過(guò)程,這2個(gè)過(guò)程用來(lái)模擬按鍵:

Public?Const?KBC_KEY_CMD?=?&H64????'鍵盤(pán)命令端口
Public?Const?KBC_KEY_DATA?=?&H60???'鍵盤(pán)數(shù)據(jù)端口

Sub?MyKeyDown(ByVal?vKeyCoad?As?Long)???
'這個(gè)用來(lái)模擬按下鍵,參數(shù)vKeyCoad傳入按鍵的虛擬碼
Dim?btScancode?As?Long
btScancode?=?MapVirtualKey(vKeyCoad,?0)
??
????KBCWait4IBE???'發(fā)送數(shù)據(jù)前應(yīng)該先等待鍵盤(pán)緩沖區(qū)為空
????SetPortVal?KBC_KEY_CMD,?&HD2,?1?????'發(fā)送鍵盤(pán)寫(xiě)入命令
'SetPortVal函數(shù)用于向端口寫(xiě)入數(shù)據(jù),它的用法是SetPortVal?端口號(hào),欲寫(xiě)入的數(shù)據(jù),寫(xiě)入數(shù)據(jù)的長(zhǎng)度
????KBCWait4IBE
????SetPortVal?KBC_KEY_DATA,?btScancode,?1??'寫(xiě)入按鍵信息,按下鍵
????
End?Sub

?Sub?MyKeyUp(ByVal?vKeyCoad?As?Long)???
'這個(gè)用來(lái)模擬釋放鍵,參數(shù)vKeyCoad傳入按鍵的虛擬碼
Dim?btScancode?As?Long
btScancode?=?MapVirtualKey(vKeyCoad,?0)
??
????KBCWait4IBE???'等待鍵盤(pán)緩沖區(qū)為空
????SetPortVal?KBC_KEY_CMD,?&HD2,?1??'發(fā)送鍵盤(pán)寫(xiě)入命令
????KBCWait4IBE
????SetPortVal?KBC_KEY_DATA,?(btScancode?Or?&H80),?1??'寫(xiě)入按鍵信息,釋放鍵

End?Sub


定義了上面的過(guò)程后,就可以用它來(lái)模擬鍵盤(pán)輸入了。在窗體模塊中添加一個(gè)定時(shí)器控件,然后加入以下代碼:


Private?Sub?Form_Load()

?If?InitializeWinIo?=?False?Then???
??'用InitializeWinIo函數(shù)加載驅(qū)動(dòng)程序,如果成功會(huì)返回true,否則返回false
????MsgBox?"驅(qū)動(dòng)程序加載失敗!"
????Unload?Me
?End?If
Timer1.Interval=3000
Timer1.Enabled=True
End?Sub

Private?Sub?Form_Unload(Cancel?As?Integer)
?ShutdownWinIo?'程序結(jié)束時(shí)記得用ShutdownWinIo函數(shù)卸載驅(qū)動(dòng)程序
End?Sub

Private?Sub?Timer1_Timer()
Dim?VK_A?as?Long?=?&H41?
MyKeyDown?VK_A????
MyKeyUp?VK_A????'模擬按下并釋放A鍵
End?Sub
[/quote]
運(yùn)行上面的程序,就會(huì)每隔3秒鐘模擬按下一次A鍵,試試看,怎么樣,是不是對(duì)所有程序都有效果了?
需要注意的問(wèn)題:
要在VB的調(diào)試模式下使用WINIO,需要把那3個(gè)文件拷貝到VB的安裝目錄中。
鍵盤(pán)上有些鍵屬于擴(kuò)展鍵(比如鍵盤(pán)上的方向鍵就是擴(kuò)展鍵),對(duì)于擴(kuò)展鍵不應(yīng)該用上面的MyKeyDown和MyKeyUp過(guò)程來(lái)模擬,可以使用下面的2個(gè)過(guò)程來(lái)準(zhǔn)確模擬擴(kuò)展鍵:
[quote]Sub?MyKeyDownEx(ByVal?vKeyCoad?As?Long)???'模擬擴(kuò)展鍵按下,參數(shù)vKeyCoad是擴(kuò)展鍵的虛擬碼
Dim?btScancode?As?Long
btScancode?=?MapVirtualKey(vKeyCoad,?0)

????KBCWait4IBE???'等待鍵盤(pán)緩沖區(qū)為空
????SetPortVal?KBC_KEY_CMD,?&HD2,?1?????'發(fā)送鍵盤(pán)寫(xiě)入命令
????KBCWait4IBE
????SetPortVal?KBC_KEY_DATA,?&HE0,?1??'寫(xiě)入擴(kuò)展鍵標(biāo)志信息
????
????
????KBCWait4IBE???'等待鍵盤(pán)緩沖區(qū)為空
????SetPortVal?KBC_KEY_CMD,?&HD2,?1?????'發(fā)送鍵盤(pán)寫(xiě)入命令
????KBCWait4IBE
????SetPortVal?KBC_KEY_DATA,?btScancode,?1??'寫(xiě)入按鍵信息,按下鍵
????
????
End?Sub


Sub?MyKeyUpEx(ByVal?vKeyCoad?As?Long)???'模擬擴(kuò)展鍵彈起
Dim?btScancode?As?Long
btScancode?=?MapVirtualKey(vKeyCoad,?0)

????KBCWait4IBE???'等待鍵盤(pán)緩沖區(qū)為空
????SetPortVal?KBC_KEY_CMD,?&HD2,?1?????'發(fā)送鍵盤(pán)寫(xiě)入命令
????KBCWait4IBE
????SetPortVal?KBC_KEY_DATA,?&HE0,?1??'寫(xiě)入擴(kuò)展鍵標(biāo)志信息
????
????
????KBCWait4IBE???'等待鍵盤(pán)緩沖區(qū)為空
????SetPortVal?KBC_KEY_CMD,?&HD2,?1?????'發(fā)送鍵盤(pán)寫(xiě)入命令
????KBCWait4IBE
????SetPortVal?KBC_KEY_DATA,?(btScancode?Or?&H80),?1??'寫(xiě)入按鍵信息,釋放鍵
????
End?Sub
[/quote]
還 應(yīng)該注意的是,如果要從擴(kuò)展鍵轉(zhuǎn)換到普通鍵,那么普通鍵的KeyDown事件應(yīng)該發(fā)送兩次。也就是說(shuō),如果我想模擬先按下一個(gè)擴(kuò)展鍵,再按下一個(gè)普通鍵, 那么就應(yīng)該向端口發(fā)送兩次該普通鍵被按下的信息。比如,我想模擬先按下左方向鍵,再按下空格鍵這個(gè)事件,由于左方向鍵是擴(kuò)展鍵,空格鍵是普通鍵,那么流程 就應(yīng)該是這樣的:
[quote]MyKeyDownEx?VK_LEFT???'按下左方向鍵
Sleep?200?????????????'延時(shí)200毫秒
MyKeyUpEx?VK_LEFT?????'釋放左方向鍵

Sleep?500
MyKeyDown?VK_SPACE???'按下空格鍵,注意要發(fā)送兩次
MyKeyDown?VK_SPACE
Sleep?200
MyKeyUp?VK_SPACE?????'釋放空格鍵



好了,相信到這里,你的模擬按鍵程序也就差不多了,測(cè)試一下,是不是很有效呢,嘿嘿~~~~
WINIO組件的下載地址:http://www.114vip.com.cn/download/winio.zip
4.骨灰級(jí)模擬
????方法3算是很底層的模擬了,我現(xiàn)在還沒(méi)有發(fā)現(xiàn)有它模擬無(wú)效的程序。但是如果你用盡上面所有的方法,仍然無(wú)效的話,那么還有最后一個(gè)方法,絕對(duì)對(duì)任何程序都會(huì)有效,那就是:把鍵盤(pán)拿出來(lái),老老實(shí)實(shí)地按下去吧。~~~~

posted on 2007-08-12 13:50 旅途 閱讀(3260) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久网站免费| 久久不射2019中文字幕| 欧美在线看片| 久久中文字幕导航| 亚洲一区二区三区成人在线视频精品| 欧美极品欧美精品欧美视频| 91久久精品日日躁夜夜躁欧美| 国产精品二区在线| 欧美亚洲一级| 午夜在线精品偷拍| 亚洲精品视频在线| 亚洲女性喷水在线观看一区| 亚洲国产精品成人一区二区| 先锋资源久久| 国产综合色精品一区二区三区| 欧美成人午夜剧场免费观看| 久久精品国产第一区二区三区最新章节 | 在线观看av不卡| 亚洲国产精品电影在线观看| 欧美日韩成人精品| 久久嫩草精品久久久精品一| 久久精品国产免费观看| 亚洲国产老妈| 亚洲一区二区三区视频| 伊大人香蕉综合8在线视| 亚洲午夜精品一区二区| 亚洲国产精品传媒在线观看| 亚洲欧美精品中文字幕在线| 亚洲一区二区在线免费观看| 老司机aⅴ在线精品导航| 久久久久久午夜| 午夜国产精品视频| 老司机精品导航| 亚洲视频香蕉人妖| 欧美国产视频日韩| 欧美激情按摩在线| 在线看视频不卡| 久久网站热最新地址| 久久久综合免费视频| 欧美91大片| 免费不卡欧美自拍视频| 国产一区美女| 久久国产精品亚洲va麻豆| 性视频1819p久久| 国产精品一区二区久激情瑜伽 | 欧美日韩精品在线| 欧美黄色成人网| 亚洲片在线观看| 欧美日本精品在线| 日韩一区二区福利| 午夜久久久久久| 亚洲精品久久久久久久久久久久久 | 麻豆成人在线| 日韩图片一区| 亚洲精品系列| 在线视频欧美一区| 亚洲欧美日韩国产综合在线 | 亚洲综合导航| 久久久99爱| 欧美激情亚洲| 日韩午夜三级在线| 午夜亚洲伦理| 久久综合导航| 欧美亚一区二区| 国产一区二区三区四区老人| 亚洲国产日韩欧美在线动漫| 一区二区免费看| 久久精品亚洲一区二区三区浴池| 欧美搞黄网站| 亚洲一区二区三区中文字幕在线| 久久精品中文字幕一区| 欧美日韩精品久久| 国产自产女人91一区在线观看| 亚洲成色最大综合在线| 亚洲图片在区色| 久久综合九九| 一区二区日韩精品| 久久在线免费观看视频| 欧美视频在线免费| 在线观看一区二区视频| 亚洲一区二区三区精品在线| 美女精品在线观看| 一级日韩一区在线观看| 久久综合伊人77777麻豆| 国产精品高潮粉嫩av| 亚洲国产综合在线看不卡| 亚洲日本欧美天堂| 国产日韩欧美精品| 欧美黄色免费| 久久精品国产精品 | 欧美一区二区在线看| 精品二区久久| 9人人澡人人爽人人精品| 欧美亚洲日本网站| 欧美激情视频一区二区三区在线播放 | 久久国产精品久久国产精品| 亚洲国产精品欧美一二99| 亚洲欧美www| 欧美另类高清视频在线| 国内激情久久| 性一交一乱一区二区洋洋av| 亚洲精品综合久久中文字幕| 久久欧美肥婆一二区| 国产伦精品一区二区三区照片91| 日韩亚洲一区二区| 欧美成人午夜77777| 欧美亚洲日本国产| 国产精品免费一区二区三区在线观看| 亚洲精品中文在线| 欧美成人四级电影| 久久久久久久999| 国产色综合久久| 香蕉亚洲视频| 亚洲一区二区三区高清不卡| 欧美日韩免费一区| 亚洲经典三级| 欧美成人精品一区二区三区| 久久精品盗摄| 国产亚洲欧洲| 久久精品官网| 香蕉成人久久| 国产午夜精品一区二区三区视频| 亚洲一区精彩视频| av成人黄色| 欧美日韩一区二区视频在线| 99re热这里只有精品视频| 欧美国产日韩在线观看| 美女尤物久久精品| 亚洲激情欧美激情| 欧美国产日韩一区二区三区| 另类av一区二区| 亚洲国产婷婷综合在线精品| 欧美大片在线观看| 欧美xart系列高清| 亚洲精品日韩精品| 亚洲国产精品va在线观看黑人| 欧美aⅴ一区二区三区视频| 亚洲黄色免费| 亚洲人成网站777色婷婷| 欧美理论电影网| 亚洲新中文字幕| 亚洲一区欧美激情| 国产一区白浆| 可以免费看不卡的av网站| 久久综合999| 亚洲乱码国产乱码精品精天堂| 最新日韩精品| 国产精品黄视频| 欧美在线播放一区| 久久久久久久久一区二区| 亚洲福利在线视频| 亚洲级视频在线观看免费1级| 欧美日韩亚洲91| 欧美一区亚洲| 狼狼综合久久久久综合网| 亚洲精品综合久久中文字幕| 99这里只有精品| 国产欧美一区二区三区国产幕精品| 久久久久综合一区二区三区| 裸体女人亚洲精品一区| 夜夜嗨av一区二区三区网页| 亚洲一区二区三区四区在线观看| 好吊视频一区二区三区四区| 亚洲国产精品黑人久久久 | 夜夜精品视频一区二区| 亚洲欧美国产视频| 日韩午夜视频在线观看| 欧美日本亚洲| 亚洲美女区一区| 亚洲缚视频在线观看| 免费成人av资源网| 亚洲精品国久久99热| 欧美激情视频给我| 欧美经典一区二区三区| 国际精品欧美精品| 久久久xxx| 亚洲国产精品一区二区久 | 久久久久久综合网天天| 亚洲精品久久久久久久久久久久久| 亚洲乱码国产乱码精品精可以看| 国产精品久久久久久影视| 久久婷婷麻豆| 欧美精品久久久久久久久老牛影院| 亚洲欧美久久| 老司机午夜免费精品视频| 亚洲男同1069视频| 久久先锋资源| 午夜精品一区二区三区在线播放| 老司机凹凸av亚洲导航| 亚洲欧美在线免费| 鲁大师影院一区二区三区| 午夜精品久久久久久久99水蜜桃 | 亚洲男女自偷自拍图片另类| 精品69视频一区二区三区| 日韩视频精品| 在线欧美小视频| 亚洲女同精品视频| 日韩亚洲成人av在线| 久久国产精品99精品国产| 亚洲一区二区三区高清 |