在写WG或者一些辅助小工具的过程中,难免会涉及到向窗口的某个控件发送鼠标消息,或者是直接点击窗口或者屏幕上的某一个区域。在资料不充分(例如对方使用的是DirectUI,控件的句柄就很难获得,自然也很难知道某个控件或者对象相对于窗口或者屏幕左上角的坐标值)的情况下,很难确定在发送鼠标消息的时候,鼠标的坐标是多少。那么,如何快速地利用工具作简单的查找呢?
笔者在制作一个QQ游戏的辅助工具时,就曾经因为一时间找不到两幅图片相对于窗口左上角的坐标而苦恼。
(因为这个找茬辅助工具是基于屏幕截图,像素点之间逐一直接比对的)
如何知道上图两个红点分别相对于窗口左上角的坐标值呢?
扩展,又如何知道两幅找茬图片的宽度和高度呢?
网上不乏好的查找方法,但是为了获取几组值而另外写程序,笔者认为不够灵活。程序员还是应该懒一点~解决方案如下:
运用photoshop的标尺功能即可完成任务:
笔者用的是photoshopCS4,估计其他版本也有这个功能。
第一步:
利用QQ自带的截图功能(TX这回自作聪明了,QQ截图居然可以针对某个特定窗口或者某个特定控件截图,从而省却了全屏截图过后裁切窗口的步骤),截取游戏窗口的PP,如下
:
第二步,在photoshopCS4中打开这张图片,放大之,然后在工具栏中选择标尺工具,如图:
标尺工具
接着在图片左上角的位置开始,沿着任意方向拖曳标尺工具,就像平时在windows画图中画直线一样,然后我们会看到一条很细的直线被拖出;
笔者往下垂直拖曳,这除了能够确定左上角坐标之外,还可以测量出图片的高度。
红色框框里面的灰色线条(两头有十字图案的)就是拖曳出来的直线标尺。
蓝色框框有几组值,熟悉windows窗口编程的童鞋们应该都可以笑而不语了,笔者不才,还是斗胆解说一下:
x:相对于图片左上角的像素横坐标(也就是我们要找的图片或者控件相对于窗口左上角的坐标值)
y:相对于图片左上角的像素纵坐标(同上)
w:width,线段两端端点之间的
水平宽度(单位是像素)在这里是负数是因为笔者的终点在起点的水平方向左边,因此是负数。
h:height,线段两端端点之间的
垂直宽度(单位是像素)
注意:这里得到的数值是一个小数,其实说白了也是精度问题。
平时在做windows窗口编程的
过程中,控件的坐标总是整数,例如上图的x = 9.44,要取9还是取10,那就要看我们在一开始选点的时候是否够贴近真值。
这里目测一下(噗!O(∩_∩)O哈哈~),显然是比真实图像稍微偏左了,因此取10,其他值都按照这个方法处理。
用这种方法,可以测出两幅图片的左上角坐标和图片的宽、高。获得值之后,运用到程序中,误差不会超过5个像素,到时在测试过程中微调一下就OK了。
笔者很幸运,第一次取整的时候就估中了,O(∩_∩)O哈哈~
针对QQ游戏大家来找茬,发放一下小屏幕版本的关键数据吧:
x1 = 10
y1 = 185
x2 = 403
y2 = 185
nWidth = 380
nHeight = 285
最后恶心一下:祝各位准备YY各种游戏辅助工具的亲们开发愉快,噗哈哈哈哈哈!
谁说只有美工能用PS捏?咱们程序员也可以适当投机取巧一下嘛~哈哈
posted @
2011-07-24 22:22 ArthasLee 阅读(10120) |
评论 (0) |
编辑 收藏
Q1:为什么程序的数据需要放在堆、栈两个不同(甚至更多)的地方?
对于堆和栈中的数据内容来说:
栈:编译器需知道数据内容的生存周期、但是可以快速管理和分配栈内存;
堆:编译器无需知道数据内容的生存周期,保证灵活性、但是分配和回收内存不如把数据放在栈中来得快;
Q2:对象在其生命周期结束后经历什么步骤而后被释放?销毁机制具体是怎样的?底层通过什么实现?
当程序执行到一个块or作用域(scope)的结尾,会自动清理其维护的栈中的内存数据。
于是,如果保存在栈中的唯一reference挂掉了,就意味着再没有办法可以操作其原先引用的对象了。
但是保存在堆中的对象在这时候还没有被清理掉。
对于在堆中,没有被引用的对象。垃圾回收器会直接把他们占据的内存空间释放掉。
真的如书中所说,这种机制滴水不漏吗?会不会有陷阱?
会不会有一些不经意的操作导致引用计数永远不为零,然而用户却懵然不知呢?
内存泄漏真的可以在真正意义上得到避免吗?
Q3:垃圾回收机制究竟能干什么,不能干什么?究竟本质是什么?
垃圾回收机制原来只会对new出来的堆内存起作用!!!
万一不是new出来的,那还是得人工回收……
1、You might not get garbage collected!
哎……这样的垃圾回收机制啊……
还真是懒啊……
总之就是,垃圾回收机制只会回收对象在堆中的内存,但究竟这个对象的操作曾经干了什么,有没有“历史遗留问题”,java是一概不管的……
这个垃圾回收机制还是回到回忆中去吧……(我没吐槽最终幻想,真的没有!)
ClassName obj;//局部对象,放在栈中(C++可以这样,java不行)
C++的好处:作用域结束,局部对象的destructor自动被调用,释放栈中内存;
New出来的对象:
//C++的坏处:不执行delete的话,对象占用的内存会一直赖在堆中。就让内存漏一会儿吧。
//java的好处:不用显式执行,只要作用域结束,reference被清除,垃圾回收器就会自动回收堆中的内存;
而且,java兄还不让你在栈中创建局部对象呢……
Q3/1:那究竟new操作发生的时候,java语言为用户干了什么?new的操作也会对引用计数产生作用——例如初始化和创建吗?垃圾回收器如何工作呢?
相对于堆而言,在栈中释放和分配内存还是效率较高。这可能也是一些程序的数据放在栈中,一些放在堆中的原因之一吧?
引用计数类似是一个对象中的成员;有东西引用对象,就增加1,当有引用在栈中被释放或者设为NULL,就减少1;发现引用计数为0,就证明这个对象已经没人要了……
缺点:
垃圾回收器要扫描整个对象列表,查找引用计数为0的对象;
如果有两个对象碰巧相互引用了彼此,那这两个对象的引用计数就用不为零,即使没人要也不会被清除掉;
最悲催的是:
JVM都不是通过这种机制实现垃圾回收滴……
JVM是这么干的……
逆向思维,不找死的,找活的!从一个引用出发,遍历其对象-树(自己作的)。透过每一个在栈中或者在静态区中保存的引用,以之为根节点,遍历由他出发可以到达的对象节点。
好处:
不用遍历所有堆中的对象。
解决两个对象互相引用而导致引用计数恒不为0的问题;
经过上述处理,没被找到的对象会被清理掉,但是会留下内存碎片,浪费空间。所以……
妙!
把程序停止下来,把活动的对象copy到新的堆内存,连续存放,这样就腾出了那些原先成为碎片的空间。
然而,一直copy来copy去需要有额外的堆内存来保存copy的数据,实际上copy发生的时候需要双倍于被copy内容的堆内存同时可用。
其次,copy也需要时空开销……
于是……
JVM就把sweep-and-mark和stop-and-copy结合起来(thinking in java有详述)
大对象占用一个block,每个block有一个generation count作为其可用与否的标记。
一些小对象放在一个block里;
根据引用来遍历其对象-树的操作开始执行:
一般来说,大对象是不会被copy的;
小对象会被复制和重新管理,释放内存碎片;
JVM在碎片多的时候进行stop-and-copy来整理碎片,腾出空间;在堆内存足够和碎片不多的情况下,则只执行sweep-and-mark。
在这样的垃圾回收机制下,只要是new出来的东西,真的都能回收了。某程度上还真是滴水不漏啊……
显然是抄IBM大型机的外存管理嘛!数据集放在block中,被删除的数据集的block标记为不可用,新建的数据集放在后面的block中。当存储空间不够了,整理那些已经存在又可用的数据集,存放在一片连续空间中,把碎片重新整理为可用内存,真是……
抄吧抄吧,不是罪……
posted @
2011-03-04 20:49 ArthasLee 阅读(804) |
评论 (1) |
编辑 收藏