我发现这两个函数的功能真的不是一般的有意思,贴上这两个函数函数原型:
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); } }