设为首页 加入收藏

TOP

用Visual C++设计窗体探测器(二)
2012-11-04 15:17:56 】 浏览:803
Tags:Visual 设计 窗体 探测器
  这里的问题就在 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函数内的可见性判断,隐藏窗体也无处藏身。有兴趣的朋友可以亲自设计一下,如果你是懒惰者,可到华军软件园下在该程序红色间谍.


首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇为OpenFile对话框增添预展功能 下一篇用VC++6.0编写注册表管理程序

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目