我自己写了个程序来随便找了个全屏游戏实现窗口化,发现虽然可以改变窗口大小,也显示是窗体(有Caption),但是并不能实现真正意义上的窗口化,只要我点一下窗口以外的空间,立刻被切换到桌面,而且关键是颜色不对,游戏窗口以外的颜色似乎是256色,很奇怪,dmBitsPerPel我设置了32位啊
哪位朋友能帮忙解释一下,谢谢了
我的部分代码 HWND hWnd = ::FindWindow(NULL, "Age of Empires II Expansion");//查找主窗体的句柄 DEVMODE devmode; if(EnumDisplaySettings(0, 0, &devmode))
{
devmode.dmPelsWidth=800;
devmode.dmPelsHeight=600;
devmode.dmBitsPerPel=16;
devmode.dmDisplayFrequency=75;
ChangeDisplaySettings(&devmode,0);
}
///修改窗体属性
long style,exstyle;
style= GetWindowLong(hWnd,GWL_STYLE);
style=style | WS_CAPTION ;
SetWindowLong(hWnd,GWL_STYLE,style);//修改窗体的exstyle属性
exstyle=GetWindowLong(hWnd,GWL_EXSTYLE);
exstyle=exstyle | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
SetWindowLong(hWnd,GWL_EXSTYLE,exstyle);
////
::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,width,height,SWP_SHOWWINDOW);
::ShowWindow(hWnd,SW_SHOWNORMAL);
哪位朋友能帮忙解释一下,谢谢了
我的部分代码 HWND hWnd = ::FindWindow(NULL, "Age of Empires II Expansion");//查找主窗体的句柄 DEVMODE devmode; if(EnumDisplaySettings(0, 0, &devmode))
{
devmode.dmPelsWidth=800;
devmode.dmPelsHeight=600;
devmode.dmBitsPerPel=16;
devmode.dmDisplayFrequency=75;
ChangeDisplaySettings(&devmode,0);
}
///修改窗体属性
long style,exstyle;
style= GetWindowLong(hWnd,GWL_STYLE);
style=style | WS_CAPTION ;
SetWindowLong(hWnd,GWL_STYLE,style);//修改窗体的exstyle属性
exstyle=GetWindowLong(hWnd,GWL_EXSTYLE);
exstyle=exstyle | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
SetWindowLong(hWnd,GWL_EXSTYLE,exstyle);
////
::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,width,height,SWP_SHOWWINDOW);
::ShowWindow(hWnd,SW_SHOWNORMAL);
看看DirectX关于初始化DirectDraw,Direct3D的部分,建立桌面窗口游戏在DirectX初始化的时候就需要指定的,和建立全屏幕的不同,而且游戏里DirectDraw的表面(IDirectDrawSurface)会不一致
能不能好人帮到底,再多给点提示,或给点资料文档什么的呢?
谢谢了~
常运行)
prevproc=(PROC)GetWindowLong(hwnd,GWL_WNDPROC);
SetWindowLong(hwnd,GWL_WNDPROC,(long)MyProc);//设置窗体消息过滤函数(函数见下面
),设置好 后,那个全屏程序仍然能正常运行,而且此时可以随便按WIN键切换出任务栏。DWORD style=GetWindowLong(hwnd,GWL_STYLE);
style = style | WS_CAPTION;
SetWindowLong(hwnd,GWL_STYLE,style);//给全全屏程序的窗体设置标题栏,这行只要一执行,全屏游戏,马上就缩小成640*480的窗口模式(但并没有标题栏),同时,这个窗口将不接受任何消息,整个窗口就和死了一样,但是程序内部还是在运行的(程序的声音部分还在运行),这样下面的那些代码基本就执行不下去了。DWORD exstyle=GetWindowLong(hwnd,GWL_EXSTYLE);
exstyle = exstyle | 0x40100;
SetWindowLong(hwnd,GWL_EXSTYLE,exstyle);
SetWindowPos(hwnd,HWND_NOTOPMOST ,0 ,0 ,648 ,505 ,SWP_SHOWWINDOW);
ShowCursor(true);窗口消息过滤函数
主要是为了欺骗全屏程序让它以为自己还是在一个全屏模式下工作
switch(message)
{
case WM_ACTIVATEAPP://0x1c
case WM_ACTIVATE://0x6
case WM_SETFOCUS: //0x7
case WM_KILLFOCUS: //0x8
return 0;
default:
break;}
return CallWindowProcA((WNDPROC)prevproc,hWnd,message,wParam,lParam);
SetWindowLong(hwnd,GWL_WNDPROC,(long)MyProc);
//MyProc是自己写的处理函数,如下:LRESULT CALLBACK MyProc(HWND hwnd,UINT umsg,WPARAM wparam,LPARAM lparam)
{
//消息过滤
switch (umsg)
{
case WM_ACTIVATEAPP:
case WM_ACTIVATE:
case WM_KILLFOCUS:
case WM_SETFOCUS:
case WM_CLOSE:
return 0;
}
return CallWindowProc(oldproc,hwnd,umsg,wparam,lparam);
}同时为了能让目标程序能调用这个函数,必须保证这个函数与目标程序在同一个进程内,所以经常使用键盘钩子之类的方法注入到目标进程当中。
不知道你是不是在上面发过一篇这个类似的帖子。 ;)
我在MSDN里看到的例子的是这样的,怎么回事?
//在全局键盘钩子里面对游戏进行窗口化。
LRESULT _declspec(dllexport) CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if((HIWORD(lParam) & KF_UP) == 0 && nCode==HC_ACTION)
{
if(wKey == g_nHotKey)//是热键
{
HWND hwnd = GetActiveWindow();
GetWindowText(hwnd, szText, 100);
if (hwnd)
{
ChangeDisplaySettings(NULL,0);
style= GetWindowLong(hwnd,GWL_STYLE);
style=style | WS_CAPTION ;
SetWindowLong(hwnd,GWL_STYLE,style);
exstyle=GetWindowLong(hwnd,GWL_EXSTYLE);
exstyle=exstyle | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | 0x40100;
SetWindowLong(hwnd,GWL_EXSTYLE,exstyle);
SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,807,632,SWP_SHOWWINDOW);
ShowWindow(hwnd,SW_SHOWNORMAL);
oldproc=(FARPROC)GetWindowLong(hwnd,GWL_WNDPROC);
if(SetWindowLong(hwnd,GWL_WNDPROC,(long)WINPROC)==0)
return false;
return true;
}
}
}不过在cs里面测试的时候也有点问题,就是窗口化以后,点击cs的菜单切换界面的时候,cs又最大化了(因为没有处理其他的事件)。但是游戏开始以后窗口化就没什么问题。
现在我按楼上的hyamw(林锋) 朋友的意思,写在DLL里,我以前是直接写在程序里,就会产生我上述的问题,我想也许是不在一个进程的原因?
但现在又出现了新问题,窗口化后,窗口里都是黑屏,程序跟死掉似的,但声音还是有的,还请hyamw(林锋)朋友继续关注了,再次感谢!!
黑屏的话,我也不是很清楚了,手里没有帝国时代2的游戏,没法测试。有可能是像gameres论坛上的一篇将mu游戏窗口化说的那样,还需要处理一些其它的事情吧。你把你的代码贴上来看看
不过,对于全屏游戏,则会产生游戏虽然窗体化,不过窗体外部的界面会是256色,窗体内部游戏的进行并没有问题,但点击窗体外部会快速的切回桌面采用了DLL来安装全局钩子后,虽然全屏可以窗体话,而且窗体外部的颜色也显示正常,但是窗体内部是黑屏(晕),游戏的声音还是有的代码:
LRESULT __declspec(dllexport) CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
{
switch(wParam)
{case 'F':
{
HWND hwnd = ::FindWindow(NULL, "Age of Empires II Expansion");
// GetWindowText(hwnd, szText, 100);
if (hwnd)
{
DWORD exstyle,style;
ChangeDisplaySettings(NULL,0);
style= GetWindowLong(hwnd,GWL_STYLE);
style=style | WS_CAPTION ;
SetWindowLong(hwnd,GWL_STYLE,style);
exstyle=GetWindowLong(hwnd,GWL_EXSTYLE);
exstyle=exstyle | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | 0x40100;
SetWindowLong(hwnd,GWL_EXSTYLE,exstyle);
SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,807,632,SWP_SHOWWINDOW);
ShowWindow(hwnd,SW_SHOWNORMAL);
oldproc=(WNDPROC)GetWindowLong(hwnd,GWL_WNDPROC);
if(SetWindowLong(hwnd,GWL_WNDPROC,(long)MyProc)==0)
return false;
} };break;
case :..//其他的键
}
}
return true;
}LRESULT CALLBACK MyProc(HWND hwnd,UINT umsg,WPARAM wparam,LPARAM lparam)
{
//消息过滤
switch (umsg)
{
case WM_ACTIVATEAPP:
case WM_ACTIVATE:
case WM_KILLFOCUS:
case WM_SETFOCUS:
case WM_CLOSE:
return 0;
}
return CallWindowProc(oldproc,hwnd,umsg,wparam,lparam);
}调用的就不用写了吧?
不知道你用的什么方法,说来听听