How to make an SDL window the child of another window in Win32

亦凉 2022-04-11 07:13 202阅读 0赞















This had me beating my head against the wall for days. Now as you know, It is fairly straightforward to open an SDL surface in a window:


  1. SDL_Surface screen = SDL_SetVideoMode(width, height, 24, SDL_NOFRAME);
    if(screen == 0)
    throw AVException(SDL_GetError());

The SDL_NOFRAME option removes the window borders so the window is now ready to become a child window. Next we need to obtain the SDL window’s HWND


  1. #include <SDL_syswm.h>

    struct SDL_SysWMinfo wmInfo;
    SDL_VERSION(&wmInfo.version);

    if(-1 == SDL_GetWMInfo(&wmInfo))
    throw AVException(SDL_GetError());

    HWND hwndSDL = wmInfo.window;

Now we can parent it to our window:


  1. SetParent(hwndSDL, hwndMyWindow);

So far so good but this is where it all falls apart. When the parent window is moved, the SDL window does not move with it. You get an effect where the clipping rectangle moves but the contents of the window stay put.


This took me days to figure out. It tried messsing about with WM_MOVE handlers and using offsets on my SDL_UpdateRect() coordinates and all kinds of crazy stuff but in the end I found two important facts:



  1. The SDL window does not receive WM_MOVE noftifications from its parent

  2. Using MoveWindow to set the position of the SDL window does not work if the new coordinates are the same as the current coordinates (that was the tough one to work out)


Since I am using SDL to play video, I am constantly updating the window all the time. This means I can use a test in my update function to check if the window has moved. If so, I need to use two calls to MoveWindow to fool SDL into moving. If you are not doing animation, perhaps you could use a timer call or something to achieve the same result. Anyway, here is the code:


  1. // Dumps the given frame to the screen.
    void showFrame(SDL_Surface
    surface)
    {
    static RECT lastPos;

    // Check to see if the window has been moved.
    RECT r;
    GetWindowRect(hwndSDL, &r);

    if(r.left != lastPos.left || r.top != lastPos.top)
    {
    GetClientRect(hwndSDL, &r);
    MoveWindow(hwndSDL, r.left, r.top, r.right - r.left, r.bottom - r.top, FALSE);
    MoveWindow(hwndSDL, r.left + 4, r.top, r.right - r.left, r.bottom - r.top, FALSE);
    lastPos = r;
    }

    // Copy the off-screen surface to the screen.
    SDL_BlitSurface(surface, 0, screen, 0);
    SDL_UpdateRect(screen, 0, 0, 0, 0);
    }



No Comments »









How to make an SDL window the child of another window in Win32



Filed under: 
Nerd Notes — adam @ 12:23 pm


This had me beating my head against the wall for days. Now as you know, It is fairly straightforward to open an SDL surface in a window:


  1. SDL_Surface screen = SDL_SetVideoMode(width, height, 24, SDL_NOFRAME);
    if(screen == 0)
    throw AVException(SDL_GetError());

The SDL_NOFRAME option removes the window borders so the window is now ready to become a child window. Next we need to obtain the SDL window’s HWND


  1. #include <SDL_syswm.h>

    struct SDL_SysWMinfo wmInfo;
    SDL_VERSION(&wmInfo.version);

    if(-1 == SDL_GetWMInfo(&wmInfo))
    throw AVException(SDL_GetError());

    HWND hwndSDL = wmInfo.window;

Now we can parent it to our window:


  1. SetParent(hwndSDL, hwndMyWindow);

So far so good but this is where it all falls apart. When the parent window is moved, the SDL window does not move with it. You get an effect where the clipping rectangle moves but the contents of the window stay put.


This took me days to figure out. It tried messsing about with WM_MOVE handlers and using offsets on my SDL_UpdateRect() coordinates and all kinds of crazy stuff but in the end I found two important facts:



  1. The SDL window does not receive WM_MOVE noftifications from its parent

  2. Using MoveWindow to set the position of the SDL window does not work if the new coordinates are the same as the current coordinates (that was the tough one to work out)


Since I am using SDL to play video, I am constantly updating the window all the time. This means I can use a test in my update function to check if the window has moved. If so, I need to use two calls to MoveWindow to fool SDL into moving. If you are not doing animation, perhaps you could use a timer call or something to achieve the same result. Anyway, here is the code:


  1. // Dumps the given frame to the screen.
    void showFrame(SDL_Surface
    surface)
    {
    static RECT lastPos;

    // Check to see if the window has been moved.
    RECT r;
    GetWindowRect(hwndSDL, &r);

    if(r.left != lastPos.left || r.top != lastPos.top)
    {
    GetClientRect(hwndSDL, &r);
    MoveWindow(hwndSDL, r.left, r.top, r.right - r.left, r.bottom - r.top, FALSE);
    MoveWindow(hwndSDL, r.left + 4, r.top, r.right - r.left, r.bottom - r.top, FALSE);
    lastPos = r;
    }

    // Copy the off-screen surface to the screen.
    SDL_BlitSurface(surface, 0, screen, 0);
    SDL_UpdateRect(screen, 0, 0, 0, 0);
    }








发表评论

表情:
评论列表 (有 0 条评论,202人围观)

还没有评论,来说两句吧...

相关阅读