<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-348  評論-598  文章-0  trackbacks-0

    快樂蝦

    http://blog.csdn.net/lights_joy/

    lights@hb165.com

     

    本文適用于

    SDL-1.2.13

    vs2008

    Windows XP

     

    歡迎轉載,但請保留作者信息


    SDL的設計并沒有考慮到要和MFC相結合,但是既然它要在windows的系統上運行,必然需要使用Windows提供的API。為了在MFC SDI中使用SDL,首先想到的就是替換SDL創建的窗口,改為使用MFC提供的窗口。

    想想在Windows下要創建窗口需要使用的API必然是CreateWindow,在SDL代碼中搜,很容易發現了這樣一段代碼:

    int DIB_CreateWindow(_THIS)

    {

         char *windowid = SDL_getenv("SDL_WINDOWID");

     

         SDL_RegisterApp(NULL, 0, 0);

     

         SDL_windowid = (windowid != NULL);

         if ( SDL_windowid ) {

    #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)

             /* wince 2.1 does not have strtol */

             wchar_t *windowid_t = SDL_malloc((SDL_strlen(windowid) + 1) * sizeof(wchar_t));

             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, windowid, -1, windowid_t, SDL_strlen(windowid) + 1);

             SDL_Window = (HWND)wcstol(windowid_t, NULL, 0);

             SDL_free(windowid_t);

    #else

             SDL_Window = (HWND)SDL_strtoull(windowid, NULL, 0);

    #endif

             if ( SDL_Window == NULL ) {

                  SDL_SetError("Couldn't get user specified window");

                  return(-1);

             }

     

             /* DJM: we want all event's for the user specified

                  window to be handled by SDL.

              */

             userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC);

             SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage);

         } else {

             SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,

                            (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),

                            CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL);

             if ( SDL_Window == NULL ) {

                  SDL_SetError("Couldn't create window");

                  return(-1);

             }

             ShowWindow(SDL_Window, SW_HIDE);

         }

     

         /* JC 14 Mar 2006

             Flush the message loop or this can cause big problems later

             Especially if the user decides to use dialog boxes or assert()!

         */

         WIN_FlushMessageQueue();

     

         return(0);

    }

    注意到前面的if條件判斷使用了SDL_windowid,如果這個變量不為0,那么SDL是不會創建新窗口的!而這個值直接來自于SDL_WINDOWID這個環境變量!以此推斷,只要在調用SDL_Init之前設置好SDL_WINDOWID這個環境變量,那么SDL將可以使用我們提供的窗口。

    下面修改SDL提供的testwin示例,使之在MFC SDI環境下運行。

    1.1    工程創建
    直接使用VS2008的向導生成一個叫sdi_sdl的MFC工程,選擇SDI類型。

    1.2    拋棄SDLmain.lib
    在SDL提供的測試用例中,都要使用SDLmain.lib,這個lib文件實現了Winmain和main這兩個入口函數,在這兩個函數中進行了一些SDL的初始化工作。而在MFC下,我們不需要自己寫WinMain,因此直接拋棄SDLmain.lib,將相關的代碼轉移到Csdi_sdlView的OnCreate函數中。之所以選擇Csdi_sdlView::OnCreate是因為此時窗口已經創建,可以取到這個窗口的Handle,從而可以在SDL初始化之前設置好Window id。

    int Csdi_sdlView::OnCreate(LPCREATESTRUCT lpCreateStruct)

    {

         if (CView::OnCreate(lpCreateStruct) == -1)

             return -1;

     

        char variable[256];

         sprintf(variable, "SDL_WINDOWID=0x%lx", this->GetSafeHwnd());

        SDL_putenv(variable);

         SDL_WinMain(AfxGetApp()->m_hInstance, NULL, AfxGetApp()->m_lpCmdLine, SW_MAXIMIZE);

         return 0;

    }

    1.3    SDL_WinMain
    這個函數來源于SDLmain中的WinMain函數,只是刪除了一些不必要的代碼:

    /* This is where execution begins [windowed apps] */

    int Csdi_sdlView::SDL_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)

    {

         HINSTANCE handle;

         char **argv;

         int argc;

         char *cmdline;

         char *bufp;

         size_t nLen;

     

         /* Start up DDHELP.EXE before opening any files, so DDHELP doesn't

            keep them open.  This is a hack.. hopefully it will be fixed

            someday.  DDHELP.EXE starts up the first time DDRAW.DLL is loaded.

          */

         handle = LoadLibrary(TEXT("DDRAW.DLL"));

         if ( handle != NULL ) {

             FreeLibrary(handle);

         }

     

         /* Grab the command line */

         bufp = GetCommandLine();

         nLen = SDL_strlen(bufp)+1;

         cmdline = SDL_stack_alloc(char, nLen);

         SDL_strlcpy(cmdline, bufp, nLen);

     

         /* Parse it into argv and argc */

         argc = ParseCommandLine(cmdline, NULL);

         argv = SDL_stack_alloc(char*, argc+1);

         ParseCommandLine(cmdline, argv);

     

         /* Run the main program (after a little SDL initialization) */

         SDL_PreMain(argc, argv);

     

         /* Hush little compiler, don't you cry... */

         return 0;

    }

    1.4    SDL_PreMain
    這個函數來源于sdlmain.lib中的main函數:

    /* This is where execution begins [console apps] */

    int Csdi_sdlView::SDL_PreMain(int argc, char *argv[])

    {

         size_t n;

         char *bufp, *appname;

         int status;

     

         /* Get the class name from argv[0] */

         appname = argv[0];

         if ( (bufp=SDL_strrchr(argv[0], '\\')) != NULL ) {

             appname = bufp+1;

         } else

         if ( (bufp=SDL_strrchr(argv[0], '/')) != NULL ) {

             appname = bufp+1;

         }

     

         if ( (bufp=SDL_strrchr(appname, '.')) == NULL )

             n = SDL_strlen(appname);

         else

             n = (bufp-appname);

     

         bufp = SDL_stack_alloc(char, n+1);

         SDL_strlcpy(bufp, appname, n+1);

         appname = bufp;

     

         ///* Load SDL dynamic link library */

         //if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {

         //   ShowError("WinMain() error", SDL_GetError());

         //   return(FALSE);

         //}

     

         /* Sam:

            We still need to pass in the application handle so that

            DirectInput will initialize properly when SDL_RegisterApp()

            is called later in the video initialization.

          */

         SDL_SetModuleHandle(GetModuleHandle(NULL));

     

         /* Run the application main() code */

         status = SDL_main(argc, argv);

     

         /* Hush little compiler, don't you cry... */

         return 0;

    }

    1.5    SDL_main
    這個函數來自于testwin示例中的main函數,只是在末尾刪除了SDL_Quit這樣的退出語句。

    int Csdi_sdlView::SDL_main(int argc, char *argv[])

    {

         SDL_Surface *screen;

     

         /* Options */

         int speedy, flip, nofade;

         int delay;

         int w, h;

         int desired_bpp;

         Uint32 video_flags;

     

         /* Set default options and check command-line */

         speedy = 0;

         flip = 0;

         nofade = 0;

         delay = 1;

     

         RECT rc;

         this->GetWindowRect(&rc);

         w = rc.right;

         h = rc.bottom;

         desired_bpp = 0;

         video_flags = 0;

         if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0 ) {

             ShowError("Couldn't initialize SDL", SDL_GetError());

             return(1);

         }

     

         /* Initialize the display */

         screen = SDL_SetVideoMode(w, h, desired_bpp, video_flags);

         if ( screen == NULL ) {

             ShowError("Couldn't set %dx%dx%d video mode: %s\n", "");

             return (1);

         }

     

         DrawPict(screen, argv[1], speedy, flip, nofade);

    //   SDL_Delay(delay*1000);

    //   SDL_Quit();

         return(0);

    }

    至此,這個程序就可以正常運行了,但是它的大小還不能隨主窗口的變化而變化。為此還需要響應WM_SIZE:

    void Csdi_sdlView::OnSize(UINT nType, int cx, int cy)

    {

         SDL_Surface *screen;

         screen = SDL_SetVideoMode(cx, cy, 0, 0);

         DrawPict(screen, NULL, 0, 0, 0);

    }

    1.6    SDL_Quit
    在程序退出的時候,需要調用SDL_Quit進行一些清理的工作,原來想將這個工作放在Cview::OnDestroy中完成,但是發現這樣有很多的內存泄漏。最后將其放在Csdi_sdlApp:ExitInstance中完成:

    BOOL Csdi_sdlApp::ExitInstance()

    {

         SDL_Quit();

         return TRUE;

    }

    即便是這樣,仍然有一處內存泄漏,原因不明:

    Detected memory leaks!

    Dumping objects ->

    {98} normal block at 0x003D37C0, 21 bytes long.

     Data: <0x40784 OWID 0x4> 30 78 34 30 37 38 34 00 4F 57 49 44 00 30 78 34

    Object dump complete.

     

    本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lights_joy/archive/2009/04/04/4049123.aspx



    ---------------------------------------------------------
    專注移動開發

    Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
    posted on 2010-03-27 15:26 TiGERTiAN 閱讀(1272) 評論(0)  編輯  收藏 所屬分類: Other technique
    主站蜘蛛池模板: 美腿丝袜亚洲综合| 亚洲乱码一二三四五六区| 黄色一级免费网站| 国产成人精品免费视频软件| 亚洲人成在久久综合网站| 日韩免费精品视频| 免费乱码中文字幕网站| 男男gay做爽爽免费视频| 免费中文字幕不卡视频| 国产精品无码免费专区午夜| 久久久久久99av无码免费网站| 亚洲人成激情在线播放| 免费人成视频在线| 鲁死你资源站亚洲av| 免费永久在线观看黄网站| 国产精品福利片免费看| 亚洲不卡中文字幕无码| 亚洲视频免费播放| 亚洲人成人伊人成综合网无码| 国产精品视频免费一区二区三区| 搜日本一区二区三区免费高清视频| 亚洲综合伊人久久大杳蕉| 久久午夜羞羞影院免费观看| 亚洲国产视频一区| 亚洲JIZZJIZZ中国少妇中文| a级毛片毛片免费观看久潮| 亚洲制服丝袜精品久久| 免费国产成人午夜私人影视| 男女一进一出抽搐免费视频| 久久久久久亚洲精品成人| 午夜免费不卡毛片完整版| 一级毛片a免费播放王色| 中文字幕亚洲综合久久| 四虎影库久免费视频| 国产成人免费视频| 噜噜综合亚洲AV中文无码| 午夜亚洲www湿好大| 国产美女无遮挡免费网站| 精品四虎免费观看国产高清午夜 | 毛色毛片免费观看| 亚洲天堂免费在线视频|