程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> Windows按鍵突破專家的原理

Windows按鍵突破專家的原理

編輯:關於VC++

相信在window按鍵突破專家沒有出來的時候,很多人還不知道軟件還可以這樣編的吧,本人也是一樣,當知道有window按鍵突破專家這個軟件時,仔細去想一下它的實現原理,才突然恍然大悟,原來原理居然是這麼的簡單,為什麼以前我就沒有想到呢。

好了,不說那麼多廢話,直接進入主題,我先是說說按鍵突破的原理。實現按鍵突破的其實就是EnableWindow這個函數。

BOOL EnableWindow(
HWND hWnd,
BOOL bEnable
);

hWnd 指定將要啟用或者禁用的窗口的句柄;

bEnable 若為TRUE則啟用窗口,為FALSE則禁用窗口;

只要把EnableWindow的第二個參數設置為TRUE,第一個參數填控件的句柄就將原來被禁止的控件重新變為可用。

現在的主要的問題是怎麼得到控件的句柄,用vc++的朋友,應該都用過spy++這個強大的工具吧,它可以得到任意控件的句柄,和窗口的類名,看完這篇文章後,讀者們也可以自己做一個屬於自己的spy++啦。

先介紹一下RealChildWindowFromPoint這個函數。該函數的功能是用來獲取在指定點上的子窗口的句柄 :

HWND RealChildWindowFromPoint(
HWND hwndParent, // 父窗口的句柄
POINT ptParentClientCoords // 以客戶坐標指定的點
)

返回值 :

返回其子窗口句柄

RealChildWindowFromPoint函數只能夠查找到由 ptParentClientCoords 所得到的子窗口,但是無法得到最深層的窗口,也就是說如果有兩個窗口重疊,就無法見到下面的窗口,這樣的情況是經常出現的。

“第一個子窗口”的窗口和“最深層的窗口”的復選框窗口就重疊了,如果用 RealChildWindowFromPoint 就只能得到“第一個子窗口”的窗口,而無法的到“最深層的窗口”的復選框,所以只簡單的調用這個函數是無法實現Spy++的功能的。

大家來看看這個函數,這個函數會將鼠標所在的位置的窗口句柄賦予*phWnd。讀者下次想得實現spy++的功能就調用這個函數就可以了。

解釋一下,用GetCursorPos得到的鼠標位置,是屏幕的鼠標位置,比如你的分辨率為1024*768,GetCursorPos這個函數得到的就是在1024*768這個屏幕范圍的鼠標位置,而客戶區窗口坐標,指的是鼠標在一個窗口上的坐標,不同於屏幕坐標。

void GetRealWindow(HWND *phWnd)
{
 POINT ptPoint;
 HWND hWndTop = NULL;
 HWND hWndChild = NULL;
 POINT ptCooChild = {0};
 // 先得到ptPoint指向的(子)窗口,再通過子窗口得到父窗口的句柄
 GetCursorPos(&ptPoint);//得到鼠標的位置
 hWndTop = ::WindowFromPoint(ptPoint);//獲取鼠標包含指定點的窗口的句柄
 ptCooChild = ptPoint;
 *phWnd = GetParent(hWndTop); //用來獲取最上層的父窗口的句柄
 ::ScreenToClient(*phWnd, &ptCooChild);//該函數將屏幕的一個坐標轉換成客戶區(窗口)的坐標
 //從最上層的窗口開始外下找,只直到找到最地層的窗口
 while (TRUE){
  hWndChild = RealChildWindowFromPoint(*phWnd, ptCooChild);
  if (hWndChild && (hWndChild != *phWnd))
   *phWnd = hWndChild;
  else
   break;
 }
}

代碼不是很多,如果看不懂的話,不要緊,懂得調用這個函數就可以啦。

現在要再調用EnableWindow就可以了。

HWND s;
GetRealWindow(&s);
::EnableWindow(s,1);

如果只是運行一次這面的這些語句的話,還是不行的,必須在程序開啟突破功能的時候一直運行。

所以

while(1)
{
 GetRealWindow(&s);
 ::EnableWindow(s,1);
 Sleep(100);
}

但是,這樣的話,問題又來了,就是讓程序休息100毫秒,這個程序還是會把所以的cpu都占用完的,總不能因為這一個程序,而把資源的耗盡了,這是誰都不願意看到的,這時,就必須用到多線程了,對於多線程技術,很多文章都有介紹了的.我就不多說那麼多了。

DWORD WINAPI run(LPVOID l)
{
 while(k==1)
 {
  GetRealWindow(&s);
  ::EnableWindow(s,1);
  Sleep(100);
 }
 ExitThread(dwThreadID);
 return 1;
}

先把實現按鍵突破的語句放在一個新的函數裡。裡面的這個k,是個全句變量,先在“資源”中添加一個Button按鍵(只是為了說明問題,所以程序做得很簡單)。

void CJiandanwindowDlg::OnButton1()
{
 k=1;
 CreateThread(NULL,0,run,(LPVOID)i,0,&dwThreadID);
}

當按了一下Button時,就可以開始實現按鍵突破的功能了,仔細看一下,會發現這個程序和window按鍵突破專家有點不同,因為window按鍵突破專家在鼠標指向一個窗口時,就會將那個窗口下所有被禁止的控件都變成可用,而本程序,是鼠標指去哪個不可用的控件,那個控件就會編程可用,其他控件不受影響,如果想和window按鍵突破專家一樣的功能,其實也很簡單,只要改一下代碼就可以了,讀者們自己想想吧。

補充一點:這個程序不能直接在vc++下運行,因為源代碼將編譯不了,必須去微軟的老窩去下載最新的windows sdk,安裝以後,把所有的.h和.lib拷貝到vc++的相關目錄裡。windows sdk有許多有用的函數,建議用vc++的朋友都應該去下載。

程序在winxp、vc++6.0下通過編譯。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved