0
回答
C#制作QQ截图的自动框选功能的个人思路(一)<思路介绍>
华为云4核8G,高性能云服务器,免费试用   

源码连接:

http://download.csdn.net/detail/crystal_lz/4118677    (2012-03-07 这个是框选功能 下载需要两分 )

 

http://download.csdn.net/detail/crystal_lz/4247506    (2012-04-22 这个是把功能完善了 在上面的那个的代码上改了一些代码 然后可以保存图片 增加快捷键 不要分数下载)

悲剧了 突然 发现 注册快捷键 哪里忘了写注释了、、算了算了 反正已经上传了、、、


http://download.csdn.net/detail/crystal_lz/4863320(2012/12/9 高仿腾讯截图程序 效果请看http://blog.csdn.net/crystal_lz/article/details/8274277)

效果图:

Oh、、

 

哎哟哎哟!、、首先不得不说一下、、当时想做这个功能的时候百度了N久啊 没有找到一篇关于这个的文章

然后我就默默地、、一个人研究中、、在经历了四天(好吧确实有点久 途中出现了N多低级错误)的热血奋战、、oh yeah、、终于把这个功能实现了

首先先说一下思路 在qq截图中 我们看到 当我们鼠标移动到 一个控件或者窗体上的时候 那个就自动的把那个区域框选了 那么很明显 这个东西肯定是和鼠标的坐标有关系

想到这里 马上想到一条函数WindowFormPoint()根据鼠标的坐标来找寻窗体(或者控件)恩 这个函数的确错 那么好 现在可以根据鼠标来获取鼠标下面的控件了 那么是不是感觉后面的事情就有点好办了?获取到控件的句柄后 马上就使用GetWindowRect来获得改控件的位置信息 现在有了位置信息还不好办么? 根据那个位置就在外面画一个框啊?yes you are right!、、、but、、、、、

当我那个时候正高兴的时候 有了这两个函数是不是万事大吉了 ?!、、why?、、好吧 现在来分析一下

首先我们的截图程序运行的时候 第一步 将屏幕当前的状态绘制成一个静态的图片 然后我们的窗体全屏弹出然后上面显示刚才截取的静态图(当然 你可以把图片稍稍的弄黑一点就像qq一样)、、好吧 到这里有可以开始截图了 、、恩 对啊!、、难道没有发现什么不对的么?

oh No、、妹妹的(和谐)、、我们是可以使用WindowFormPoint()根据鼠标位置来获取鼠标下面的控件是句柄、、不要忘了现在 鼠标下面是我们弹出来的截图程序的窗体(别以为那个就是你的屏幕 那个只是窗体上面放了一个图片)、、、那怎么办呢 ?、、、oh、、shit、、当时我果断想到了SetWindowLong() 既然鼠标下面是我们的窗体 那么 要是鼠标能穿过我们的窗体 到后面去 那么是不是、、、、哈哈哈!、、、、

然后这个问题就貌似解决了、、不过 oh no、、鼠标把窗体传过去了、、鼠标都不能点到我们的窗体了 这简直就是一种悲剧 要是 能在我想让他穿透的时候穿透 不想让他穿透的时候就别穿透 这个怎么办、、果断Hook、、恩 这个确实可以解决 不过 我在仔细一想 即使就像这样 只要有鼠标穿过窗体的时候 那么 我们窗体后面的程序就可以响应鼠标的响应事件、、这也是一种悲剧、、、比如我写了一个程序 窗体MouseMove事件里面弹出提示框  然后 启动我的截图程序 鼠标从哪里滑动过去的时候 提示框出来了、、还有 Win7系统 把鼠标移动到 任务栏?、、、oh no、、我没有想到什么办法 可以屏蔽其他程序对鼠标的move事件的办法你总不能Hook把鼠标移动给拦截下来吧?、、、

莫非这个就这样没有办法了、、、正当我沮丧的时候 在WINAPI手册上看到两个API一个是ChildWindowFormPointEx()和ChildWindowFormPoint()  当时我一想 对啊!桌面不也是一个窗体么 我们的程序在桌面上 就相当于桌面窗体的一个控件 然后果断从桌面下手 根据坐标在桌面句柄上找寻子窗体 那和刚才那个有WindowFormPoint()有什么却别呢?、、

no 有、、、区别很大 而且 其中一个却别让我就像抓住了救命稻草!、、什么区别?、、ChildWindowFormPointEx、、在查找过程中可以忽略一些窗体 哈哈哈 不正合我意?要是查找的时候 把我自己忽略不就相当于 鼠标在截图程序窗体的后面去了?、、哇哈哈哈、、、来看看这上个函数的说明

函数原型:HWND WindowFromPoint(POINT Point);

    参数:

    Point:指定一个被检测的点的POINT结构。

    返回值S:返回值为包含该点的窗口的句柄。如果包含指定点的窗口不存在,返回值为NULL。如果该点在静态文本控制之上,返回值是在该静态文本控制的下面的窗口。

    备注:WindowFromPoint函数不获取隐藏或禁止的窗口句柄,即使点在该窗口内。应用程序应该使用ChildWindowFromPoint函数进行无限制查询。

函数原型:HWND ChidWindowFromaPointEx(HWND hwndParent,POINT pt,UNIT uFlags);

    参数:

    hWndParent:父窗口句柄。

    pt:指定一个POINT结构,该结构定义了被检查的点的坐标。

    uFlags:指明忽略的子窗口的类型。该参数可以是下列参数的组合。

    CWP_ALL:不忽略任一子窗口。CWP_SKIPINVISIBLE:忽略不可见的子窗口。

    CWP_SKIPDISABLE:忽略禁止的子窗口。CWP_SKIPTRABSPARENT:忽略透明子窗口。

    返回值:返回值为包含该点并且满足由uFlags定义的规则的第一个子窗口的句柄。如果该点在父窗口内,但在任一满足条件的子窗口外,则返回值为父窗口句柄。如果该点在父窗口之外或函数失败,则返回值为NULL。

    备注:系统有一个与某一父窗口有联系的所有子窗口的内部列表。列表中的句柄顺序依据这些子窗口的Z序。如果有多于一个的子窗口包含该点,那么系统返回在列表中包含该点并且满足由uFlags定义的规则的第一个窗口的句柄。

 

函数原型:HWND ChildWindowFromaPoint(HWND hWndParent.POINT Point):

    Parent:父窗口句柄。

    Point:指定一个POINT结构,该结构给定了被检查的点的坐标。

    返回值:返回值为包含该点的子窗口的句柄,即使该子窗口是隐藏的或被禁止的。如果该点在父窗口之外,则返回值为NULL。如果该点在父窗口内,但在任一子窗口外,则返回值为父窗口句柄。

备注:系统有一个与某一父窗口有联系的所有子窗口的内部列表。列表中的句柄顺序依据这些子窗口的z序。如果有多于一个的子窗口包含该点,那么系统返回在列表中包含该点的第一个窗口的句柄。

看见没有 WindowFormPoint不会忽略窗体 特殊情况只是获取不到 不会忽略(当然穿透那个就另当别论了)

再看看Ex那个 那可以忽略被禁用的窗体而不是不获取  是忽略 要是 我把我截图程序的窗体 this.Enable = false ?  那么他不就是被忽略了?、、就相当于鼠标到背后去了?

但是我们的窗体在屏幕顶层挡着 后面的程序不就就不能响应鼠标事件了?、、只是 在必要的时候 禁用 于 恢复窗体就行了、、当然 我想到的只有Hook

 

oh yeah、、想到这里就差不多了、、可以开始工作了、、

思路大致就是这些了、、、

下一篇中介绍代码、、、


原文链接:http://blog.csdn.net/crystal_lz/article/details/7327268
<无标签>
举报
长平狐
发帖于6年前 0回/237阅
顶部