后面是源码和CE分析文件:
成品效果图:


不建议看源码哈(代码组织的很不好,自己看都头大)。直接用CE自己去分析出来。
版本不一样的话可能很CE文件不能用哈。但只要按下面的方法去找不论什么版都可以写出自己的记牌器。
我分析的版本:时间是2011-4-13



牌面和数据的对应关系:
A--1 2--2 ....... 10--10 J--11 ..小鬼--14 大鬼--15


  QQ的保存打出的牌的数据是存放在3个数组中的(这个数组可能又是某个结构的成员哈, 我们不管)。并且和大厅的座位号对应。大厅的座位号是这样的:



打出的牌是按从右向左的顺序排列的。
这个数组的第一字节,保存的是第一张打出的牌花色:

(按照黑红梅方 对应数据 1 2 3 4)保存的。
第二字节就是按最上面的对应关系保存的第一张牌的牌面数据。

第二张牌的花色在 第一张牌花色+c的位置
第二张牌牌面在第一张牌 牌面+c的位置

比如大家可以通过CE搜索打出的牌面,最后找到你自己打出的牌的牌面地址是 4451001; 那么这张牌的花色地址就是4451001-1
第二张牌牌面地址就是4451001+0xc, 花色地址就是4451001-1+c

搜索出来的地址是这样的:



是以GameLogic.dll+e9f2c做为基址的, 这种地址比较稳定。(可以自己写个函数得到GameLogic.dll的基址就可以读出想读出的数据了)

用CE找到保存打出牌数据的地址。并找到牌数。( 这个搜索很简单)

还可找到正在出牌的玩家座位号(本文提到的座位号都是大厅里的不是游戏里的)标示 (这是个1字节的数据, 分别是 0, 1, 2, 和上图大厅座位号的关系对应, 0代表的是大厅右边玩家,1代表下边,2代表左边。 )
搜索方法:比如你的大厅座位号是2(大厅里的左边),搜索2,然后看一下你下家的座位号。这样很快就能搜索出来。

还可以找到一个已出牌的座位号标示。
  搜索同上,比如你的座号是2,那么你先在CE里填上2,然后出牌,马上点搜索,多几次就可以搜索出来。

还要找到一个保存自己座位号的标示。
  这个比较麻烦。你在大厅直接点座位号2,然后CE搜索,关游戏,
在点座位号1,然后CE打开游戏,它会询问你是否保存当前的地址。点是在搜索1。 反复几次也就能找出来了。

还可以找到保存自己手中牌的信息。

有了以上信息就可以做出自己的记牌器了, 实现上图的所有功能了。

可以根据已出牌标示来表示有人出牌,也可以通过比较牌数的变化来表示有人出牌。从而更新或者读取出牌数据。
还有个问题就是怎么确定是谁打出的牌:
  打出牌的数据只是和大厅里的座位位置有关系,(我没有找到一个稳定的可以标示游戏里玩家位置的数据,你可以自己找找 )
所以第一个图中左边玩家,右边玩家出牌怎么能确定呢。

我的程序里是这样搞的哈:
  读取牌数只要其中一个牌数为20就表示抓地主完成了。然后只要牌数一变化你就可以读出:
  自己的大厅座位号: dwMySeatID
 已出牌的玩家大厅座位号: dwPlayedSeatID
 正在出牌的玩家大厅座位号:dwPlayingSeatID
 因为自己的在游戏中的位置是确定的,就是下方。但对应的大厅的座位就不是一定的了。

 在第一次完成出牌(牌数有变化或都已出牌标示)的时候读取上面的三个数据
 // 自己的座位号 == 已出牌的座位号,那么表示自己已经出了牌了, 说明自己是地主。
 if ( dwMySeatID == dwPlayedSeatID )
  那么知道自己是地主,那么游戏里右边的玩家的
  大厅座位号 = 正在出牌的座位号 = dwPlayingSeatID
 这样就把游戏里的位置和大厅里的位置和打出牌数据属于谁相关联起来了。就可以左边玩家打的什么,右边打的什么牌了。

可能存在的炸弹:
  读出自己的牌,自己没有的就可能有炸弹。在每次有人打出牌的时候就把已出的牌从可能是炸弹的数据中踢除并更新。

没有KB的可以去115下哈源码加CE文件
http://u.115.com/file/f3fbd9ac48#Download

上传的附件 记牌器源码加CE分析文件.7z