间谍行动——窗体探测器

原创 2004年01月02日 19:43:00

间谍行动——窗体探测器

最近心血来潮,对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=(Point))
              {
                if(hWndNow!=hWndPoint)//目标已改变
                {
                  if(hWndNow)
                  {
                    //清除旧目标上的黑框
                    (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;
    }
这里的问题就在 WindowFromPoint XorBorder 中.这里我们先看第一版XorBorder
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);
    hWndPoint=NULL;
    do
    {
      if(GetWindowStyle(hWndBrother)&WS_VISIBLE)//可见
      {
        GetWindowRect(hWndBrother,&rcNow);
        if(PtInRect(&rcNow,Point))
        {
          //检验矩形嵌套情况
          if(hWndPoint==NULL)
          {
            hWndPoint=hWndBrother;
            rcPoint=rcNow;
          }
          else if(
            ((rcNow.bottom<rcPoint.bottom)&&(rcNow.bottom>rcPoint.top)&&(rcNow.left>rcPoint.left)&&(rcNow.left<rcPoint.right))//左下角
            ||((rcNow.bottom<rcPoint.bottom)&&(rcNow.bottom>rcPoint.top)&&(rcNow.right>rcPoint.left)&&(rcNow.right<rcPoint.right))//右下角
            ||((rcNow.top>rcPoint.top)&&(rcNow.top<rcPoint.bottom)&&(rcNow.left>rcPoint.left)&&(rcNow.left<rcPoint.right))//左上角
            ||((rcNow.top>rcPoint.top)&&(rcNow.top<rcPoint.bottom)&&(rcNow.right>rcPoint.left)&&(rcNow.right<rcPoint.right))//右上角
            )
          {
            hWndPoint=hWndBrother;
            rcPoint=rcNow;
          }
        }
      }
    }while(hWndBrother=GetWindow(hWndBrother,GW_HWNDNEXT));
    return hWndPoint;
}
该函数检测同层窗口,获得指定点内,嵌套最深的窗口,由此我们便可以生成我们自己的WindowFromPoint
HWND MyWindowFromPoint(const POINT Point)
{
  HWND hWndPoint=WindowFromPoint(Point);
  if(hWndPoint)
  {
    //宽度搜索兄弟窗口
    HWND hWndChild;
    if(!(GetWindowLong(hWndPoint,GWL_STYLE)&WS_CHILD))//顶层窗口
      return hWndPoint;
    //非顶层窗口,要进行兄弟查找.
    hWndPoint=MyBrotherWindowFromPoint(hWndPoint,Point);
    assert(hWndPoint);
    //深度搜索子窗口
    while(hWndChild=GetTopWindow(hWndPoint))
    {
      //宽度搜索兄弟子窗口
      if(NULL==(hWndChild=MyBrotherWindowFromPoint(hWndChild,Point)))
        break;
      hWndPoint=hWndChild;
    } //*/
  }
  return hWndPoint;
}

该函数首先判断是否是顶层窗体,如果不是,首先进行宽度搜索,虽然麻烦了些,然而却不得不如此。顺便说一下,vc资源编辑器中正在设计的对话框拥有disable属性,spyxx你的窗体探测器也不能得到其内的所有控件句柄,而该函数所向无敌,如果去掉BrotherWindowFromPoint函数内的可见性判断,隐藏窗体也无处藏身。有兴趣的朋友可以亲自设计一下,如果你是懒惰者,可到华军软件园下在该程序红色间谍.

个人主页:http://ggg82.126.com

电子邮件:

字符串练习11_潜伏者

/* Name: 11_潜伏者 Copyright: Author: Date: 01-09-17 10:40 Description: 11_潜伏者 查看 提交 统计 提问 总时间限制...
  • QiaoRuoZhuo
  • QiaoRuoZhuo
  • 2017年09月01日 17:04
  • 203

1071:验证角谷猜想

题目描述 数论中有许多猜想尚未解决,其中有一个被称为“角谷猜想”的问题,该问题在五、六十年代的美国多个著名高校中曾风行一时,这个问题是这样描述的:任何一个大于一的自然数,如果是奇数,则乘以三再加一;如...
  • u013041792
  • u013041792
  • 2013年12月28日 14:54
  • 434

VIJOS P1752潜伏者

【题目描述】     R 国和 S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。  历尽艰险后,潜伏于 S国的 R 国间谍小 C 终于摸清了 S国军用密码的编码规则:  1. S ...
  • LIYOUFHASS
  • LIYOUFHASS
  • 2016年06月06日 16:14
  • 353

noi-7915-潜伏者

潜伏者 总时间限制: 1000ms 内存限制: 65536kB 描述 R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。 历经艰险后...
  • mahz666
  • mahz666
  • 2017年03月15日 15:58
  • 199

Unity3D - 灯探测器(Light Probes)

在Unity中Baked和Precomputed Realtime Gl系统只应用于静态物体。为了让动态物体可以受到静态物体灯光的影响,我们需要将照明信息记录在一个格式中,这种格式可以在游戏中迅速被读...
  • biezhihua
  • biezhihua
  • 2017年08月11日 23:53
  • 408

基于四象限探测器的激光窃听及定位系统

摘要:   一、 研究背景: 窃听技术经过多年的发展,衍生出多种窃听的方式,其中激光窃听技术由于其能够远距离非接触式窃听,不易被发现等优点,逐渐有了较为广阔的应用价值以及研究空间。近几年激光窃听...
  • harry19902002
  • harry19902002
  • 2014年06月24日 14:12
  • 1127

【电子电路技术】短波红外InGaAs探测器简析

核心提示:  红外线是波长介于微波与可见光之间的电磁波,波长在0.75~1000μm之间,其在军事、通讯、探测、医疗等方面有广泛的应用。目前对红外线的分类还没有统一的标准,各个专业根据应用的需要,有着...
  • LG1259156776
  • LG1259156776
  • 2016年07月22日 14:04
  • 1231

GOOGLE办公室间谍照片,你所不知道的Google

              GOOGLE办公室间谍照片,你所不知道的Google        注:原文地址:http://www.admin100.com/Internet/200603261423...
  • cyz1980
  • cyz1980
  • 2006年03月26日 16:21
  • 1281

平板探测器的工作原理和比较各平板探测器优缺点

非晶硒型平板探测器 概括原理: 光导半导体直接将接收的X线光子转换成电荷,再由薄膜晶体管阵列将电信号读出并数字化。 具体原理: 1. X 线入射光子在非晶硒层激发出电子-空穴对;2. 电子和空穴在外...
  • utimes
  • utimes
  • 2013年01月26日 08:08
  • 2788

动态规划(城市里的间谍,uva 1025)

#include #define INF 0X3F3F3F3F using namespace std; int N,T; int t[55]; int M1,M2; int d[55]; int ...
  • xl2015190026
  • xl2015190026
  • 2016年09月16日 18:36
  • 455
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:间谍行动——窗体探测器
举报原因:
原因补充:

(最多只允许输入30个字)