扫雷外挂的设计与实现(三)

2016-02-19 19:31 18 1 收藏

关注图老师设计创意栏目可以让大家能更好的了解电脑,知道有关于电脑的更多有趣教程,今天给大家分享扫雷外挂的设计与实现(三)教程,希望对大家能有一点小小的帮助。

【 tulaoshi.com - 编程语言 】

  如上述,本程序分为了接口层和算法层。上述全局变量和常量,基本都属于接口层的内容。下面,来看接口层的具体实现。其工作的第一步,是要捕获扫雷窗口并取得其信息。这由函数GetMineWindow来完成:

  =================================================================

  //试图取得可用的扫雷窗口,返回值表示是否成功。若成功,则全局变量
  //MineWnd、MineDC、AreaHeight、AreaWidth都得到相应的填充。若失败,则以上变量的值无意义。

  function GetMineWindow: Boolean;
  var
    clientRect: TRect;
  begin
    result := false;

    MineWnd := FindWindow(nil, MINE_WINDOW_TITLE);           //检查是否存在“扫雷”窗口,并且必须为当前窗口
    if (MineWnd = 0) or (GetForegroundWindow MineWnd) then
      Exit;

    MineDC := GetDC(MineWnd);                                //取得“扫雷”窗口的设备上下文
    if MineDC = 0 then
      Exit;

    GetClientRect(MineWnd, clientRect);                      //检查“扫雷”窗口的内容是否全部显示在屏幕上
    with TCanvas.Create do
      try
        Handle := MineDC;
        if (ClipRect.Left clientRect.Left) or
           (ClipRect.Right clientRect.Right) or
           (ClipRect.Top clientRect.Top) or
           (ClipRect.Bottom clientRect.Bottom) then
          Exit;
      finally
        Free;
      end;

    //从已获得的clientRect中的数值,根据实测数据计算AreaWidth和AreaHeight的值。
    AreaWidth := (clientRect.Right - LEFT_MARGIN - RIGHT_MARGIN) div CELL_WIDTH;
    AreaHeight := (clientRect.Bottom - TOP_MARGIN - BOTTOM_MARGIN) div CELL_HEIGHT;

    //检查游戏是否在进行中,原理为判断“重开始”按钮的图标上的
    //某一像素是否是指定的值。该经验由实测得到,只有游戏进行中,该像素才为该值。
    if TColor(GetPixel(MineDC, AreaWidth*8 + 8, 30)) clBlack then
      Exit;

    result := true;
  end;

  =================================================================

  理解这个函数的工作过程,有几个要点:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  WinAPI函数FindWindow:用来查找当前桌面上的某个窗口。第一个参数是指定该窗口的“窗口类”的名字,这个稍微高深了一点,只有研究过Windows SDK编程才会理解。当它为nil的时候,使用第二个参数,也就是窗口标题栏的字符串来查找。若找到这样一个窗口,则返回值为其窗口句柄,否则为0。

  WinAPI函数GetForegroundWindow:无参数,返回桌面上的当前窗口,也就是标题条加亮的窗口的句柄。

  WinAPI函数GetDC:给定一个窗口句柄,返回它的设备上下文句柄。“设备上下文”实际上就是一个“画布”,在Delphi中,被封装成了TCanvas类。获得了某个设备上下文句柄,就可以用一个TCanvas型的对象指向它(这个过程是,把句柄赋给TCanvas对象的Handle属性),从而实现画布的各种操作。

  WinAPI函数GetClientRect:给定某个窗口句柄,取得它的客户区矩形,这个矩形是一个TRect类型的变量。调用这个函数,要用一个TRect型的变量来接收结果,而不是用返回值。这个结果的Left和Top成员都必定是0,而Right和Bottom成员其实就是窗口客户区的宽和高。

  TCanvas类的属性ClipRect:简单的说,在此处,该TRect型属性取得的是该画布实际上被显示在屏幕上的矩形部分。只有该画布不被其它窗口遮挡,并且没有移出桌面边界的时候,这个矩形才完全等于等于窗口的客户区矩形。这用来判断扫雷窗口是否全部可见。

  WinAPI函数GetPixel:给定一个设备上下文(画布)句柄和X,Y坐标,取得一个像素的值。这个值是整型的,可以简单的强制转换为TColor类型。

  上述库函数,具体说明可以参考MSDN和Delphi自身的帮助文档,可以得到最为权威、详细、正确的说明。

  不得不说一下GetMineWindow函数的最后几行,它牵涉到了对“重开始”按钮的hack。注意一下,可以发现那个简单的脸谱总共有5种状态:平时的笑脸,自身被按下时的笑脸,在雷区中按下鼠标时的紧张表情,触雷时的衰脸和胜利时酷酷的表情~——显然,只有在第一种情况时,扫雷外挂才应该动作,其它四种时则应该停止。我编了一个临时程序,找到了一个像素位置,它只有在第一种情况下值为clBlack,其它情况都不是。它的坐标为(AreaWidth*8 + 8, 30),横坐标是个随方块列数而变的变量,很好理解,因为无论窗口有多宽,该按钮都是水平居中的。

  

  

  

  

  
  

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

来源:http://www.tulaoshi.com/n/20160219/1621204.html

延伸阅读
template class CToolbar { public: CToolbar(); void CreateToolbar(HWND hParent);// 创建工具条 void AddButtons();// 逐个加入按钮 void DestroyToolbar();// 撤消工具条 LRESULT OnToolbarNeedText(WPARAM, LPNMHDR pnmh, BOOL&); // 工具条上按钮的提示信息 protected: ...
进入游戏 在这里我们以最基础的开始学习,以初级游戏为基础,打开软件,开始→所有程序→游戏→扫雷;启动游戏后能看到这么一个窗口。 开始游戏 点击笑脸,则开始游戏计时。计时器位于右侧,总雷数位于左侧,扫除一个则左侧数字减少一个。 随意点击 红框的地方是告诉你在这个游戏中总共有几个地雷。上来是没有办法的,第一步只能随...
Java界面设计应该是一项布满创造性、富有乐趣的工作,但是却往往被认为非常的枯燥和繁琐。究其原因,是因为界面布局领域所采用的描述概念和具体的实现语言之间存在很大的语义隔阂。而一般的界面开发工具提供的所见即所得以及界面布局治理器等方案也无法很好地解决这个问题。 在本文中,我们会给出一种更好的解决方案,我们不是去试图把...
躲避了NP的扫描现在就可以模拟了! -------------------------------------------------------------------------------------------------------------------------------------------------------- 需要VBAPI函数: keybd_event←函数模拟了键盘行动 ----------------------------------------------------------------------...
界面设计应该是一项布满创造性、富有乐趣的工作,但是却往往被认为非常的枯燥和繁琐。究其原因,是因为界面布局领域所采用的描述概念和具体的实现语言之间存在很大的语义隔阂。而一般的界面开发工具提供的所见即所得以及界面布局治理器等方案也无法很好地解决这个问题。 在本文中,我们会给出一种更好的解决方案,我们不是去试图把界...

经验教程

379

收藏

95
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部