下面这段代码可以让OpenGL游戏窗口化,显示正常,但是DirectX游戏窗口化可以,然而窗口化后,游戏屏幕全是黑的,怎样让DirectX游戏窗口化呢?
DirectX游戏是独占模式的,怎样才能取消其独占呢?// MyGame.cpp : 通用游戏窗口话程序,一般能改变分辨率的游戏都可以使用
//阿龙软件出品.#include "stdafx.h"
#include <afxdllx.h>
#include "MyGame.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif#pragma data_seg("ShareData")
HHOOK glhHook=NULL;
HINSTANCE glhInstance=NULL;
UINT KeyPressed;
UINT AutoTalkFlag;
HWND hwndmu;
HHOOK hHook;
HINSTANCE pHinstance;
bool bs=false;
WNDPROC oldproc;
#pragma data_seg()void __declspec(dllexport) WINAPI InstallHook(BOOL,DWORD);BOOL WINAPI UnInstallHook();
LRESULT CALLBACK HookProc(int ,WPARAM ,LPARAM);
LRESULT CALLBACK MyMsgProc(HWND hwnd,UINT umsg,WPARAM wparam,LPARAM lparam);
bool __stdcall winmu(void);
BOOL WINAPI UnInstallHook();static AFX_EXTENSION_MODULE MyGameDLL = { NULL, NULL };extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved); if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("MyGame.DLL Initializing!\n");

// Extension DLL one-time initialization
if (!AfxInitExtensionModule(MyGameDLL, hInstance))
return 0; //new CDynLinkLibrary(MyGameDLL);
pHinstance = hInstance;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("MyGame.DLL Terminating!\n");
// Terminate the library before destructors are called
//AfxTermExtensionModule(MyGameDLL);
}
return 1;   // ok
}
void __declspec(dllexport) WINAPI InstallHook(BOOL IsHook,DWORD dwThreadId)
{
if(IsHook)
{
hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)HookProc,pHinstance,dwThreadId);
}
else
{
UnInstallHook();
}
}
LRESULT CALLBACK HookProc(int ncode,WPARAM wparam,LPARAM lparam)
{
if(ncode<0)
return CallNextHookEx(hHook,ncode,wparam,lparam);
//用一个bool变量让我们的MyGame()只调用一次
if (!bs)  
MyGame();
bs=true;
return CallNextHookEx(hHook,ncode,wparam,lparam);
}
bool __stdcall MyGame(void)
{
long style;
long exstyle;
DEVMODE  devmode;
hwndmu=GetForegroundWindow();
// hwndmu=(HWND)FindWindow(NULL,"Dweep");
if(EnumDisplaySettings(0, 0, &devmode))
{
devmode.dmPelsWidth=1024;
devmode.dmPelsHeight=768;
devmode.dmBitsPerPel=32;
devmode.dmDisplayFrequency=75;
ChangeDisplaySettings(&devmode,0);
}
//修改窗体的style属性
style= GetWindowLong(hwndmu,GWL_STYLE);
style=style | WS_CAPTION ;
SetWindowLong(hwndmu,GWL_STYLE,style);
//修改窗体的exstyle属性
exstyle=GetWindowLong(hwndmu,GWL_EXSTYLE);
exstyle=exstyle | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
SetWindowLong(hwndmu,GWL_EXSTYLE,exstyle);
//设置窗体的位置,取消其最前端显示,
SetWindowPos(hwndmu,HWND_NOTOPMOST,0,0,800,600,SWP_SHOWWINDOW); //
ShowWindow(hwndmu,SW_SHOWNORMAL);
//修改窗体的回调函数地址到我们自己定义的回调函数
oldproc=(WNDPROC)GetWindowLong(hwndmu,GWL_WNDPROC);
if(SetWindowLong(hwndmu,GWL_WNDPROC,(long)MyMsgProc)==0)
return false;
return true;
}
LRESULT CALLBACK MyMsgProc(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;

case WM_TIMER:
if(wparam==0x3e9)
KillTimer(hwnd,wparam);
break;
    }
return CallWindowProc(oldproc,hwnd,umsg,wparam,lparam);
}
BOOL WINAPI UnInstallHook()
{
UnhookWindowsHookEx(hHook);
return TRUE;
}

解决方案 »

  1.   

    整个画面全部被 DirectX 独占,这种模式叫 "Full Screen Mode(全屏模式)",需要高速描绘的游戏程序,很多都使用全屏模式。
      这回我们让 DirectX 程序与其他 Windows 程序同屏显示。
      这个模式其实就是标准 Windows 程序的运行方式,所以称作 "Windowed Mode(窗口模式)" 。在窗口模式下,参照同时运行的其它程序来切换窗口、移动、调整大小等因素都必须考虑。 
    以窗口模式初始化 DirectX 的代码。
    "320,240" 是窗口的初始大小,这里让它跟要显示的图象大小一样: 
        if (FAILED(hr = g_pDisplay->CreateWindowedDisplay(hWnd,320,240)))
        {   ERMSG("Failed initializing DirectDraw.");
            return hr;
        }
     
    窗口模式的 CALLBACK 函数。
    用它来处理窗口的移动、调整大小等事件: 
    //★ MainWndProc()
    LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {   switch (msg)
        {   case WM_KEYDOWN:
                 PostMessage(hWnd,WM_CLOSE,0,0);
                 return 0L;
            case WM_PAINT:
                 if (g_pDisplay)
                 {   // Display the new position of the sprite
                     if (DisplayFrame() == DDERR_SURFACELOST)
                     {   PostMessage(hWnd,WM_CLOSE,0,0);
                     }
                 }
                 break;
            case WM_MOVE:
                 if (g_pDisplay)    g_pDisplay->UpdateBounds();
                 return 0L;
            case WM_SIZE:
                 // Check to see if we are losing our window...
                 if (SIZE_MAXHIDE==wParam||SIZE_MINIMIZED==wParam)  g_bActive= FALSE;
                 else   g_bActive= TRUE;
                 if (g_pDisplay)    g_pDisplay->UpdateBounds();
                 break;
            case WM_DESTROY:
                 // Cleanup and close the app
                 FreeDirectDraw();
                 PostQuitMessage(0);
                 return 0L;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
     
      本章的例子编译成功后,试试用鼠标拖曳来改变窗口大小。图象的大小、 Aspect Ratio(纵横比) 会适应窗口的大小而改变。
      如果把 "WM_SIZE:" 下面这行注释起来跳过编译,再改变窗口大小的时候图象的大小就不会随着改变了: 
    //    if (g_pDisplay)    g_pDisplay->UpdateBounds(); 
      其它的跟以前的程序一样。  
      窗口模式也能使用 Common 文件夹下那4个文件,跟上一节一样,我们也把它复制到工程文件夹。
      下面说明工程的创建方法。1. 新建一个 Win32 Application 空白工程,命名为 "Winmode"。2. 向工程中新建一个 C++ Source File ,命名为 "winmode" ,向其中键入篇末附带的源程序。3. 把下面4个文件复制到工程文件夹(我是 G:\DirectX 8\Winmode\):
      E:\Mssdk\samples\Multimedia\Common\include\ddutil.h
      E:\Mssdk\samples\Multimedia\Common\include\dxutil.h
      E:\Mssdk\samples\Multimedia\Common\src\ddutil.cpp
      E:\Mssdk\samples\Multimedia\Common\src\dxutil.cpp
      然后选择菜单 [Project|工程]-[Add To Project|添加到工程]-[Files...|文件...] ,向工程中添加这4个文件。4. 准备合适的图象文件(我是在 G:\DirectX 8\ 下放了张 "旷野中的小屋.bmp")。
      我用的图象大小是 320*240 ,实际上随便多大都可以。下面是读取图象的代码,请改成你自己准备的路径和文件名: 
      if (FAILED(hr = g_pDisplay->CreateSurfaceFromBitmap
                         (&g_pBmpSurface,"G:\\DirectX 8\\旷野中的小屋.bmp",0,0)))5. 选择菜单 [Project|工程]-[Settings...|设定...] 打开[Project Settings|工程设定] 面板,点击 [Link|链接] 标签,向 [Object/library modules|对象、库模块] 栏内添加下面4个库文件:
      dxguid.lib
      ddraw.lib
      dxerr8.lib
      winmm.lib6. 编译并执行! 
    源程序: 
    /************************************************************************/
    /*★ 用 Windowed Mode(窗口模式) 显示位图图象      2001-01-10  前田 稔 ★*/
    /************************************************************************/
    #define     STRICT
    #include    <windows.h>
    #include    <ddraw.h>
    #include    <mmsystem.h>
    #include    "ddutil.h"// Defines, constants, and global variables
    #define SAFE_DELETE(p)  { if (p) { delete (p);     (p)=NULL; } }
    #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
    #define ERMSG(x)        MessageBox(hWnd, x, "DirectDraw Samplee", MB_OK);CDisplay*   g_pDisplay    = NULL;
    CSurface*   g_pBmpSurface = NULL;
    BOOL        g_bActive     = FALSE;// Function-prototypes
    LRESULT     CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
    HRESULT     WinInit(HINSTANCE hInst, int nCmdShow, HWND* phWnd);
    HRESULT     InitDirectDraw(HWND hWnd);
    VOID        FreeDirectDraw();
    HRESULT     DisplayFrame();
      

  2.   


    //★ Windows Main
    int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow)
    {   MSG     msg;
        HWND    hWnd;    if (FAILED(WinInit(hInst, nCmdShow, &hWnd)))    return FALSE;    if (FAILED(InitDirectDraw(hWnd)))
        {   if (g_pDisplay)
                g_pDisplay->GetDirectDraw()->SetCooperativeLevel(NULL, DDSCL_NORMAL);        ERMSG("DirectDraw init failed. The sample will now exit.");
            return FALSE;
        }    while(TRUE)
        {   if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
            {   if (0 == GetMessage(&msg, NULL, 0, 0))  return (int)msg.wParam;
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {   if (g_bActive)
                {   if (FAILED(DisplayFrame()))
                    {   SAFE_DELETE(g_pDisplay);
                        ERMSG("Displaying the next frame failed. The sample will now exit.");
                        return FALSE;
                    }
                }
                else    WaitMessage();
            }
        }
    }//★ WinInit()
    HRESULT WinInit(HINSTANCE hInst, int nCmdShow, HWND* phWnd)
    {   WNDCLASS wc;
        HWND     hWnd;    // Register the Window Class
        wc.lpszClassName = TEXT("BMP View");
        wc.lpfnWndProc   = MainWndProc;
        wc.style         = CS_VREDRAW | CS_HREDRAW;
        wc.hInstance     = hInst;
        wc.hIcon         = LoadIcon(NULL,IDI_APPLICATION);
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
        wc.lpszMenuName  = NULL;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;    if (RegisterClass(&wc) == 0)    return E_FAIL;    // Create and show the main window
        hWnd = CreateWindowEx(0, TEXT("BMP View"), TEXT("WindowedMode"),
                     WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
                     CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
        if (hWnd==NULL)   return E_FAIL;    ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
        *phWnd = hWnd;    return S_OK;
    }//★ InitDirectDraw()
    HRESULT InitDirectDraw(HWND hWnd)
    {   HRESULT             hr;    g_pDisplay = new CDisplay();
        if (FAILED(hr = g_pDisplay->CreateWindowedDisplay(hWnd,320,240)))
        {   ERMSG("Failed initializing DirectDraw.");
            return hr;
        }    // Create a surface, and draw a bitmap resource on it.  
        if (FAILED(hr = g_pDisplay->CreateSurfaceFromBitmap
                           (&g_pBmpSurface,"G:\\DirectX 8\\旷野中的小屋.bmp",0,0)))
            return hr;    return S_OK;
    }//★ FreeDirectDraw()
    VOID FreeDirectDraw()
    {   SAFE_DELETE(g_pBmpSurface);
        SAFE_DELETE(g_pDisplay);
    }//★ MainWndProc()
    LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {   switch (msg)
        {   case WM_KEYDOWN:
                 PostMessage(hWnd,WM_CLOSE,0,0);
                 return 0L;
            case WM_PAINT:
                 if (g_pDisplay)
                 {   // Display the new position of the sprite
                     if (DisplayFrame() == DDERR_SURFACELOST)
                     {   PostMessage(hWnd,WM_CLOSE,0,0);
                     }
                 }
                 break;
            case WM_MOVE:
                 if (g_pDisplay)    g_pDisplay->UpdateBounds();
                 return 0L;
            case WM_SIZE:
                 // Check to see if we are losing our window...
                 if (SIZE_MAXHIDE==wParam||SIZE_MINIMIZED==wParam)  g_bActive= FALSE;
                 else   g_bActive= TRUE;
                 if (g_pDisplay)    g_pDisplay->UpdateBounds();
                 break;
            case WM_DESTROY:
                 // Cleanup and close the app
                 FreeDirectDraw();
                 PostQuitMessage(0);
                 return 0L;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }//★ DisplayFrame()
    HRESULT DisplayFrame()
    {   HRESULT hr;    // Fill the back buffer with black, ignoring errors until the flip
        g_pDisplay->Clear(0);
        // Blt all the sprites onto the back buffer
        g_pDisplay->Blt(0,0,g_pBmpSurface,NULL);
        // We are in fullscreen mode, so perform a flip and return 
        if (FAILED(hr= g_pDisplay->Present())) return hr;
        return S_OK;
    }
     
      

  3.   

    TO: BLsoft(網龍ζ龍活) 
    可能我的意思没有表达清楚,我的目的并非是在游戏程序的代码中将其窗口化,而是外挂程序,在外挂程序中将已经运行的游戏窗口化。
    谢谢你的代码。
    继续等待高手指点。
      

  4.   

    TO:cdl371 有这样的外挂.我从来没见过.外挂就外挂.为什么非要游戏窗口化呀.有的游戏本来就是要全幕的.窗口不能运行
      

  5.   

    To: BLsoft(網龍ζ龍活)
    呵呵,为了一边打游戏一边聊MM~~~~
    这样的外挂现在很流行的,以窗口化为主,MU就被很多人窗口化了,但MU是OPENGL的。但我还没有发现DirectX游戏被窗口化的,想研究一下。
      

  6.   

    #define WIN32_LEAN_AND_MEAN  // just say no to MFC#define INITGUID // make sure directX guids are included#include <windows.h>   // include important windows stuff
    #include <windowsx.h> 
    #include <mmsystem.h>
    #include <iostream.h> // include important C/C++ stuff
    #include <conio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <memory.h>
    #include <string.h>
    #include <stdarg.h>
    #include <stdio.h> 
    #include <math.h>
    #include <io.h>
    #include <fcntl.h>#include <ddraw.h> // include directdraw// DEFINES ////////////////////////////////////////////////// defines for windows 
    #define WINDOW_CLASS_NAME "WINCLASS1"// default screen size
    #define SCREEN_WIDTH    640  // size of screen
    #define SCREEN_HEIGHT   480
    #define SCREEN_BPP      8    // bits per pixel
    #define MAX_COLORS      256  // maximum colors// TYPES //////////////////////////////////////////////////////// basic unsigned types
    typedef unsigned short USHORT;
    typedef unsigned short WORD;
    typedef unsigned char  UCHAR;
    typedef unsigned char  BYTE;// MACROS /////////////////////////////////////////////////#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
    #define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)// initializes a direct draw struct
    #define DD_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }// GLOBALS ////////////////////////////////////////////////
    HWND      main_window_handle = NULL; // globally track main window
    HINSTANCE hinstance_app      = NULL; // globally track hinstance// directdraw stuffLPDIRECTDRAW7         lpdd         = NULL;   // dd object
    LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface
    LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface
    LPDIRECTDRAWPALETTE   lpddpal      = NULL;   // a pointer to the created dd palette
    LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   // dd clipper
    PALETTEENTRY          palette[256];          // color palette
    PALETTEENTRY          save_palette[256];     // used to save palettes
    DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct
    DDBLTFX               ddbltfx;               // used to fill
    DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct
    HRESULT               ddrval;                // result back from dd calls
    DWORD                 start_clock_count = 0; // used for timing// these defined the general clipping rectangle
    int min_clip_x = 0,                          // clipping rectangle 
        max_clip_x = SCREEN_WIDTH-1,
        min_clip_y = 0,
        max_clip_y = SCREEN_HEIGHT-1;// these are overwritten globally by DD_Init()
    int screen_width  = SCREEN_WIDTH,            // width of screen
        screen_height = SCREEN_HEIGHT,           // height of screen
        screen_bpp    = SCREEN_BPP;              // bits per pixel
    char buffer[80];                     // general printing buffer// FUNCTIONS //////////////////////////////////////////////
    LRESULT CALLBACK WindowProc(HWND hwnd, 
              UINT msg, 
                                WPARAM wparam, 
                                LPARAM lparam)
    {
    // this is the main message handler of the system
    PAINTSTRUCT  ps;  // used in WM_PAINT
    HDC    hdc; // handle to a device context
    char buffer[80];        // used to print strings// what is the message 
    switch(msg)
     { 
     case WM_CREATE: 
            {
      // do initialization stuff here
            // return success
      return(0);
      } break;
       
     case WM_PAINT: 
      {
      // simply validate the window 
            hdc = BeginPaint(hwnd,&ps);  
            
            // end painting
            EndPaint(hwnd,&ps);        // return success
      return(0);
         } break;
      

  7.   

    case WM_DESTROY: 
      {  // kill the application, this sends a WM_QUIT message 
      PostQuitMessage(0);        // return success
      return(0);
      } break; default:break;    } // end switch// process any messages that we didn't take care of 
    return (DefWindowProc(hwnd, msg, wparam, lparam));} // end WinProc///////////////////////////////////////////////////////////int Game_Main(void *parms = NULL, int num_parms = 0)
    {
    // this is the main loop of the game, do all your processing
    // here// for now test if user is hitting ESC and send WM_CLOSE
    if (KEYDOWN(VK_ESCAPE))
       SendMessage(main_window_handle,WM_CLOSE,0,0);// return success or failure or your own return code here
    return(1);} // end Game_Main////////////////////////////////////////////////////////////int Game_Init(void *parms = NULL, int num_parms = 0)
    {
    // this is called once after the initial window is created and
    // before the main event loop is entered, do all your initialization
    // here// create IDirectDraw interface 7.0 object and test for error
    if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
       return(0);// set cooperation to normal since this will be a windowed app
    lpdd->SetCooperativeLevel(main_window_handle, DDSCL_NORMAL);// return success or failure or your own return code here
    return(1);} // end Game_Init/////////////////////////////////////////////////////////////int Game_Shutdown(void *parms = NULL, int num_parms = 0)
    {
    // this is called after the game is exited and the main event
    // loop while is exited, do all you cleanup and shutdown here// simply blow away the IDirectDraw4 interface
    if (lpdd)
       {
       lpdd->Release();
       lpdd = NULL;
       } // end if// return success or failure or your own return code here
    return(1);} // end Game_Shutdown// WINMAIN ////////////////////////////////////////////////
    int WINAPI WinMain( HINSTANCE hinstance,
         HINSTANCE hprevinstance,
         LPSTR lpcmdline,
         int ncmdshow)
    {WNDCLASSEX winclass; // this will hold the class we create
    HWND    hwnd;  // generic window handle
    MSG     msg;   // generic message
    HDC        hdc;      // graphics device context// first fill in the window class stucture
    winclass.cbSize         = sizeof(WNDCLASSEX);
    winclass.style   = CS_DBLCLKS | CS_OWNDC | 
                              CS_HREDRAW | CS_VREDRAW;
    winclass.lpfnWndProc = WindowProc;
    winclass.cbClsExtra  = 0;
    winclass.cbWndExtra  = 0;
    winclass.hInstance  = hinstance;
    winclass.hIcon   = LoadIcon(NULL, IDI_APPLICATION);
    winclass.hCursor  = LoadCursor(NULL, IDC_ARROW); 
    winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    winclass.lpszMenuName = NULL;
    winclass.lpszClassName = WINDOW_CLASS_NAME;
    winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);// save hinstance in global
    hinstance_app = hinstance;// register the window class
    if (!RegisterClassEx(&winclass))
     return(0);// create the window
    if (!(hwnd = CreateWindowEx(NULL,                  // extended style
                                WINDOW_CLASS_NAME,     // class
              "DirectDraw Initialization Demo", // title
              WS_OVERLAPPEDWINDOW | WS_VISIBLE,
               0,0,   // initial x,y
              400,300,  // initial width, height
              NULL,   // handle to parent 
              NULL,   // handle to menu
              hinstance,// instance of this application
              NULL))) // extra creation parms
    return(0);// save main window handle
    main_window_handle = hwnd;// initialize game here
    Game_Init();// enter main event loop
    while(TRUE)
     {
        // test if there is a message in queue, if so get it
     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        { 
        // test if this is a quit
           if (msg.message == WM_QUIT)
               break;
     
        // translate any accelerator keys
        TranslateMessage(&msg);    // send the message to the window proc
        DispatchMessage(&msg);
        } // end if
        
           // main game processing goes here
           Game_Main();
           
     } // end while// closedown game here
    Game_Shutdown();// return to Windows like this
    return(msg.wParam);} // end WinMain