作者:superhackerlin E-mail:happyhunterlin@21cn.com
大家都知道,函数SetForegroundWindow用于切换前台窗口,但事实上它往往并未达到 我们想要的目的:SetForegroundWindow并不能用于和其他进程的窗口协同工作,通常 情况下SetForegroundWindow会调用FlashWindowEx来闪烁目标窗口,代表已经切换了 窗口,但事实上往往我们需要在某个时候将我们的窗口弹出到最前台来!曾听说过有高 手使用修改窗口切换的糸统规则来达到此目的,这样做未必太麻烦了,必定不是每个人 都是高手呢!下面给大家介绍一个"偏方",非常简单,只是利用了一个MSDN未公开的函数罢了. 好,come on ,follow me!
这个未公开的函数是:SwitchToThisWindow 它的c格式的原形是: void WINAPI SwitchToThisWindow ( HWND hWnd, // Handle to the window that should be activated BOOL bRestore // FAULS表示最小化显示; );
由于没有原型和库,我们在使用时通常用动态联接法: szUser32 db "user32.dll",0 szFuName db "SwitchToThisWindow",0 ...
invoke GetModuleHandle,addr szUser32 ;得到地址空间内user32.dll的模块句柄; mov hUser32,eax
invoke GetProcAddress,hUser32,addr szFuName ;得到SwitchToThisWindow的地址; mov FuAddr,eax
当想把窗口弹到最前台来时可以用如下语句:
push TRUE push hWnd ;窗口句柄 call FuAddr
下面是我写的一个例子程序,此程序会每隔五秒钟就弹到最前台来.此程序只在winxp下通过测试, 如在其他糸统下有问题的话请通知我!
.386 .model flat,stdcall option casemap:none include windows.inc include gdi32.inc includelib gdi32.lib include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib
.data? FuAddr dd ? hUser32 dd ? hInstance dd ? hWinMain dd ?
.const szClassName db 'MyClass',0 szCaptionMain db '前台窗口',0 szText db '前台窗口切换演示',0 szUser32 db "user32.DLL",0 szFuName db "SwitchToThisWindow",0
.code _ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam local @stPs:PAINTSTRUCT local @stRect:RECT local @hDc
mov eax,uMsg
.if eax == WM_PAINT invoke BeginPaint,hWnd,addr @stPs mov @hDc,eax invoke GetClientRect,hWnd,addr @stRect invoke DrawText,@hDc,addr szText,-1,addr @stRect,\ DT_SINGLELINE or DT_CENTER or DT_VCENTER invoke EndPaint,hWnd,addr @stPs .elseif eax == WM_CLOSE invoke DestroyWindow,hWinMain invoke PostQuitMessage,NULL .elseif eax == WM_TIMER ;注意此处调用SwitchToThisWindow! push TRUE push hWnd call FuAddr .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .endif xor eax,eax ret _ProcWinMain endp
_WinMain proc local @stWndClass:WNDCLASSEX local @stMsg:MSG invoke GetModuleHandle,NULL mov hInstance,eax invoke GetModuleHandle,addr szUser32 ;得到地址空间内user32.dll的模块句柄; mov hUser32,eax invoke GetProcAddress,hUser32,addr szFuName ;得到SwitchToThisWindow的地址; mov FuAddr,eax invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass invoke LoadCursor,0,IDC_ARROW mov @stWndClass.hCursor,eax push hInstance pop @stWndClass.hInstance mov @stWndClass.cbSize,sizeof WNDCLASSEX mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW mov @stWndClass.lpfnWndProc,offset _ProcWinMain mov @stWndClass.hbrBackground,COLOR_WINDOW + 1 mov @stWndClass.lpszClassName,offset szClassName invoke RegisterClassEx,addr @stWndClass
invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\ WS_OVERLAPPEDWINDOW,150,150,600,400,NULL,NULL,hInstance,NULL mov hWinMain,eax invoke ShowWindow,hWinMain,SW_SHOWNORMAL invoke UpdateWindow,hWinMain invoke SetTimer,hWinMain,1,5000,NULL ;设置一个计时器,每五秒钟调用一次
.while TRUE invoke GetMessage,addr @stMsg,NULL,0,0 .break .if eax == 0 invoke TranslateMessage,addr @stMsg invoke DispatchMessage,addr @stMsg .endw ret _WinMain endp
start: call _WinMain invoke ExitProcess,NULL end start
|