一、什麼是“QQ對戰平台擠房器”?
喜歡在“QQ對戰平台”或“浩方對戰平台”玩遊戲的人都知道。平常平台上的房間基本很多都是人滿的,如果想找個房間,那可是要費好長的時間來“擠”才能進去,如果是節假日或晚上,那更要花費更多的時間在“擠”房上了,如:
而對於“QQ對戰平台”,如果房間已滿擠不進去,卻變態的還會彈出兩次提示!平時,就只有拚命的按“斷行符號鍵”或“空格鍵”關閉這兩個討厭的快顯視窗,然後再用滑鼠點房間,如果房間還是進不去,就只能再按上面來一次迴圈……一次、兩次不是問題;五次、十次也許還不是問題;但如果十幾次或上百次還是擠不進去,還手按那就有問題了!當然,如果你喜歡手虐那就另外說了-_-#
我不喜歡手虐,所以當有次碰到N次還是擠不進去時,我就在想,為什麼不寫個工具來代替我的手,用工具自動去幫我“擠”房間,幫我點那兩個討厭的提示視窗呢?於是這篇文章中的“QQ對戰平台擠房器”就這樣誕生了(這可解放多少人的雙手啊,大家鼓掌……)
二、“擠房”要怎樣“擠”?
上面說了,“擠房器”就是幫我們自動“擠”房,但是它要怎麼幫我們“擠”呢?它畢竟是機器,而不是人,它不會自動一看到房間就幫我們“擠”,除非我們給它定製了一套規則(也可以叫命令)。機器就是機器,有規則它才會去做事,如果沒規則也會做事,那它就是“人”(智能機器人?)了。
這規則要怎樣定製?讓我們先來看看我們平時進入房間的流程,如:
好了,根據上面的流程,我們要給“擠房器”定製的規則就是分別以下幾條:
1)、點擊房間。
2)、判斷是否已進入房間,如果沒有進入房間,則負責將顯示房間滿的兩個討厭的提示視窗關閉掉,並重新回到第1步。
3)、已進入房間,則停止“擠”房動作。
三、自動“擠房”的實現。
這裡的實現,就是用代碼去實現上面定製的三個規則。
1、點擊房間:
在這裡我們簡單點,只是類比滑鼠去點擊滑鼠當前所在的房間。說到這裡,也許做過WINDOWS應用程式開發的朋友已想到了用哪幾個API函數去類比,對!就是以下幾個API的結合一起使用,就能實現滑鼠的類比點擊了。
1)、GetCursorPos : 擷取滑鼠的當前所在位置。
定義原型如下:
[DllImport("user32.dll")]
internal static extern bool GetCursorPos(out Point lpPoint);
此函數返回當前滑鼠所在的座標位置。
2)、mouse_event : 滑鼠事件的類比
定義原型如下:
[DllImport("user32.dll", EntryPoint = "mouse_event")]
public static extern void mouse_event(
int dwFlags,
int dx,
int dy,
int dwData,
int dwExtraInfo
);
此函數通過不同的dwFlags參數定義,可以類比不同的滑鼠事件,如滑鼠左鍵的按下、彈起事件等。
結合以上兩個API函數,我們就能實現自動點擊滑鼠所在的房間"的效果了,類似如下代碼:
Point point;
if(Win32API.GetCursorPos(out point)){
//MouseAPI是對mouse_event API函數的一個簡單封裝。
MouseAPI.SendMouseEvent(MouseAPI.MouseEvents.LeftButtonDown | MouseAPI.MouseEvents.LeftButtonUp, point, true);
}
但是上面的代碼是非常“機械”的,也即是不管當前滑鼠所在的視窗是不是在房間上,它都會自動“點擊”一次!這樣可不人性化,所以我們再改進一下,點擊時先判斷當前滑鼠停留的是不是在對戰平台的房間上,但可惜的QQ對戰平台的房間不是標準WINDOWS控制項,所以無法擷取到房間的資料,最後只好簡單點判斷滑鼠停留的視窗是不是QQ對戰平台的大廳,因為大廳是可擷取到的WINDOWS視窗控制項,如是用Spy++擷取到的大廳資料:
也就是我們判斷滑鼠停留的視窗的類型是不是屬於“Afx:400000:3”即可,如果是則表明滑鼠是停留在QQ對戰平台的遊戲大廳中的,就可以點擊房間了(注意:這裡停留的位置不一定是房間上,但這不影響使用,所以我就沒加以處理了)
這裡需要使用的API有:
3)、WindowFromPoint : 擷取某個座標位置所在的視窗
定義原型如下:
[DllImport("user32.dll")]
internal static extern IntPtr WindowFromPoint(Point Point);
4)、GetClassName : 擷取某個視窗的類型名稱
定義原形如下:
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern int GetClassName(IntPtr hWnd, StringBuilder buf, int nMaxCount);
加入上面的條件判斷,上面的代碼改進後如下:
if (Win32API.GetCursorPos(out point)){ hwnd = Win32API.WindowFromPoint(point); if (hwnd != IntPtr.Zero) { string className = Win32API.GetWindowClassName(hwnd); if (className.Equals("Afx:400000:3")) { MouseAPI.SendMouseEvent(MouseAPI.MouseEvents.LeftButtonDown | MouseAPI.MouseEvents.LeftButtonUp, point, true); } }}
這樣“點擊房間”這步就可以算完美了,當滑鼠不在房間(正確的說不在遊戲大廳)上停留時,滑鼠也不會亂點,這就方便在“擠房間”時隨時可以切換視窗了。
2、判斷是否已進入房間,如果沒有進入房間,則負責將顯示房間滿的兩個討厭的提示視窗關閉掉。
1)判斷是否已進入房間: 和上面那步判斷滑鼠是否停留在遊戲大廳一樣,也是判斷滑鼠是否停留在聊天室中,如果是那麼就表示已擠進去了。用Spy++擷取到聊天室的視窗類別型分別是“RichEdit20A”和“Afx:44a0000:0” ,所以判斷代碼如下:
//判斷滑鼠是否停留在聊天視窗上if (Win32API.GetCursorPos(out point)){ hwnd = Win32API.WindowFromPoint(point); if (hwnd != IntPtr.Zero) { string className = Win32API.GetWindowClassName(hwnd); if (className.Equals("RichEdit20A") || className.Equals("Afx:44a0000:0")) { isOk = true; } }}
如果isOk=true則表示已擠進房間。則就可以停止“擠房”,否則就要處理那兩個討厭的提示視窗了。
2)關閉提示視窗:
先需要判斷是否有這兩個提示視窗出現,因為在擠房過程中,QQ對戰平台會優先顯示一個進度條(視窗)。我們為了簡單點處理,只是判斷當前使用中視窗是否是“提示視窗”即可,也即是簡單的判斷當前使用中視窗中是否包含那個“確定”按鈕,如果存在,那麼就簡單的認為這視窗是那提示視窗,關閉它即可。需要用到的API函數有以下幾個:
A、GetForegroundWindow : 擷取當前使用中視窗
它的定義原形:
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
B、FindWindowEx : 尋找某個視窗
它的定義原型:
[DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
關閉提示視窗,則只使用簡單的方法,也即是發送“斷行符號鍵”即可,因為我們擷取到的視窗是當前使用中視窗,並且又是強制回應視窗,所以它能接受鍵盤訊息。關於鍵盤的類比,請參考我的這篇文章《C#對遊戲手柄的編程開發-API篇(3)》。
最後代碼如下:
if (!isOk){ //沒有擠進去,則判斷是否有提示視窗彈出,有的話關閉掉它 hwnd = Win32API.GetForegroundWindow(); if (hwnd != IntPtr.Zero) { //尋找使用中視窗是否包含有"確定"按鈕 IntPtr buttonHwnd = Win32API.FindWindowEx(hwnd, IntPtr.Zero, "Button", null); if (buttonHwnd != IntPtr.Zero) { KeyboardAPI.SendKeyEvent(Keys.Enter, KeyboardAPI.KeyboardEvents.KeyDown | KeyboardAPI.KeyboardEvents.KeyUp); } }}
isOk是上面判斷有沒有“擠”進去的值,如果沒有“擠”進去就進行上面的“關閉提示視窗”的操作,如果已“擠進去”則停止即可。
到此,將上面的所有代碼整合到一起,並加入到Timer的定時執行中,我們的“QQ對戰平台擠房器”就實現了。
以下提供者下載(不提供源碼,但你可以對其反編譯查看):
/Files/kingthy/QQBattleThruster.rar