文章转自冰封的世界百度空间
我们都知道按win+D可以把所有的窗口最小化到任务栏上,今天我们不讨论这个功能,我们讨论一个类似的功能,一键把任务栏上的窗口隐藏
起来。比如按下ALT+D把任务栏上的窗口隐藏起来,再次按时,又显示成原来的样子。
我们来分析一下实现的过程和方法,因为在什么时候按下ALT+D键,都可以把窗口隐藏,所以要使用到系统钩子。
一、先创建Dll文件(先看具体文件代码,之后作解释):
Code
#include<windows.h> #include<stack> using namespace std;
extern "C"__declspec(dllexport) void sethook(); extern "C"__declspec(dllexport) void stophook();
#ifndef WH_KEYBOARD_LL #define WH_KEYBOARD_LL 13 #endif
HHOOK hook=NULL;//钩子句柄 stack<HWND> taskhwnd;//存任务栏上的窗口句柄 int flag=1;//标记,看是否显示或隐藏
typedef struct tagKBDLLHOOKSTRUCT { DWORD vkCode; DWORD scanCode; DWORD flags; DWORD time; DWORD dwExtraInfo; } KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
BOOL CALLBACK EnumTaskbarWnds(HWND hwnd,LPARAM lparam) { char lpClass[255];//存窗口类名 if(!GetWindow(hwnd,GW_OWNER)&&IsWindowVisible(hwnd)) { GetClassName(hwnd,lpClass,sizeof(lpClass));//获取窗口类名 if(strcmp(lpClass,"Progman")//滤掉桌面句柄 &&strcmp(lpClass,"Shell_TrayWnd")//滤掉任务栏本身 ) { HWND wnd=FindWindow(lpClass,NULL);//获取窗口句 ShowWindow(wnd,SW_HIDE); taskhwnd.push(wnd); } } return TRUE; }
void Hide() { EnumWindows(EnumTaskbarWnds,NULL); }
void Show() { while(!taskhwnd.empty()) { ShowWindow(taskhwnd.top(),SW_SHOW); taskhwnd.pop(); } }
/*键盘钩子函数*/
LRESULT CALLBACK keyboard(int nCode,WPARAM wparam,LPARAM lparam) { if(nCode<0) return CallNextHookEx(hook,nCode,wparam,lparam); if(HC_ACTION==nCode) { KBDLLHOOKSTRUCT* lpkey=(KBDLLHOOKSTRUCT*)lparam; if(GetKeyState(VK_MENU)<0&&lpkey->vkCode=='D')//当安下ALT+D键时 { if(flag==1)//隐藏 { flag*=(-1); Hide(); } else//显示任务栏窗口 { flag*=(-1); Show(); } } } return CallNextHookEx(hook,nCode,wparam,lparam); }
void sethook() { if(hook==NULL) hook=SetWindowsHookEx(WH_KEYBOARD_LL,keyboard,GetModuleHandle("HIDE.dll"),0); }
void stophook() { if(hook!=NULL) UnhookWindowsHookEx(hook); }
1、如何创建Dll文件,这里就不说了,读者可以查相关资料
Code
extern "C"__declspec(dllexport) void sethook(); extern "C"__declspec(dllexport) void stophook();
这两句是导出函数sethook()和stophook(),因为调用该DLL文件时要用到这两个函数,其他不用到的不用导出
2、taskhwnd变量用来存任务栏上显示的所有窗口的句柄。
3、flag标记,全局变量,当值为1时隐藏,否则显示。
4、GetClassName函数用来获取窗口的类名.函数功能:该函数获得指定窗口所属的类的类名。
函数原型:Int GetClassName(HWND hWnd,LPTSTR IpClassName int nMaxCount);参数:
hWnd:窗口的句柄及间接给出的窗口所属的类。
IpClassName:指向接收窗口类名字符串的缓冲区的指针。
nMaxCount:指定由参数lpClassName指示的缓冲区的字节数。如果类名字符串大于缓冲区的长度,则多出的部分被截断。
返回值:如果函数成功,返回值为拷贝到指定缓冲区的字符个数:如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。
5、IsWindowVisible函数看窗口是否有WS_ISIBLE的风格,也就是看该窗口是否是显示的
函数功能:该函数获得给定窗口的可视状态。;
函数原型:BOOL IsWindowVisible(HWND hWnd);
参数;
hWnd:被测试窗口的句柄。
返回值:如果指定的窗口及其父窗口具有WS_VISIBLE风格,返回值为非零;如果指定的窗口及其父窗口不具有WS_VISIBLE风格,返回值为零。
由于返回值表明了窗口是否具有Ws_VISIBLE风格,因此,即使该窗口被其他窗口遮盖,函数返回值也为非零。
6、FindWindow查找窗口
函数功能:该函数获得一个顶层窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。这个函数不查找子窗口。在查找时不区分大小写。
函数型:HWND FindWindow(LPCTSTR IpClassName,LPCTSTR IpWindowName);
参数:
IpClassName :指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。如果该参数为一个成员,则它必须为前次调用theGlobafAddAtom函数产生的全局成员。该成员为16位,必须位于IpClassName的低 16位,高位必须为 0。
IpWindowName:指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为空,则为所有窗口全匹配。
返回值:如果函数成功,返回值为具有指定类名和窗口名的窗口句柄;如果函数失败,返回值为NULL。
7、ShowWindow显示或隐藏窗口
函数功能:该函数设置指定窗口的显示状态。
函数原型:BOOL ShowWindow(HWND hWnd,int nCmdShow);
参数:
hWnd:窗口句柄。
nCmdShow:指定窗口如何显示。如果发送应用程序的程序提供了STARTUPINFO结构,则应用程序第一次调用ShowWindow时该参数被忽略。
否则,在第一次调用ShowWindow函数时,该值应为在函数WinMain中nCmdShow参数。在随后的调用中,该参数可以为下列值之一:
SW_FORCEMINIMIZE:在WindowNT5.0中最小化窗口,即使拥有窗口的线程被挂起也会最小化。在从其他线程最小化窗口时才使用这个参数。
SW_MIOE:隐藏窗口并激活其他窗口。
SW_MAXIMIZE:最大化指定的窗口。
SW_MINIMIZE:最小化指定的窗口并且激活在Z序中的下一个顶层窗口。
SW_RESTORE:激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指
定这个标志。
SW_SHOW:在窗口原来的位置以原来的尺寸激活和显示窗口。
SW_SHOWDEFAULT:依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的。
SW_SHOWMAXIMIZED:激活窗口并将其最大化。
SW_SHOWMINIMIZED:激活窗口并将其最小化。
SW_SHOWMINNOACTIVATE:窗口最小化,激活窗口仍然维持激活状态。
SW_SHOWNA:以窗口原来的状态显示窗口。激活窗口仍然维持激活状态。
SW_SHOWNOACTIVATE:以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态。
SW_SHOWNOMAL:激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时
候应该指定此标志。
返回值:如果窗口以前可见,则返回值为非零。如果窗口以前被隐藏,则返回值为零。
备注:应用程序第一次调用ShowWindow时,应该使用WinMain函数的nCmdshow参数作为它的nCmdShow参数。在随后调用ShowWindow
函数时,必须使用列表中的一个给定值,而不是由WinMain函数的nCmdSHow参数指定的值。
8、EnumWindows该函数用来枚举窗口
函数功能:该函数枚举所有屏幕上的顶层窗口,办法是先将句柄传给每一个窗口,然后再传送给应用程序定义的回调函数。
EnumThreadWindows函数继续到所有顶层窗口枚举完为止或回调函数返回FALSE为止函数原型:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam);
参数:
lpEnumFunc:指向一个应用程序定义的回调数指针,请参看EnumWindowsProc。
lPararm:指定一个传递给回调函数的应用程序定义值。
返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。
备注:EnumWindows函数不列举子窗口。
9、SetWindowsHookEx该函数用来设置系统钩子,更具体请相关资料
10、UnhookWindowsHookEx当不用钩子时销毁钩子
我们可以通过一个控制的程序测试一下,代码如下:
Code
//HideWin.cpp
#include<windows.h>
extern "C"__declspec(dllimport) void sethook(); extern "C"__declspec(dllimport) void stophook();
void main() { MSG msg; int ret; sethook(); while(ret=GetMessage(&msg,NULL,0,0))//必须要创建一个消息循环 { if(ret==-1)break; else { TranslateMessage(&msg); DispatchMessage(&msg); } } stophook(); }
编译前设置一下:找到刚才编译的DLL文件中的hide.lib文件,该文件在debug文件夹里,把该文件复制到Hide.cpp工程里;把hide.dll文件复制到Hide.cpp工程的debug文件夹里;然后在集成开发环境的"工程”、"设置”、"连接”、"对象/库模块”下加入"hide.lib",确定。
之后,编译运行,按ALT+D按,就可以看到效果了(^_^).
|