近来在重温一个游戏,感觉兴趣来了,想做个修改器什么的,现在碰到两个问题,特来请教:1,我的修改器进程能否在游戏的画面内显示一个窗口(windows,非模式的),这个窗口可以接收特殊按键(就是游戏没定义的按键),但我这个窗口使用的是游戏的主线程,通过按键调出,是否可行,大概应该怎么做?2,如果我正在桌面操作我的修改器,我能否调用什么函数使之从桌面切换到游戏中谢了

解决方案 »

  1.   

    外挂?  alphax 怎么也对这个玩意感兴趣了?哈哈 俺也不会,瞎说几句,不知道对不对
    1.DX写的游戏,初始化的时候,有个地方是控制是否独占,一般全屏的游戏都是独占的,看看改变它,然后让你的窗体最前端显示行不2.DX写的游戏,一般都会有页面保护,主页面丢失,游戏一般就会终止,切换回去的时候,重新让他获得主页面就会继续,不知道是不是这个……
      

  2.   

    别笑话我了,我从来没弄过,你来了就好
    我第一个问题是这样的:
    就是我正在玩游戏,然后我按下我定义的hotkey,然后捕获程序不离开游戏画面在一个角落显示一个小窗口,这个窗口接不接收按键都无所谓,如果我可以截获所有的按键和鼠标的话,这样行不行?我听说好像DX写的程序用钩子是无法钩住鼠标和按键的,是不是这样,有没有其他解决办法
    我没弄过DX,不知道他和Windows有什么区别,你给我讲讲课阿第二个问题,有点像alt-tab切换进程,就是切换回游戏,需要什么特殊函数么,还是ShowWindow就可以?DX的画面是Window么?
      

  3.   

    我最感到好奇的是,暗黑里的外挂,加载后他们会整合到暗黑游戏里,游戏会打出一行“xxx has been installed”,而且还可以接收暗黑聊天里的文字,作为自己的命令。比如在聊天框里输入".stop" 外挂就会停止运行,而且这行字还不会发送出去感觉挺牛的,不知道怎么实现的。
      

  4.   

    楼上说的是通过暴雪提供的接口和SDK实现的,否则不可能让游戏的控制台调用
    现在WOW也提供了SDK和接口,现在有好多这种嵌入到游戏的第三方插件
    在网上可以搜到这类网站to alphax:我也没研究过这个,不明白……DX的初始化过程一般是这样的,贴段代码给你你一看就知道了
    以DDraw为例,重点看InitDDraw这个函数,其他的基本上是win32下创建窗体那一套,对你来说小菜一碟
      

  5.   

    #include "stdafx.h"
    #include "resource.h"
    #define INITGUID
    #include 
    #define SafeRelease(x) if (x) { x->Release(); x=NULL; }//函数声明
    BOOL InitWindow( HINSTANCE hInstance, int nCmdShow );
    LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
    void DrawImage();//变量说明
    HWND hWnd; //窗口句柄LPDIRECTDRAW7 lpDD=NULL;// DirectDraw对象的指针
    LPDIRECTDRAWSURFACE7 lpDDSPrimary=NULL;// DirectDraw主页面的指针
    LPDIRECTDRAWCLIPPER lpClip=NULL; // DirectDraw 剪裁对象
    LPDIRECTDRAWSURFACE7 lpBmp=NULL; // 存放背景图的页面的指针//************************************************************
    //函数:InitDDraw()
    //功能:DX初始化函数
    //************************************************************
    BOOL InitDDraw()
    {
     DDSURFACEDESC2 ddsd; // DirectDraw的页面描述
     HRESULT hRet;
      /*
        如果要使用DirectDraw,必须创建一个DirectDraw对象,它是DirectDraw接口的核心。
        用DirectDrawCreateEx( )函数可以创建DirectDraw对象,
        DirectDrawCreateEx( )函数是在ddraw.h中定义的,它的原型如下:       HRESULT WINAPI DirectDrawCreateEx(
             GUID FAR *lpGUID, //指向DirectDraw接口的GUID的指针,NULL表示采用默认(当前)
             LPVOID *lplpDD,   //用来接受初始化的DirectDraw对象的地址
             REFIID iid,       //IID_IDirectDraw7,当前版本
             IUnknown FAR *pUnkOuter  //NULL  保留
        ); 
        所有的DirectDraw函数的返回值都是HRESULT类型,它是一个32位的值。
        函数调用成功用 "DD_OK"表示,
        所有的错误值标志开头都为"DDERR",如:
        DDERR_DIRECTDRAWALREADYCREATED
        DDERR_OUTOFMEMORY 
      */
      if (DirectDrawCreateEx(NULL,(LPVOID*)&lpDD, IID_IDirectDraw7, NULL)!= DD_OK)
        return FALSE; //创建DirectDraw对象
      /*
      DirectDrawCreate函数调用成功后,lpDD已经指向了一个DirectDraw对象,
      它是整个DirectDraw接口的最高层领导,以后的步骤都是在它的控制之下。
      我们用IDirectDraw7::SetCooperativeLevel( )来设置DirectDraw程序对系统的控制级。
      它的原型如下:
      HRESULT SetCooperativeLevel (HWND hWnd, DWORD dwFlags )
      第一个参数是窗口句柄,我们给它hWnd,使DirectDraw对象与主窗口联系上。
         第二个参数是控制级标志。这里使用DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN,
      表示我们期望DirectDraw以独占和全屏方式工作。
         
      控制级描述了DirectDraw是怎样与显示设备及系统作用的。
      DirectDraw控制级一般被用来决定应用程序是运行于全屏模式(必须与独占模式同时使用),
      还是运行于窗口模式。但DirectDraw的控制级还可设置如下两项:
         (1)允许按Ctrl+Alt+Del重新启动(仅用于独占模式,为DDSCL_ALLOWREBOOT)。
         (2)不允许对DirectDraw应用程序最小化或还原 (DDSCL_NOWINDOWCHANGES)。
         
      普通的控制级(DDSCL_NORMAL)表明我们的DirectDraw应用程序将以窗口的形式运行。
      在这种控制级下,我们将不能改变显示器分辨率,或进行换页操作(这是一个重要的操作)。
      除此之外,我们也不能够调用那些会对显存产生激烈反应的函数,如Lock()。
         当应用程序为全屏并且独占的控制级时,我们就可以充分的利用硬件资源了。
      此时其它应用程序仍可创建页面、使用DirectDraw或GDI的函数,只是无法改变显示模式。
      */ 
         if (lpDD->SetCooperativeLevel(hWnd,DDSCL_NORMAL)!= DD_OK) 
            return FALSE; //设置DirectDraw控制级
      /*
      下一步我们使用IDirectDraw7::SetDisplayMode( )来设置显示模式,其原形为:
      HRESULT SetDisplayMode(
      DWORD dwWidth, 
      DWORD dwHeight, //dwWidth and dwHeight用来设置显示模式的宽度和高度。
      DWORD dwBPP, //dwBPP用来设置显示模式的颜色位数。
      DWORD dwRefreshRate, //dwRefreshRate设置屏幕的刷新率,0为使用默认值。
      DWORD dwFlags //dwFlags现在唯一有效的值是DDSDM_STANDARDVGAMODE
      );
      */
         if (lpDD->SetDisplayMode(1024,768,32,0,DDSDM_STANDARDVGAMODE)!= DD_OK) 
            return FALSE; //设置显示模式
      /*
      HRESULT CreateClipper(
      DWORD dwFlags, //现在不用,必须设为0
      LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,//指向剪裁器对象的指针
      IUnknown FAR *pUnkOuter // //现在不用,必须设为NULL
      );
      成功的时候返回DD_OK
      */  //创剪裁器(必须在设置完DirectDraw控制级后,创建主页面之前进行)
      hRet=lpDD->CreateClipper(NULL,&lpClip,NULL);
      if (hRet != DD_OK) {
       return FALSE;
      }
      lpClip->SetHWnd(0,hWnd);    /*
       创建一个页面之前,首先需要填充一个DDSURFACEDESC2结构,
       它是DirectDraw Surface Description的缩写,意思是DirectDraw的页面描述。
       它的结构非常庞大,这里只能作一个最简单的介绍。
       要注意的是在填充此结构前一定要将其清空!
     */ //开始创建主页面,先清空页面描述
     ZeroMemory(&ddsd, sizeof(ddsd)); //填充页面描述
        ddsd.dwSize = sizeof(ddsd);//给dwSize页面描述的大小
     ddsd.dwFlags = DDSD_CAPS;
        ddsd.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE;//主页面
        /*
     CreateSurface( )函数的第一个参数是被填充了页面信息的DDSURFACEDESC2结构的地址,
     此处为&ddsd;
     第二个参数是接收主页面指针的地址,此处为&lpDDSPrimary;
     第三个参数现在必须为NULL,为该函数所保留。
        如果函数调用成功,lpDDSPrimary将成为一个合法的主页面对象。
     由于在前面已经设置了该程序的工作模式为独占和全屏,
     所以,此时主页面所代表的实际上是我们的整个显示屏幕。
     在主页面上所绘制的图形将立即反映到我们的显示屏幕上。
     */
         if (lpDD->CreateSurface(&ddsd,&lpDDSPrimary, NULL) != DD_OK )
           return FALSE; //创建主页面
        lpDDSPrimary->SetClipper(lpClip);//设置剪裁
     //载入图片
     lpBmp=bitmap_surface(PicName);
     //画图
        DrawImage();
     return TRUE;
    }
      

  6.   

    void Cleanup(void)
    {
     //释放接口
     SafeRelease(lpBmp);
     SafeRelease(lpDDSPrimary);//删除主页面
     SafeRelease(lpClip);//删除剪裁
     SafeRelease(lpDD);//删除ddraw对象
     //ps:与创建的顺序正好相反
    }
    void DrawImage()
    {
     if (lpBmp==NULL)
     {
      return;
     }
     //全屏画图
     lpDDSPrimary->Blt(NULL,lpBmp,NULL,DDBLT_WAIT,NULL);
    }//************************************************************
    //函数:WinMain( )
    //功能:Windows程序入口函数。创建主窗口,处理消息循环
    //************************************************************
    int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
      if ( !InitWindow( hInstance, nCmdShow ) ) return FALSE; //创建主窗口
      //如果创建不成功则返回FALSE并同时退出程序
      MSG msg;
      //进入消息循环:
      for(;;)
      {
     if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
     {
      if ( msg.message==WM_QUIT) break;
      TranslateMessage(&msg); 
      DispatchMessage(&msg);
     }
      }
       return msg.wParam;
    }//************************************************************
    //函数:InitWindow( )
    //功能:创建窗口
    //************************************************************static BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )
    {
     //定义窗口风格:
     WNDCLASS wc; 
     wc.style = CS_VREDRAW|CS_HREDRAW;//窗体类的风格
     wc.lpfnWndProc = (WNDPROC)WinProc; //窗口消息处理函数的指针
     wc.cbClsExtra = 0;//分配给窗口类结构之后的额外字节数
     wc.cbWndExtra = 0;//分配给窗口实例之后的额外字节数
     wc.hInstance = hInstance;//窗口所对应的应用程序的句柄
     wc.hIcon = NULL;//窗口的图标
     wc.hCursor = LoadCursor(NULL, IDC_ARROW); //窗口的鼠标
     wc.hbrBackground = CreateSolidBrush (RGB(0, 0, 0)); //黑色的背景
     wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);//窗口的菜单资源名称
     wc.lpszClassName = "My_Test";//窗口类的名称
     RegisterClass(&wc);//注册窗口    //按所给参数创造窗口
         hWnd = CreateWindow("My_Test",//创建窗口所用的窗口类的名称
       "24小时学DX_第2个小时",//窗口标题
       WS_POPUP|WS_CAPTION,//窗口风格,定义为普通型
       0,0,//窗口位置的x,y坐标
       1024,768,//窗口的宽度,高度
       NULL,//父窗口句柄
       NULL,//菜单句柄
       hInstance,//应用程序句柄
       NULL);
     if(!hWnd ) return FALSE;
     ShowWindow(hWnd,nCmdShow);//显示窗口
     UpdateWindow(hWnd);//刷新窗口
     InitDDraw();//初始化DX
     return TRUE;
    }//************************************************************
    //函数:WinProc( )
    //功能:处理窗口消息
    //************************************************************LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
    {
     switch(message)
     {
     case WM_COMMAND:
      switch (LOWORD(wParam))
      {
      case IDM_Exit:
        DestroyWindow(hWnd);
        break;
      }
       break;
     case WM_KEYDOWN://击键消息
      switch(wParam)
      {
      case VK_ESCAPE:
       PostMessage(hWnd, WM_CLOSE, 0, 0);//给窗口发送WM_CLOSE消息
       break;
      }
      break;
     case WM_PAINT://画图消息
      PAINTSTRUCT ps;
      BeginPaint(hWnd, &ps);
      DrawImage();
      EndPaint(hWnd, &ps);
      break;
     case WM_DESTROY: //如果窗口被人释放…
      Cleanup();
         PostQuitMessage(0); //给窗口发送WM_QUIT消息
      break;
        default://调用缺省消息处理过程
      return DefWindowProc(hWnd, message, wParam, lParam);  
     } 
     return 0;
    }
      

  7.   

    看到你的短信了,很感谢你给我来一段
    游戏用Window那一套来弄就好办
    我晚上回家看看游戏是否用消息来处理键盘和鼠标的,具体问题明天再来讨教现在想问,我想实现在DX的屏幕内显示一个置顶的窗口,不知道难度大不大?
      

  8.   

    有点难度,DxDraw好像还没有提供接口可以让进程外的程序操作它,一些的外挂好像是用了游戏本身提供的Plugin技术!
      

  9.   

    昨晚弄了一下,好像直接显示一个窗口不行,我试着显示一个窗口,结果导致游戏退回桌面来显示我的窗口to 甲骨文:
    我有了新想法,不要在进程外操作它,我可以用我的程序来引导它,在他执行以前安排我一个DLL在他的进程内,然后通过键盘钩子使用它的游戏窗口线程来创建一个窗口,但是这个窗口必须和游戏窗口在同一个屏幕内,我的初步想法是把他安排在一个固定的角落,我按某个键时他才出来,有没有办法?或者在游戏窗口内开个区域显示也可以我观察了一下,可以钩住键盘消息,但是鼠标消息勾不住,估计是用了DXInput,在XP下好像有一个wm_input消息和dxinput有关,我还没有具体试昨晚看了一下dx的例子程序,头昏啊,咔咔,很多东西根本没接触过,概念很多,不知从何开始,还有几何的东西,混乱阿,咔咔不过不着急,反正不是工作上的东西,慢慢来,先熟悉一些基本的dx概念再说,咔咔