近来在重温一个游戏,感觉兴趣来了,想做个修改器什么的,现在碰到两个问题,特来请教:1,我的修改器进程能否在游戏的画面内显示一个窗口(windows,非模式的),这个窗口可以接收特殊按键(就是游戏没定义的按键),但我这个窗口使用的是游戏的主线程,通过按键调出,是否可行,大概应该怎么做?2,如果我正在桌面操作我的修改器,我能否调用什么函数使之从桌面切换到游戏中谢了
解决方案 »
- 有一个数组去掉连续出现次数少的数字的问题,非高手莫进
- 介绍些好点的Delphi网站给我学习学习了~~~!
- N久不接触软件开发了,想问一下数据库网络程序开发大家现在一般都用什么,内详
- 在DELPHI里怎么判断星期六和星期日?
- 大家都是用什么控件来显示数据库中有多少条记录以及当前正在编辑的记录号?
- 一个动态调用控件的问题
- [--申请一个外部ip地址要多少钱--]
- 请问char和string 之间如何相互转换
- VCLZIP的多卷压缩问题
- 后台线程是否支持定时事件?
- [Microsoft][ODBC SQL Server Driver]没有提供需要的指示器变量,这种错误怎么处理?在线等,急
- 怎样计算出dbgrid的行数`
1.DX写的游戏,初始化的时候,有个地方是控制是否独占,一般全屏的游戏都是独占的,看看改变它,然后让你的窗体最前端显示行不2.DX写的游戏,一般都会有页面保护,主页面丢失,游戏一般就会终止,切换回去的时候,重新让他获得主页面就会继续,不知道是不是这个……
我第一个问题是这样的:
就是我正在玩游戏,然后我按下我定义的hotkey,然后捕获程序不离开游戏画面在一个角落显示一个小窗口,这个窗口接不接收按键都无所谓,如果我可以截获所有的按键和鼠标的话,这样行不行?我听说好像DX写的程序用钩子是无法钩住鼠标和按键的,是不是这样,有没有其他解决办法
我没弄过DX,不知道他和Windows有什么区别,你给我讲讲课阿第二个问题,有点像alt-tab切换进程,就是切换回游戏,需要什么特殊函数么,还是ShowWindow就可以?DX的画面是Window么?
现在WOW也提供了SDK和接口,现在有好多这种嵌入到游戏的第三方插件
在网上可以搜到这类网站to alphax:我也没研究过这个,不明白……DX的初始化过程一般是这样的,贴段代码给你你一看就知道了
以DDraw为例,重点看InitDDraw这个函数,其他的基本上是win32下创建窗体那一套,对你来说小菜一碟
#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;
}
{
//释放接口
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;
}
游戏用Window那一套来弄就好办
我晚上回家看看游戏是否用消息来处理键盘和鼠标的,具体问题明天再来讨教现在想问,我想实现在DX的屏幕内显示一个置顶的窗口,不知道难度大不大?
我有了新想法,不要在进程外操作它,我可以用我的程序来引导它,在他执行以前安排我一个DLL在他的进程内,然后通过键盘钩子使用它的游戏窗口线程来创建一个窗口,但是这个窗口必须和游戏窗口在同一个屏幕内,我的初步想法是把他安排在一个固定的角落,我按某个键时他才出来,有没有办法?或者在游戏窗口内开个区域显示也可以我观察了一下,可以钩住键盘消息,但是鼠标消息勾不住,估计是用了DXInput,在XP下好像有一个wm_input消息和dxinput有关,我还没有具体试昨晚看了一下dx的例子程序,头昏啊,咔咔,很多东西根本没接触过,概念很多,不知从何开始,还有几何的东西,混乱阿,咔咔不过不着急,反正不是工作上的东西,慢慢来,先熟悉一些基本的dx概念再说,咔咔