Thread: SDL and Windows

  1. #1
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986

    SDL and Windows

    Hey guys,

    I'm taking a break from the dark world of server programming and stepping into the public eye with a little game programming (I've noticed that most people can't appreciate any sort of server, unless they understand how much work is involved in it).

    I tried DirectDraw but the windows programming side of it got a little too much for me to handle at the moment (I've never written a proper windows app with windows), but then I found SDL. SDL seems to be really easy to use and I am loving it, and I think learning this will make it easier for me to learn OpenGL/Direct Draw later. I also picked up a copy of Charles Petzolds Programming Windows 5th edition.

    Now, enough gassbagging and onto the questions.

    Its been my experience with SDL that when I create an SDL App, it opens a new window that has all the SDL graphics in it. This is all well and fine, except I'd like to do some other things with this window. I'd like to get a handle to it, so that when I create message boxes they come up blocking that window.

    I know theres a function somewhere that I can use to get a handle for a window based on its title, but theres a chance I might not get the right one (they might have 2 instances of the program open at once for example).

    I'd also like it so that when I create other windows, like dialog boxes, to have the show up over the top of the SDL window. I figure that can also be done by getting a handle to it, but I'm not sure.

    And, is it possible to create a menu on the SDL window? I'm not sure how menus are created, but if its possible I'd like to know.

    And lastly, how can I create skinned windows like Winamp and windows media player use? I know a lot of this is beyond me right now, but I'd like to know for future reference.

    Many thanks to anyone that can help

  2. #2
    Programming is fun, mkay?
    Join Date
    Oct 2001
    Posts
    490

    Lightbulb Some solutions ...

    First, you would want to #include the <windows.h> file. Next, you will use the "FindWindow()" function like this:

    Code:
    // Get window handle, where "Window Title" is the title
    HWND hApp = FindWindow(NULL, "Window Title");
    Do that once the window is created. Now you can create a message box with this window as the parent. Just like this:

    Code:
    // Create the message box as a child of the "hApp" handle
    MessageBox(hApp, "Text", "Title", MB_OK | MB_ICONINFORMATION);
    For the menu, I don't know if you can add a menu to an SDL window. You may try to add a resource file to your project, then do this (#include "resource.h", too):

    Code:
    // Load the menu from the resource file
    HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDM_MYMENU));
    
    // Set the menu to the SDL window
    SetMenu(hApp, hMenu);
    To create a resource file, click File->New, then click the "Files" tab, and select "Resource Script", type a file name (i.e. rsrc), and click "OK". Now close the window that appears with the resource file name (ex. rsrc.rc) by clicking the "X" button (not the VC++ window itself). Click the "ResourceView" tab where your "FileView" and "ClassView" tabs are. Right-click the top item in the tree-view control, and click "Insert...", then click "Menu" and then click "New". You can expand the "Menu" tab, if it isn't already. Right-click the menu resource in the list and rename it to your own (i.e. IDM_MYMENU). You can then setup the menu, and use the last "CODE" "/CODE" section I gave you to load and display the menu.

    If this does not work, then I don't think it's possible, but it's worth a try . Glad I could help!

    Matt U.
    Website(s): http://www16.brinkster.com/trifaze/

    E-mail: [email protected]

    ---------------------------------
    C++ Environment: MSVC++ 6.0; Dev-C++ 4.0/4.1
    DirectX Version: 9.0b
    DX SDK: DirectX 8.1 SDK

  3. #3
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986

    Woohoo!

    Wow, thanks very much SyntaxBubble I was able to create the message box and the menu perfectly and very easily thanks to your help. The menu showed in the SDL window perfectly

    Now, my problem is getting notified about what they select on that menu. As far as I understand, you use the WinProc function of the SDL window to handle the messages from the menu. How can I recieve notification of messages from the menu I created, without access to the WinProc of the window?

  4. #4
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    Ok, I pieced together the following, and put it in my main game loop:
    Code:
    if (PeekMessage(&Message, SDLWindowHandle, 0, 0, PM_REMOVE))
            {
                switch (Message.message)
                {
                case WM_COMMAND:
                    MessageBox(SDLWindowHandle, "Got a message", "hello", MB_OK);
                    switch (LOWORD(Message.wParam))
                    {
                    case ID_FILE_NEWGAME:
                        MessageBox(SDLWindowHandle, "Hello", "New", MB_OK);
                        break;
                    default:
                        break;
                    }
                    
                default:
                    TranslateMessage(&Message);
                    DispatchMessage(&Message);
                }
            }
    Where Message is a MSG, SDLWindowHandle is the handle for the window created by SDL and found with FindWindow().

    ID_FILE_NEWGAME is an ID set in my menu, but I don't even get sent the WM_COMMAND message. I do, however, recieve messages, because I put a message box to come up for all messages (under my dispatchMessage call) and it said I was getting them.

    How come I get messages, but not WM_COMMAND?

  5. #5
    Programming is fun, mkay?
    Join Date
    Oct 2001
    Posts
    490

    Post Hmmmm ...

    Great! Glad I was able to help. That problem with receiving menu commands was my only concern after I posted and thought about it. I am not really sure how to do it in an SDL window. I am thinking you will have to use the Win32 API function, SetWindowLong(), to set a WinProc() for your SDL window. It shouldn't be too complicated. I can get some code if you like.
    Website(s): http://www16.brinkster.com/trifaze/

    E-mail: [email protected]

    ---------------------------------
    C++ Environment: MSVC++ 6.0; Dev-C++ 4.0/4.1
    DirectX Version: 9.0b
    DX SDK: DirectX 8.1 SDK

  6. #6
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    Thanks again SnytaxBubble I looked on MSDN for SetWindowLong which made me refer to SetWindowLongPtr.

    I'm not quite sure how this could work. I think I'll have to call GetWindowLongPtr to get the address of the SDL windows WinProc, then use SetWindowLongPtr to set my own WinProc.

    Then, for each message I get, I'll call the function I got from GetWindowLongPtr. That way the SDL window will get the messages but only after I've read them. This seems to make sense, I'll try and do it now and get back to you.

  7. #7
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    Hmm, this is what I was able to do so far:

    Code:
    // Create a pointer to store the window proc I'll get from SDL
    typedef LRESULT (CALLBACK *pfnMyWinProc)(HWND, UINT, WPARAM, LPARAM);
    pfnMyWinProc MyProc1;
    // Declare my own WindowProc
    LRESULT CALLBACK WndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
    
    // This part is called just before we get into the game loop:
    //--------------------------------------------------------------------------
    // Get the wndProc
        MyProc1 = (pfnMyWinProc)GetWindowLong(SDLWindowHandle, GWL_WNDPROC);
    
        // Set the winProc
        SetWindowLong(SDLWindowHandle, GWL_WNDPROC, WndProc);
    
    // And heres my own WndProc
    //--------------------------------------------------------------------------
    LRESULT CALLBACK WndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        // Look for a WM_COMMAND, since thats where menu commands are
        if (Message == WM_COMMAND)
            MessageBox(NULL, "Hello", "Hello", MB_OK);
        // Send it on to the old window proc
        return MyProc1(hWnd, Message, wParam, lParam);
    }
    My problem is, I'm calling:
    SetWindowLong(SDLWindowHandle, GWL_WNDPROC, WndProc);
    Which is trying to assign my WndProc as the new value, which is the way I think it should work. That doesn't compile though, the third argument is supposed to be a long.

    So, I figure I'll do this:
    SetWindowLong(SDLWindowHandle, GWL_WNDPROC, (DWORD) WndProc);
    By typecasting my wndProc to a DWORD (unsigned long). This compiles, but when run the program closes prematurely, probably because I stuffed the third parameter up.

    How can I tell it to use my WndProc function? MSDN says the third parameter should be the address of the new proc, but it wants a long If I'm supposed to convert the address of the function to a long, then I'm not sure how

  8. #8
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    MSDN says this:
    GWL_WNDPROC
    Retrieves the address of the window procedure, or a handle representing the address of the window procedure. You must use the CallWindowProc function to call the window procedure.
    So I made my WndProc look like this:
    Code:
    LRESULT CALLBACK WndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        if (Message == WM_COMMAND)
            MessageBox(NULL, "Hello", "Hello", MB_OK);
        
        return CallWindowProc(MyProc1, hWnd, Message, wParam, lParam);
    }
    That also exited prematurely. So, I did this:
    Code:
    LRESULT CALLBACK WndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        if (Message == WM_COMMAND)
            MessageBox(NULL, "Hello", "Hello", MB_OK);
        
        return 0;
    }
    And the code ran, and instead of exiting it just sat there (the WM_PAINT message never would have been processed, neither would any of the others).

    So it seems I cannot make the call to the old window proc function. Can you see why?

  9. #9
    Programming is fun, mkay?
    Join Date
    Oct 2001
    Posts
    490

    Lightbulb Try this ...

    Instead of passing the third agrument of SetWindowLong() as a DWORD, try making it (WNDPROC). That may work, but I'm not sure.
    Website(s): http://www16.brinkster.com/trifaze/

    E-mail: [email protected]

    ---------------------------------
    C++ Environment: MSVC++ 6.0; Dev-C++ 4.0/4.1
    DirectX Version: 9.0b
    DX SDK: DirectX 8.1 SDK

  10. #10
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Code:
    WNDPROC g_lpOriginalWndProc;
    
    g_lpOriginalWndProc = (WNDPROC) SetWindowLongPtr(hwndTarget, GWL_WNDPROC, (LONG_PTR) WndProc);
    Code:
    LRESULT CALLBACK WndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        if (Message == WM_COMMAND) {
            MessageBox(NULL, "Hello", "Hello", MB_OK);
            return 0;
        }
    
        return CallWindowProc(g_lpOriginalWndProc, hwnd, Message, wParam, lParam);
    }

  11. #11
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    Hm... this is strange. It seems I cannot use SetWindowLongPtr or GetWindowLongPtr, because my compiler hasn't heard of them.

    I use VC++6.0, on Windows 2000. MSDN says all I need is to #include windows.h, and link with userlib32. I get a compile error though, so I doubt the linking is the problem. Maybe my windows.h file is missing something?:S

  12. #12
    Master of the Universe! velius's Avatar
    Join Date
    Sep 2003
    Posts
    219
    I believe that was shipped with the .Net Visual Studio. You will need to update your headers.
    While you're breakin' down my back n'
    I been rackin' out my brain
    It don't matter how we make it
    'Cause it always ends the same
    You can push it for more mileage
    But your flaps r' wearin' thin
    And I could sleep on it 'til mornin'
    But this nightmare never ends
    Don't forget to call my lawyers
    With ridiculous demands
    An you can take the pity so far
    But it's more than I can stand
    'Cause this couchtrip's gettin' older
    Tell me how long has it been
    'Cause 5 years is forever
    An you haven't grown up yet
    -- You Could Be Mine - Guns N' Roses

  13. #13
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Just put these below <windows.h>:
    Code:
    #define GetWindowLongPtr GetWindowLong
    #define SetWindowLongPtr SetWindowLong

  14. #14
    Registered User
    Join Date
    Oct 2003
    Posts
    9
    Just thought I would add, if ur not interested in dealing with dx you might look at allegro. SDL from my experience with it, is really a VERY thin wrapper over dx. Allegro is a much "thicker" wrapper over it and gives u a lot of functionality. It's some what limiting, but is a great library for keeping you out of dealing with windows. Just though I would let you know about it, case u wanna take a look. Site: http://www.talula.demon.co.uk/allegro/
    -John

  15. #15
    Banned nickname_changed's Avatar
    Join Date
    Feb 2003
    Location
    Australia
    Posts
    986
    Actually, I think I might just use Direct Draw. I've used it before and gotten pretty far, but my understanding wasn't all that great. Now thanks to SDL I think I understand a lot of the concepts (blitting and surfaces) a lot more, so I will be able to use it easier. Thanks for all the help everyone

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Difficulty choosing graphics library
    By jdiperla in forum Game Programming
    Replies: 11
    Last Post: 02-27-2008, 06:35 PM
  2. DirectX or SDL?
    By Leeman_s in forum Game Programming
    Replies: 2
    Last Post: 01-19-2003, 10:13 PM
  3. Windows GDI
    By Hunter2 in forum Game Programming
    Replies: 37
    Last Post: 11-06-2002, 09:20 AM
  4. SDL project won't compile (no code yet)
    By Shadow12345 in forum Game Programming
    Replies: 7
    Last Post: 05-25-2002, 12:00 PM
  5. SDL project won't compile (no code yet)
    By Shadow12345 in forum C++ Programming
    Replies: 4
    Last Post: 05-22-2002, 01:04 PM