用VisualC 设计窗体探测器
2008-04-09 04:09:12来源:互联网 阅读 ()
最近心血来潮,对spy深感兴趣,便准备进行一次间谍行动,目标很简单,利用EnableWindow函数激活不可用或无效的控件按钮,当然,这窗体探测器是必不可少了,原以为很简单,但实际行动起来,却遇到不少麻烦,现将经过记录下来,供有兴趣的朋友参考。
我们大都见过spyxx中的窗体探测器,当鼠标在窗体探测器上按下左键时,更改鼠标样式,同时捕获鼠标,探测鼠标下的窗体直到鼠标左键松开。这样我们可以写出代码框架了:
case WM_LBUTTONDOWN://鼠标左键按下,检测拖动还是探测
{
MSG msg;
//在窗体探测器中按下鼠标
if(在窗体探测器内==TRUE)//替换光标,探测拖动
{
//更改鼠标样式
SetCursor(...);
//捕获鼠标
SetCapture(hWnd);
hWndNow=NULL;//当前窗体设为空//此为全局变量
//获取鼠标移动消息
while(GetMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST))
{
if((msg.message==WM_MOUSEMOVE)||(msg.message==WM_NCMOUSEMOVE))
{
HWND hWndPoint;
//设置光标
SetCursor(LoadCursor(hInst, (LPCTSTR)CUR_WINDOWSPY));
GetCursorPos(&Point);
//探测当前鼠标点
if(hWndPoint=WindowFromPoint(Point))
{
if(hWndNow!=hWndPoint)//目标已改变
{
if(hWndNow)
{
//清除旧目标上的黑框
XorBorder(hWndNow);
}
//并且不属于本线程
if(GetWindowThreadProcessId(hWndPoint,NULL)!=GetCurrentThreadId())
{
//将当前窗体画一黑边框
hWndNow=hWndPoint;
XorBorder(hWndNow);
}
else
{
hWndNow=NULL;
}
//显示窗体信息
ShowWindowMessage(hWnd,hWndNow);
}
}
else
{
hWndNow=NULL;
ShowWindowMessage(hWnd,hWndNow);
}
}
//如果左键松开,则跳出
else if(msg.message==WM_LBUTTONUP)
{
break;
}
}
XorBorder(hWndNow);
//释放鼠标并恢复鼠标样式
SetCursor(LoadCursor(NULL,(LPCTSTR)IDC_ARROW));
ReleaseCapture();
}
break;
}
void XorBorder(HWND hWnd)
{
RECT rect; //当前窗体区域
HDC hdc=GetWindowDC(hWnd);
GetWindowRect(hWnd,&rect);
//调整边框
rect.bottom-=rect.top;
rect.right-=rect.left;
rect.left=rect.top=0;
SetROP2(hdc,R2_NOT);
FrameRect(hdc,&rect,GetStockObject(BLACK_BRUSH));
ReleaseDC(hWnd,hdc);
}
然而结果总以失败告终,查看SetROP2资料,隐隐约约感觉它仅对画笔起作用,画刷无效(仅代表个人观点,正误难辨)。于是将其改为Rectangle,然而它可是连边框带矩形内部全部搞定了,这并不是我要的效果呀,这该怎么办呢?看我的最终解决方案:
void XorBorder(HWND hWnd)
{
HPEN hPen,hOldPen;
RECT rect; //当前窗体区域
HDC hdc=GetWindowDC(hWnd);
GetWindowRect(hWnd,&rect);
//调整边框
rect.bottom-=rect.top;
rect.right-=rect.left;
rect.left=rect.top=0;
SetROP2(hdc,R2_NOT);
hPen=CreatePen(PS_SOLID,6,RGB(0,0,0));
hOldPen=SelectObject(hdc,hPen);
//选择刷子为空,使矩形不填充内部
SelectObject(hdc,GetStockObject(NULL_BRUSH));
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
SelectObject(hdc,hOldPen);
DeleteObject(hPen);
ReleaseDC(hWnd,hdc);
}
我将当前画刷选择为空,我不知道这种方法是否正统,反正msdn未找到,虽然看着仅仅是小小的改动,倒是费了我好大功夫,我可是一直在FrameRect上打转呀!
现在我们开看 WindowFromPoint :msdn上说该函数跳过无效按钮,需要使用ChildWindowFromPoint来解决,然而,问题并不是那么简单,先看下面这段资源文件:
IDD_DIALOG1 DIALOGEX 0, 0, 186, 110
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "静态",IDC_STATIC,45,14,81,69
CONTROL "选中1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
57,28,61,16
CONTROL "选中1",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
57,54,60,10
END
我试验过,要想得到IDC_CHECK1,IDC_CHECK2,用上面的两个函数是无法实现的,(你知道吗,GROUPBOX是button类,而不是static,直到今天我才知道),请不要告诉我改变GROUPBOX的Tab键顺序,我们的探测器要面对各种情况,下面看我的解决方案:
HWND BrotherWindowFromPoint(HWND hWndPoint,const POINT Point)
{
//检测兄弟窗口
RECT rcPoint;
RECT rcNow;
HWND hWndBrother=hWndPoint;//GetWindow(hWndPoint,GW_HWNDFIRST);
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash