我自己写了个程序来随便找了个全屏游戏实现窗口化,发现虽然可以改变窗口大小,也显示是窗体(有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);

解决方案 »

  1.   

    这样可以吗?
    看看DirectX关于初始化DirectDraw,Direct3D的部分,建立桌面窗口游戏在DirectX初始化的时候就需要指定的,和建立全屏幕的不同,而且游戏里DirectDraw的表面(IDirectDrawSurface)会不一致
      

  2.   

    楼上说的似乎很有道理,不过在下对DirectX一点研究都没有
    能不能好人帮到底,再多给点提示,或给点资料文档什么的呢?
    谢谢了~
      

  3.   

    ChangeDisplaySettings(NULL,0);//屏幕分辨率改成桌面默认(此时全屏程序仍然能全屏正
    常运行)
    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);
      

  4.   

    关键的地方在于
    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);        
    }同时为了能让目标程序能调用这个函数,必须保证这个函数与目标程序在同一个进程内,所以经常使用键盘钩子之类的方法注入到目标进程当中。
      

  5.   

    http://bbs.gameres.com/showthread.asp?threadid=3741&
    不知道你是不是在上面发过一篇这个类似的帖子。  ;)
      

  6.   

    为什么我调用SetWindowLong(hwnd,GWL_WNDPROC,(long)MyProc);时,会提示无法从LRESULT转换到long??
    我在MSDN里看到的例子的是这样的,怎么回事?
      

  7.   

    但是我在cs下面测试了一下,没有问题。
    //在全局键盘钩子里面对游戏进行窗口化。
    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又最大化了(因为没有处理其他的事件)。但是游戏开始以后窗口化就没什么问题。
      

  8.   

    强制转换我回上个帖子时已经没问题了
    现在我按楼上的hyamw(林锋) 朋友的意思,写在DLL里,我以前是直接写在程序里,就会产生我上述的问题,我想也许是不在一个进程的原因?
    但现在又出现了新问题,窗口化后,窗口里都是黑屏,程序跟死掉似的,但声音还是有的,还请hyamw(林锋)朋友继续关注了,再次感谢!!
      

  9.   

    晕,不放在DLL里面是肯定有问题的。因为SetWindowLong设置子类化消息处理函数的时候,目标窗口会调用这个函数,而不放在DLL里面利用键盘钩子注入到目标进程的话,游戏窗口与MyProc函数是在不同的两个进程内,这样直接访问是非法的。
    黑屏的话,我也不是很清楚了,手里没有帝国时代2的游戏,没法测试。有可能是像gameres论坛上的一篇将mu游戏窗口化说的那样,还需要处理一些其它的事情吧。你把你的代码贴上来看看
      

  10.   

    我开始是直接在程序里SetWindowLong,这样,对于非全屏的程序,游戏,都可以改变窗体大小
    不过,对于全屏游戏,则会产生游戏虽然窗体化,不过窗体外部的界面会是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);        
    }调用的就不用写了吧?
      

  11.   

    DirectX的窗口,并不是真正的窗口你不能那样搞得的。。
      

  12.   

    还是建议你,研究一下,directx, 如果在 游戏的窗口,与全屏之间切换吧。。在游戏内部很好实现,在外部,我就不知道了。。我曾经,用F11做过切换健,没问题的
      

  13.   

    不要用它的那个方法,对普通窗口可以,对游戏不行,directx有自己的调色板的,所以会 256
      

  14.   

    谢谢楼上的建议,不过,用SetWindowLong()的办法似乎是可以实现的,我再看看.
      

  15.   

    晕,又是这个问题。我自己做的时候没碰到过。http://community.csdn.net/Expert/topic/3585/3585702.xml?temp=.7331507你问问那个帖子的楼主怎么解决的。解决了,告诉一下我答案。  :)
      

  16.   

    to: Mycro(莫论国事,违者杀头) 
    不知道你用的什么方法,说来听听