Thread: Bouncing Ball

  1. #1
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903

    Bouncing Ball

    This is a very rough preliminary windows api program that basically just loads a ball.bmp.. and makes it bounce off the edges of the screen. It uses exerpts from the Forger's Win32 API Tutorial. I am basically trying to put all the examples together into one working program.

    Below is the source code along with compiler errors. Please help if ye' can.

    ball.cpp
    Code:
    #include <windows.h>
    using namespace std;
    
    void UpdateBall(RECT* prc);
    void DrawBall(HDC hdc, RECT* prc);
    
    
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    char szClassName[ ] = "WindowsApp";
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default color as the background of the window */
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Windows App",       /* Title Text */
               WS_OVERLAPPEDWINDOW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    
    HBITMAP g_hbmBall = NULL;
    
    const int BALL_MOVE_DELTA = 2;
    const int ID_TIMER = 1;
    
    typedef struct _BALLINFO 
    {
        int width;
        int height;
        int x;
        int y;
    
        int dx;
        int dy;
    }BALLINFO;
    
    BALLINFO g_ballInfo;
    
        BITMAP bm;
        
        GetObject(g_hbmBall, sizeof(bm), &bm);
    
        ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));
        g_ballInfo.width = bm.bmWidth;
        g_ballInfo.height = bm.bmHeight;
    
        g_ballInfo.dx = BALL_MOVE_DELTA;
        g_ballInfo.dy = BALL_MOVE_DELTA
        
        const int ID_TIMER = 1;
    
        ret = SetTimer(hwnd, ID_TIMER, 50, NULL);
        if(ret == 0)
            MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
    
    
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                 
                g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
                if(g_hbmBall == NULL)
                MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
                
                ret = SetTimer(hwnd, ID_TIMER, 50, NULL);
                if(ret == 0)
                MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
    
                break;
            
            case WM_TIMER:
                  
                RECT rcClient;
                HDC hdc = GetDC(hwnd);
    
                GetClientRect(hwnd, &rcClient);
    
                UpdateBall(&rcClient);
                DrawBall(hdc, &rcClient);
    
                ReleaseDC(hwnd, hdc);
        
                break;   
               
            case WM_DESTROY:
                 
                KillTimer(hwnd, ID_TIMER); 
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    //Function Definitions
    
    void UpdateBall(RECT* prc)
    {
        g_ballInfo.x += g_ballInfo.dx;
        g_ballInfo.y += g_ballInfo.dy;
    
        if(g_ballInfo.x < 0)
        {
            g_ballInfo.x = 0;
            g_ballInfo.dx = BALL_MOVE_DELTA;
        }
        else if(g_ballInfo.x + g_ballInfo.width > prc->right)
        {
            g_ballInfo.x = prc->right - g_ballInfo.width;
            g_ballInfo.dx = -BALL_MOVE_DELTA;
        }
    
        if(g_ballInfo.y < 0)
        {
            g_ballInfo.y = 0;
            g_ballInfo.dy = BALL_MOVE_DELTA;
        }
        else if(g_ballInfo.y + g_ballInfo.height > prc->bottom)
        {
            g_ballInfo.y = prc->bottom - g_ballInfo.height;
            g_ballInfo.dy = -BALL_MOVE_DELTA;
        }
    }
    
    void DrawBall(HDC hdc, RECT* prc)
    {
        HDC hdcBuffer = CreateCompatibleDC(hdc);
        HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);
        HBITMAP hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);
    
        HDC hdcMem = CreateCompatibleDC(hdc);
        HBITMAP hbmOld = SelectObject(hdcMem, g_hbmMask);
    
        FillRect(hdcBuffer, prc, GetStockObject(WHITE_BRUSH));
    
        BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCAND);
    
        SelectObject(hdcMem, g_hbmBall);
        BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCPAINT);
    
        BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);
    
        SelectObject(hdcMem, hbmOld);
        DeleteDC(hdcMem);
    
        SelectObject(hdcBuffer, hbmOldBuffer);
        DeleteDC(hdcBuffer);
        DeleteObject(hbmBuffer);
    }

    resource.h
    Code:
    #define IDB_BALL  101

    resource.rc
    Code:
    #include "resource.h"
    
    IDB_BALL BITMAP "ball.bmp"
    Last edited by The Brain; 12-26-2006 at 09:04 PM.
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    903
    Code:
    // ...
    
    
    HBITMAP g_hbmBall = NULL;
    
    const int BALL_MOVE_DELTA = 2;
    const int ID_TIMER = 1;
    
    typedef struct _BALLINFO 
    {
        int width;
        int height;
        int x;
        int y;
    
        int dx;
        int dy;
    }BALLINFO;
    
    BALLINFO g_ballInfo;
    
    
        BITMAP bm;
        
        GetObject(g_hbmBall, sizeof(bm), &bm);
    
        ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));
        g_ballInfo.width = bm.bmWidth;
        g_ballInfo.height = bm.bmHeight;
    
        g_ballInfo.dx = BALL_MOVE_DELTA;
        g_ballInfo.dy = BALL_MOVE_DELTA
        
        const int ID_TIMER = 1;
    
        ret = SetTimer(hwnd, ID_TIMER, 50, NULL);
        if(ret == 0)
            MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
    
    
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                 
                g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
                if(g_hbmBall == NULL)
                MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
                
                ret = SetTimer(hwnd, ID_TIMER, 50, NULL);
                if(ret == 0)
                MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
    
                break;
            
            case WM_TIMER:
                  
                RECT rcClient;
                HDC hdc = GetDC(hwnd);
    
                GetClientRect(hwnd, &rcClient);
    
                UpdateBall(&rcClient);
                DrawBall(hdc, &rcClient);
    
                ReleaseDC(hwnd, hdc);
        
                break;   
               
            case WM_DESTROY:
                 
                KillTimer(hwnd, ID_TIMER); 
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    // ...
    The red code should belong to a function, but you left it outside of a function which is illegal. The blue code should be enclosed within braces {} because you are creating variables within a case statement.

  3. #3
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903

    Arrow

    got it down to this...

    Code:
    #include <windows.h>
    using namespace std;
    
    void UpdateBall(RECT* prc);
    void DrawBall(HDC hdc, RECT* prc);
    
    
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    char szClassName[ ] = "WindowsApp";
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default color as the background of the window */
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Windows App",       /* Title Text */
               WS_OVERLAPPEDWINDOW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    
    HBITMAP g_hbmBall = NULL;
    
    const int BALL_MOVE_DELTA = 2;
    const int ID_TIMER = 1;
    
    typedef struct _BALLINFO 
    {
        int width;
        int height;
        int x;
        int y;
    
        int dx;
        int dy;
    }BALLINFO;
    
    BALLINFO g_ballInfo;
    
    
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
            {     
                g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
                if(g_hbmBall == NULL)
                MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
                
                BITMAP bm;
        
                GetObject(g_hbmBall, sizeof(bm), &bm);
    
                ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));
                g_ballInfo.width = bm.bmWidth;
                g_ballInfo.height = bm.bmHeight;
    
                g_ballInfo.dx = BALL_MOVE_DELTA;
                g_ballInfo.dy = BALL_MOVE_DELTA;       
    
                int ret = SetTimer(hwnd, ID_TIMER, 50, NULL);
                if(ret == 0)
                       MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
                }
                break;
            
            case WM_TIMER:
            {    
                RECT rcClient;
                HDC hdc = GetDC(hwnd);
    
                GetClientRect(hwnd, &rcClient);
    
                UpdateBall(&rcClient);
                DrawBall(hdc, &rcClient);
    
                ReleaseDC(hwnd, hdc);
        
                break;
            }  
               
            case WM_DESTROY:
                 
                KillTimer(hwnd, ID_TIMER); 
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    //Function Definitions
    
    void UpdateBall(RECT* prc)
    {
        g_ballInfo.x += g_ballInfo.dx;
        g_ballInfo.y += g_ballInfo.dy;
    
        if(g_ballInfo.x < 0)
        {
            g_ballInfo.x = 0;
            g_ballInfo.dx = BALL_MOVE_DELTA;
        }
        else if(g_ballInfo.x + g_ballInfo.width > prc->right)
        {
            g_ballInfo.x = prc->right - g_ballInfo.width;
            g_ballInfo.dx = -BALL_MOVE_DELTA;
        }
    
        if(g_ballInfo.y < 0)
        {
            g_ballInfo.y = 0;
            g_ballInfo.dy = BALL_MOVE_DELTA;
        }
        else if(g_ballInfo.y + g_ballInfo.height > prc->bottom)
        {
            g_ballInfo.y = prc->bottom - g_ballInfo.height;
            g_ballInfo.dy = -BALL_MOVE_DELTA;
        }
    }
    
    void DrawBall(HDC hdc, RECT* prc)
    {
        HDC hdcBuffer = CreateCompatibleDC(hdc);
        HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);
        HBITMAP hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);
    
        HDC hdcMem = CreateCompatibleDC(hdc);
        HBITMAP hbmOld = SelectObject(hdcMem, g_hbmMask);
    
        FillRect(hdcBuffer, prc, GetStockObject(WHITE_BRUSH));
    
        BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCAND);
    
        SelectObject(hdcMem, g_hbmBall);
        BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCPAINT);
    
        BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);
    
        SelectObject(hdcMem, hbmOld);
        DeleteDC(hdcMem);
    
        SelectObject(hdcBuffer, hbmOldBuffer);
        DeleteDC(hdcBuffer);
        DeleteObject(hbmBuffer);
    }
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  4. #4
    Registered User Bajanine's Avatar
    Join Date
    Dec 2001
    Location
    The most peaks over 10,000 feet!
    Posts
    396
    edit/
    Where do you include your resource file?
    Last edited by Bajanine; 12-26-2006 at 11:31 PM.
    Favorite Quote:

    >For that reason someone invented C++.
    BLASPHEMY! Begone from my C board, you foul lover of objects, before the gods of C cast you into the void as punishment for your weakness! There is no penance for saying such things in my presence. You are henceforth excommunicated. Never return to this house, filthy heretic!



  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    903
    Code:
        HBITMAP hbmOldBuffer = (HBITMAP) SelectObject(hdcBuffer, hbmBuffer);
    
        HDC hdcMem = CreateCompatibleDC(hdc);
        HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, g_hbmMask);
    
        FillRect(hdcBuffer, prc, (HBRUSH) GetStockObject(WHITE_BRUSH));
    You forgot to cast. Also, I forgot to say it in my first post, but as Bajanine pointed out, you need to include resource.h in ball.cpp.

    Edit: Oh, and as the error says, g_hbmMask is undeclared. You either forgot to declare it(by copy-pasting parts of the code from the tutorial) or mistyped it. By the way, this code is only really useful if your compiler doesn't provide an implementation for TransparentBlt() which is common I think.
    Last edited by Desolation; 12-26-2006 at 11:39 PM.

  6. #6
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903

    Arrow

    I just want to say thanks to everyone who has helped so far... got it down to a good compiling source code.. however, I still just have one single error... IDB_BALL failed to load.

    I have ball.bmp located in the dev.cpp folder which is just a crude MS Paint drawing of a ball.

    Here is the source code thus far:

    ball.cpp
    Code:
    #include <windows.h>
    #include "resource.h"
    using namespace std;
    
    void UpdateBall(RECT* prc);
    void DrawBall(HDC hdc, RECT* prc);
    
    
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    char szClassName[ ] = "WindowsApp";
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default color as the background of the window */
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Windows App",       /* Title Text */
               WS_OVERLAPPEDWINDOW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    
    HBITMAP g_hbmBall = NULL;
    HBITMAP g_hbmMask = NULL;
    
    const int BALL_MOVE_DELTA = 2;
    const int ID_TIMER = 1;
    
    typedef struct _BALLINFO 
    {
        int width;
        int height;
        int x;
        int y;
    
        int dx;
        int dy;
    }BALLINFO;
    
    BALLINFO g_ballInfo;
    
    
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
            {     
                g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
                if(g_hbmBall == NULL)
                MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
                
                BITMAP bm;
        
                GetObject(g_hbmBall, sizeof(bm), &bm);
    
                ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));
                g_ballInfo.width = bm.bmWidth;
                g_ballInfo.height = bm.bmHeight;
    
                g_ballInfo.dx = BALL_MOVE_DELTA;
                g_ballInfo.dy = BALL_MOVE_DELTA;       
    
                int ret = SetTimer(hwnd, ID_TIMER, 50, NULL);
                if(ret == 0)
                       MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
                }
                break;
            
            case WM_TIMER:
            {    
                RECT rcClient;
                HDC hdc = GetDC(hwnd);
    
                GetClientRect(hwnd, &rcClient);
    
                UpdateBall(&rcClient);
                DrawBall(hdc, &rcClient);
    
                ReleaseDC(hwnd, hdc);
        
                break;
            }  
               
            case WM_DESTROY:
                 
                KillTimer(hwnd, ID_TIMER); 
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    //Function Definitions
    
    void UpdateBall(RECT* prc)
    {
        g_ballInfo.x += g_ballInfo.dx;
        g_ballInfo.y += g_ballInfo.dy;
    
        if(g_ballInfo.x < 0)
        {
            g_ballInfo.x = 0;
            g_ballInfo.dx = BALL_MOVE_DELTA;
        }
        else if(g_ballInfo.x + g_ballInfo.width > prc->right)
        {
            g_ballInfo.x = prc->right - g_ballInfo.width;
            g_ballInfo.dx = -BALL_MOVE_DELTA;
        }
    
        if(g_ballInfo.y < 0)
        {
            g_ballInfo.y = 0;
            g_ballInfo.dy = BALL_MOVE_DELTA;
        }
        else if(g_ballInfo.y + g_ballInfo.height > prc->bottom)
        {
            g_ballInfo.y = prc->bottom - g_ballInfo.height;
            g_ballInfo.dy = -BALL_MOVE_DELTA;
        }
    }
    
    void DrawBall(HDC hdc, RECT* prc)
    {
        HDC hdcBuffer = CreateCompatibleDC(hdc);
        HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);
        HBITMAP hbmOldBuffer = (HBITMAP)SelectObject(hdcBuffer, hbmBuffer);
    
        HDC hdcMem = CreateCompatibleDC(hdc);
        HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmMask);
    
        FillRect(hdcBuffer, prc, (HBRUSH)GetStockObject(WHITE_BRUSH));
    
        BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCAND);
    
        SelectObject(hdcMem, g_hbmBall);
        BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCPAINT);
    
        BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);
    
        SelectObject(hdcMem, hbmOld);
        DeleteDC(hdcMem);
    
        SelectObject(hdcBuffer, hbmOldBuffer);
        DeleteDC(hdcBuffer);
        DeleteObject(hbmBuffer);
    }
    resource.h
    Code:
    #define IDB_BALL  101
    resource.cpp
    Code:
    #include "resource.h"
    
    IDB_BALL BITMAP "ball.bmp"      //<- is 'BITMAP' the right script here?  or 'BMP' ?
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  7. #7
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    Erm... you don't need a "resource.cpp". What you've written in there should be in resource.rc, which is the resource script. This is handled by the resource compiler instead of the normal compiler, it would get the bitmap from your drive and stuff it into a resource section ready for linking with the rest of your code.

    What's in resource.rc?

  8. #8
    Registered User
    Join Date
    May 2006
    Posts
    903
    Try using LoadImage() instead. That's what I always do.

    http://msdn.microsoft.com/library/de.../LoadImage.asp

    LoadImage(NULL, MAKEINTRESOURCE(IDB_BALL), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);

    Don't forget to cast it to an HBITMAP.

    Edit: @SMurf: The Brain doesn't have resource.cpp file, he only has a .rc and a .h which is the way to go with Dev-C++.

    @The Brain: Just don't forget to include it in your ball.cpp.

  9. #9
    VA National Guard The Brain's Avatar
    Join Date
    May 2004
    Location
    Manassas, VA USA
    Posts
    903
    I made sure I included resource.h
    Code:
    #include <windows.h>
    #include "resource.h"
    
    using namespace std;
    
    void UpdateBall(RECT* prc);
    void DrawBall(HDC hdc, RECT* prc);
    and here I am using LoadImage( )
    Code:
    case WM_CREATE:
            {     
                //g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
                g_hbmBall = (HBITMAP)LoadImage(NULL, MAKEINTRESOURCE(IDB_BALL), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
                if(g_hbmBall == NULL)
                MessageBox(hwnd, "Could not load IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
    but I still get the same, "Could not load IDB_BALL!" error..

    This is handled by the resource compiler instead of the normal compiler, it would get the bitmap from your drive and stuff it into a resource section ready for linking with the rest of your code.
    Where is a good place to get a resource compiler..?
    • "Problem Solving C++, The Object of Programming" -Walter Savitch
    • "Data Structures and Other Objects using C++" -Walter Savitch
    • "Assembly Language for Intel-Based Computers" -Kip Irvine
    • "Programming Windows, 5th edition" -Charles Petzold
    • "Visual C++ MFC Programming by Example" -John E. Swanke
    • "Network Programming Windows" -Jones/Ohlund
    • "Sams Teach Yourself Game Programming in 24 Hours" -Michael Morrison
    • "Mathmatics for 3D Game Programming & Computer Graphics" -Eric Lengyel

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The platform SDK contains it. MinGW also comes with one.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered User Bajanine's Avatar
    Join Date
    Dec 2001
    Location
    The most peaks over 10,000 feet!
    Posts
    396
    What does GetLastError tell you?
    Favorite Quote:

    >For that reason someone invented C++.
    BLASPHEMY! Begone from my C board, you foul lover of objects, before the gods of C cast you into the void as punishment for your weakness! There is no penance for saying such things in my presence. You are henceforth excommunicated. Never return to this house, filthy heretic!



  12. #12
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Quote Originally Posted by The Brain
    and here I am using LoadImage( )....but I still get the same, "Could not load IDB_BALL!" error..
    Because you never read the LoadImage link Desolation helpfully provided you with:
    Quote Originally Posted by msdn, LoadImage
    hinst
    Handle to the module of either a DLL or executable (.exe) that contains the image to be loaded.
    Which is pretty much what LoadBitmap has to say, too, about its corresponding hInst parameter - refer to the line of code you commented out.
    Quote Originally Posted by The Brain
    Where is a good place to get a resource compiler..?
    You already have a resource compiler.
    Code:
    using namespace std;
    You don't need this. Even if you were using anything from the std namespace you should avoid this kind of namespace abuse in anything but the shortest and simplest of test or example code.

    Since you're coding in c++, you should probably try to get used to type-safe c++ casts, too - see the reply by CornedBee in FAQ: Difference between C and C++ style casting for a thorough description.

    Also, this masking technique is described in Petzold's Programming Windows and in two msdn articles:

    Bitmaps with Transparency
    How to Draw Transparent Bitmaps.

    Unless you're doing this to understand those techniques or for compatibility with win9x, I'd suggest using TransparentBlt instead as it's a lot simpler.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  13. #13
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    The winforge.zip tut comes with the source code in the files folder/ source where all the progs are there with a working prog.
    all the example programs are already there.
    Last edited by kryptkat; 12-29-2006 at 08:58 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to create a bouncing ball?
    By Swerve in forum C++ Programming
    Replies: 7
    Last Post: 09-12-2008, 03:41 AM
  2. The Old Bouncing Ball
    By bartybasher in forum Game Programming
    Replies: 3
    Last Post: 08-19-2003, 03:06 AM
  3. Simple bouncing ball program
    By funkydude9 in forum Game Programming
    Replies: 3
    Last Post: 08-18-2003, 10:00 PM
  4. Bouncing ball
    By SKINp in forum Game Programming
    Replies: 4
    Last Post: 01-13-2003, 02:26 PM
  5. Bouncing ball - help ??
    By Gugge in forum C Programming
    Replies: 7
    Last Post: 04-13-2002, 02:34 PM