Spy++原理初探
http://tech.ddvip.com 2007年09月02日 社区交流
内容摘要:用Visual Studio搞开发的朋友对Spy++这个工具一定不陌生,它可以分析窗体结构、进程和窗口消息,对开发工作有很大辅助作用。我们需要研究某个对象时,只要调出其查找窗口,拖动探测器的指针到指定窗口/控件上释放即可。下面,笔者就和大家一起,用VC打造一个属于自己的Spy++。

消息标签页的设计如下图:
该页中的列表框与样式列表框不同,它的每个列表项前都有一个复选框。这要用到类CCheckListBox。这里要再次用到子类化的知识。从本文第一段制作CMyPric过程中,我们体会到了子类化的作用,也感到了它的不便之处。这里,我们采取另外一种方法,借鸡生蛋:即用Class Wizard生成相关代码,然后再修改它。首先在该属性页对话框上画一个列表控件,打开Class Wizard关联一个CListBox类变量m_listStatus。设置列表框的Owner Draw属性为Fixed,并选中其Has Strings选项。如下图:
然后,在Page4.h中查找到m_listStatus的定义 CListBox m_listStatus并将其改为CCheckListBox m_listStatus。这样,我们就可以使用CCheckListBox的全部函数了。
在对话框初始化过程中添加下列语句以加入各列表项:
CCheckListBox* plistStatus=((CCheckListBox*)FromHandle(g_hPage4)->GetDlgItem(IDC_LISTSTATUS)); 接下来我们要判断,当窗口/控件被选定后,哪些列表项被勾选。这个判断过程与样式列表的实现类似。如第一项"窗口可见",代码如下:
plistStatus->AddString("窗口可见");
plistStatus->AddString("窗口可用");
plistStatus->AddString("总在最前");
plistStatus->AddString("窗口只读");
plistStatus->AddString("最大化");
plistStatus->AddString("最小化");
plistStatus->AddString("窗口还原");
plistStatus->AddString("关闭窗口");
plistStatus->AddString("激活窗口");long style = GetWindowLong(g_hWnd, GWL_STYLE); 其余各项详见源代码。 这个列表框的作用不仅仅是显示窗口的状态,还要在发生勾选改动时即时改变窗口状态或激发其行为。勾选状态改变的消息是LBN_SELCHANGE。另外,为了不使一个勾选的改变就引起所有列表项都激发一遍,我们采用switch结构,以使哪个列表项被选中就激发哪个列表项。代码如下:
if( style & WS_VISIBLE )
{
pListStatus->SetCheck(0,1);
}void CPage4::OnSelchangeListstatus() Spy++打造完毕。回顾其过程,难点不多,细细碎碎问题不少。也难免啊,不仅要形似,咱还要神似。文中一定还有很多地方不够周全,希望同行朋友们不吝赐教。代码在Window XP + VC6.0中调试通过。Spy++源码同时放在这里。
{
// TODO: Add your control notification handler code here
int n=m_listStatus.GetCurSel();
switch(n)
{
case 0:
if(m_listStatus.GetCheck(0)== 1 )
::ShowWindow(g_hWnd, SW_SHOW);
else
::ShowWindow(g_hWnd, SW_HIDE);
break;
case 1:
if(m_listStatus.GetCheck(1) == 1)
::EnableWindow(g_hWnd, TRUE);
else
::EnableWindow(g_hWnd,FALSE);
break;
case 2:
if(m_listStatus.GetCheck(2) == 1)
::SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
else
::SetWindowPos(g_hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
break;
case 3:
if(m_listStatus.GetCheck(3) == 1)
::SendMessage(g_hWnd, EM_SETREADONLY, TRUE, 0);
else
::SendMessage(g_hWnd, EM_SETREADONLY, FALSE, 0);
break;
case 4:
if(m_listStatus.GetCheck(4) ==1)
{
::ShowWindow(g_hWnd, SW_MAXIMIZE);
m_listStatus.SetCheck(5,0);
}
else
::ShowWindow (g_hWnd, SW_RESTORE);
break;
case 5:
if (m_listStatus.GetCheck(5) == 1)
{
::ShowWindow(g_hWnd, SW_MINIMIZE);
m_listStatus.SetCheck(4,0);
}
else
::ShowWindow(g_hWnd, SW_RESTORE);
break;
case 6:
if(m_listStatus.GetCheck(6) ==1)
{
::ShowWindow (g_hWnd, SW_RESTORE);
m_listStatus.SetCheck(6,0);
m_listStatus.SetCheck(5,0);
m_listStatus.SetCheck(4,0);
}
break;
case 7:
if(m_listStatus.GetCheck(7) ==1)
{
::SendMessage (g_hWnd, WM_CLOSE, 0, 0);
m_listStatus.SetCheck(7,0);
}
break;
case 8:
if(m_listStatus.GetCheck(8) ==1)
{
::BringWindowToTop(g_hWnd);
m_listStatus.SetCheck(8,0);
}
break;
default:
;
}
}
来源:vckbase 作者:宋陈三 责编:豆豆技术应用
- VC/VC++按钮设计专题
- VC/VC++ 菜单专题
- VC/VC++ 工具条专题
- VC/VC++ 对话框教程
- VC/VC++ 报表教程
- VC/VC++ 控件
- VC/VC++ GDI
- Visual Studio 2008
- VC/VC++ MFC教程
- VC/VC++ QQ
- VC/VC++ Socket编程
- VC/VC++ 钩子编程
- TangramMini组件应用教程
- VC/VC++ 窗体
- VC/VC++ ADO 教程
- Windows CE 教程
- VC/VC++ DLL(动态链接库)编程
- VC/VC++ PDFlib
- VC与MATLAB编程
- VC/VC++ DirectShow 教程
- VC++入门视频教程
- VC/VC++ COM组件设计与应用
- VC/VC++ ATL
- VC/VC++ WTL
- VC/VC++ 定制调试诊断工具和程序
- VC/VC++ 进程
- VC/VC++ Win32
- VC/VC++ WMI
- VC/VC++ 消息
- 更多VC/VC++专题……