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

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

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

    隨筆-348  評(píng)論-598  文章-0  trackbacks-0

    快樂(lè)蝦

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

    lights@hb165.com

     

    本文適用于

    SDL-1.2.13

    vs2008

    Windows XP

     

    歡迎轉(zhuǎn)載,但請(qǐng)保留作者信息


    SDL的設(shè)計(jì)并沒(méi)有考慮到要和MFC相結(jié)合,但是既然它要在windows的系統(tǒng)上運(yùn)行,必然需要使用Windows提供的API。為了在MFC SDI中使用SDL,首先想到的就是替換SDL創(chuàng)建的窗口,改為使用MFC提供的窗口。

    想想在Windows下要?jiǎng)?chuàng)建窗口需要使用的API必然是CreateWindow,在SDL代碼中搜,很容易發(fā)現(xiàn)了這樣一段代碼:

    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,如果這個(gè)變量不為0,那么SDL是不會(huì)創(chuàng)建新窗口的!而這個(gè)值直接來(lái)自于SDL_WINDOWID這個(gè)環(huán)境變量!以此推斷,只要在調(diào)用SDL_Init之前設(shè)置好SDL_WINDOWID這個(gè)環(huán)境變量,那么SDL將可以使用我們提供的窗口。

    下面修改SDL提供的testwin示例,使之在MFC SDI環(huán)境下運(yùn)行。

    1.1    工程創(chuàng)建
    直接使用VS2008的向?qū)梢粋€(gè)叫sdi_sdl的MFC工程,選擇SDI類型。

    1.2    拋棄SDLmain.lib
    在SDL提供的測(cè)試用例中,都要使用SDLmain.lib,這個(gè)lib文件實(shí)現(xiàn)了Winmain和main這兩個(gè)入口函數(shù),在這兩個(gè)函數(shù)中進(jìn)行了一些SDL的初始化工作。而在MFC下,我們不需要自己寫WinMain,因此直接拋棄SDLmain.lib,將相關(guān)的代碼轉(zhuǎn)移到Csdi_sdlView的OnCreate函數(shù)中。之所以選擇Csdi_sdlView::OnCreate是因?yàn)榇藭r(shí)窗口已經(jīng)創(chuàng)建,可以取到這個(gè)窗口的Handle,從而可以在SDL初始化之前設(shè)置好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
    這個(gè)函數(shù)來(lái)源于SDLmain中的WinMain函數(shù),只是刪除了一些不必要的代碼:

    /* 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
    這個(gè)函數(shù)來(lái)源于sdlmain.lib中的main函數(shù):

    /* 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
    這個(gè)函數(shù)來(lái)自于testwin示例中的main函數(shù),只是在末尾刪除了SDL_Quit這樣的退出語(yǔ)句。

    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);

    }

    至此,這個(gè)程序就可以正常運(yùn)行了,但是它的大小還不能隨主窗口的變化而變化。為此還需要響應(yīng)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
    在程序退出的時(shí)候,需要調(diào)用SDL_Quit進(jìn)行一些清理的工作,原來(lái)想將這個(gè)工作放在Cview::OnDestroy中完成,但是發(fā)現(xiàn)這樣有很多的內(nèi)存泄漏。最后將其放在Csdi_sdlApp:ExitInstance中完成:

    BOOL Csdi_sdlApp::ExitInstance()

    {

         SDL_Quit();

         return TRUE;

    }

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

    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.

     

    本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/lights_joy/archive/2009/04/04/4049123.aspx



    ---------------------------------------------------------
    專注移動(dòng)開發(fā)

    Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
    posted on 2010-03-27 15:26 TiGERTiAN 閱讀(1280) 評(píng)論(0)  編輯  收藏 所屬分類: Other technique
    主站蜘蛛池模板: 4480yy私人影院亚洲| 久久亚洲精品国产精品| 一区二区免费视频| 成人免费夜片在线观看| 亚洲av乱码一区二区三区香蕉| 午夜亚洲国产成人不卡在线| 黄页网站在线看免费| 久久亚洲免费视频| 国产精品99久久免费观看| 四虎一区二区成人免费影院网址| 亚洲人成网网址在线看| 亚洲日韩区在线电影| 久久精品国产亚洲一区二区| 中文字幕亚洲不卡在线亚瑟| 波多野结衣视频在线免费观看| 日本免费电影一区| 四虎永久成人免费影院域名| 午夜私人影院免费体验区| 无限动漫网在线观看免费| 成人免费毛片内射美女APP| 中国在线观看免费国语版| 免费无码又黄又爽又刺激| 成人激情免费视频| 亚洲Aⅴ无码一区二区二三区软件| 日韩免费一级毛片| 国产亚洲无线码一区二区| 亚洲网站在线免费观看| 亚洲综合成人婷婷五月网址| 欧美日韩亚洲精品| 国精产品一区一区三区免费视频 | 久操免费在线观看| 一个人看www在线高清免费看| 国产老女人精品免费视频| 久久精品国产亚洲5555| 911精品国产亚洲日本美国韩国 | 日韩免费毛片视频| 亚洲av无码潮喷在线观看| 亚洲一区在线视频观看| 羞羞视频免费网站在线看| 91精品国产免费久久久久久青草 | 91在线视频免费观看|