我發現這兩個函數的功能真的不是一般的有意思,貼上這兩個函數函數原型:
LONG WINAPI SetWindowLong( _In_ HWND hWnd, _In_ int nIndex, _In_ LONG dwNewLong ); LONG WINAPI GetWindowLong( _In_ HWND hWnd, _In_ int nIndex );
這兩個函數的資料在度娘上面也是不勝枚舉,同時本人在網絡上翻看了諸多大牛的文章,大家對這兩個函數的理解也都是入木三分。后來人便可綜合大家的總結,更方便的理解這兩個函數。但一是本人水平實在有限,二是為了不再給網絡增加負擔,所以本人決定理論的知識就不再贅述了,以免出現紕漏貽誤后來人。而是通過親身經歷的兩個小例子來展示一下這兩個函數的強大之處。
1.設置窗口的透明屬性。
這段代碼實現的功能就是讓我們電腦上的計算器再透明一點,本來是這樣的,然后我們寫個程序使其變成這個鬼樣子。
以SDK為例,我們新建一個默認工程,在默認工程的回調函數里,添加一個右鍵處理消息,當右鍵按下,獲取計算器的句柄,其中類名或者窗口名,可以通過VS自帶的SPY++獲得(32位和64位版本要對應),然后通過這兩個函數獲取窗口屬性,用SetLayeredWindowAttributes函數設置透明色。(前提是要打開計算器,使能夠獲取句柄成功)。代碼如下:
1 case WM_RBUTTONDOWN: 2 { 3 //獲取計算器窗口句柄(這里也可以設置QQ了,英雄聯盟了,等一系列窗口) 4 HWND hCalc=FindWindow(_T("CalcFrame"), NULL);//這個函數也是非常非常有意思的。 5 if (hCalc!=NULL) 6 { 7 //通過GetWindowLong獲得窗口的屬性 8 int ExdStyle = (int)GetWindowLong(hCalc, GWL_EXSTYLE); 9 //通過SetWindowLong設置窗口的屬性,多增加了一個WS_EX_LAYERED支持透明 10 SetWindowLong(hCalc, GWL_EXSTYLE, ExdStyle | WS_EX_LAYERED); 11 //設置窗口的透明色 12 SetLayeredWindowAttributes( 13 hCalc, RGB(255, 255, 255), 14 100, LWA_ALPHA);//100代表透明度,0是全透明,255是不透明 15 } 16 17 } 18 break;
2.改寫回調函數過濾消息。
比如改寫該進程下的回調函數,達到過濾右鍵按下的消息的目的
舊回調函數: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { //OldProc返回值是SetWindowLong原來的回調函數的地址 OldProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)NewProc); //程序主窗口此時的回調函數是NewProc而不是WndProc; } break; case WM_RBUTTONDOWN: { MessageBox(hWnd, _T("舊的窗口回調函數里"), _T("提示"), NULL); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } 新回調函數 LRESULT CALLBACK NewProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_RBUTTONDOWN: { MessageBox(hWnd, _T("新的窗口回調函數里"), _T("提示"), NULL); } return 0; //達到過濾消息后,恢復原來的回調函數,在OldProc中保存着 default: return CallWindowProc(OldProc, hWnd, message, wParam, lParam); } }