Thread: Animation Error

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    12

    Question Animation Error

    Hi, i am learning to program in C using various tutorials

    Now i have completed an Animation tutorial, but when it runs, nothing happens, but there is no errors

    Can someone point out why?
    Thanks

    Code:
    #include "stdafx.h"
    #include "Week 7 GDI.h"
    
    #define MAX_LOADSTRING 100
    
    // Global Variables:
    HINSTANCE hInst;								// current instance
    TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
    TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
    
    // More global stuff
    UINT ID_TIMER = 1;
    UINT TIMER_DELAY = 30;
    const int BALL_MOVE_DELTA = 2;
    
    typedef struct _BALLINFO
    {
    	int width;
    	int height;
    	int x;
    	int y;
    
    	int dx;
    	int dy;
    }BALLINFO;
    
    BALLINFO g_ballInfo;
    HGDIOBJ g_hbmBall = NULL;
    HGDIOBJ g_hbmMask = NULL;
    
    
    // Forward declarations of functions included in this code module:
    ATOM				MyRegisterClass(HINSTANCE hInstance);
    BOOL				InitInstance(HINSTANCE, int);
    LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
    	UNREFERENCED_PARAMETER(hPrevInstance);
    	UNREFERENCED_PARAMETER(lpCmdLine);
    
     	// TODO: Place code here.
    	MSG msg;
    	HACCEL hAccelTable;
    
    	// Initialize global strings
    	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    	LoadString(hInstance, IDC_WEEK7GDI, szWindowClass, MAX_LOADSTRING);
    	MyRegisterClass(hInstance);
    
    	// Perform application initialization:
    	if (!InitInstance (hInstance, nCmdShow))
    	{
    		return FALSE;
    	}
    
    	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WEEK7GDI));
    
    	// Main message loop:
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    
    	return (int) msg.wParam;
    }
    
    
    
    //
    //  FUNCTION: MyRegisterClass()
    //
    //  PURPOSE: Registers the window class.
    //
    //  COMMENTS:
    //
    //    This function and its usage are only necessary if you want this code
    //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
    //    function that was added to Windows 95. It is important to call this function
    //    so that the application will get 'well formed' small icons associated
    //    with it.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    	WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX);
    
    	wcex.style			= CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc	= WndProc;
    	wcex.cbClsExtra		= 0;
    	wcex.cbWndExtra		= 0;
    	wcex.hInstance		= hInstance;
    	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WEEK7GDI));
    	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
    	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WEEK7GDI);
    	wcex.lpszClassName	= szWindowClass;
    	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    	return RegisterClassEx(&wcex);
    }
    
    //
    //   FUNCTION: InitInstance(HINSTANCE, int)
    //
    //   PURPOSE: Saves instance handle and creates main window
    //
    //   COMMENTS:
    //
    //        In this function, we save the instance handle in a global variable and
    //        create and display the main program window.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       HWND hWnd;
    
       hInst = hInstance; // Store instance handle in our global variable
    
       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          10, 10, 320, 240, NULL, NULL, hInstance, NULL);
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    // Function for the ball handling
    
    HGDIOBJ CreateBitmapMask(HGDIOBJ hbmColour, COLORREF crTransparent)
    {
    	HDC hdcMem, hdcMem2;
    	HGDIOBJ hbmMask;
    	BITMAP bm;
    
    	GetObject(hbmColour, sizeof(BITMAP), &bm);
    	hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
    	// create memory device
    	hdcMem = CreateCompatibleDC(0);
    	hdcMem2 = CreateCompatibleDC(0);
    
    	SelectObject(hdcMem, hbmColour);
    	SelectObject(hdcMem2, hbmMask);
    
    	SetBkColor(hdcMem, crTransparent);
    
    	BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
    	BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCINVERT);
    
    	DeleteDC(hdcMem);
    	DeleteDC(hdcMem2);
    
    	return hbmMask;
    }
    
    // draw the ball
    
    void DrawBall(HDC hdc, RECT* prc)
    {
    	HDC hdcBuffer = CreateCompatibleDC(hdc);
    	HGDIOBJ hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);
    	HGDIOBJ hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);
    
    	HDC hdcMem = CreateCompatibleDC(hdc);
    	HGDIOBJ hbmOld = SelectObject(hdcMem, g_hbmMask);
    	// clear the drawing area (fill with white)
    	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);
    }
    
    // update the ball location
    void UpdateBall(RECT* prc)
    {
    	g_ballInfo.x += g_ballInfo.dx;
    	g_ballInfo.y += g_ballInfo.dy;
    	//hit left edge?
    	if(g_ballInfo.x<0)
    	{
    		g_ballInfo.x = 0;
    		//set direction as right
    		g_ballInfo.dx = BALL_MOVE_DELTA;
    	}
    	else
    		//hit right edge?
    	if(g_ballInfo.x + g_ballInfo.width > prc->right)
    	{
    		g_ballInfo.y = 0;
    		// set ball direction as down
    		g_ballInfo.dy = BALL_MOVE_DELTA;
    	}
    	else
    		//hit bottom edge?
    	if(g_ballInfo.y + g_ballInfo.height > prc->bottom)
    	{
    		g_ballInfo.y = prc->bottom - g_ballInfo.height;
    		// set dir as up
    		g_ballInfo.dy = -BALL_MOVE_DELTA;
    	}
    }
    
    //
    //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  PURPOSE:  Processes messages for the main window.
    //
    //  WM_COMMAND	- process the application menu
    //  WM_PAINT	- Paint the main window
    //  WM_DESTROY	- post a quit message and return
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    
    	switch (message)
    	{
    	case WM_COMMAND:
    		wmId    = LOWORD(wParam);
    		wmEvent = HIWORD(wParam);
    		// Parse the menu selections:
    		switch (wmId)
    		{
    		case IDM_ABOUT:
    			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    			break;
    		case IDM_EXIT:
    			DestroyWindow(hWnd);
    			break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
    		}
    		break;
    		//initiate Ball and start Timer when window is created
    	case WM_CREATE:
    		{
    			BITMAP bm;
    			// create a GDI object from our bitmap
    			g_hbmBall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BALL));
    			if(g_hbmBall == NULL)
    				MessageBox(hWnd, "Could not load the IDB_BALL!", "Error", MB_OK | MB_ICONEXCLAMATION);
    
    			//create a mask making black transparent
    			g_hbmMask = CreateBitmapMask(g_hbmBall, RGB(0, 0, 0));
    			if(g_hbmMask == NULL)
    				MessageBox(hWnd, "Could not create mask!", "Error", MB_OK | MB_ICONEXCLAMATION);
    
    			//Create a BITMAP object [bm] from our bitmap
    			GetObject(g_hbmBall, sizeof(bm), &bm);
    			//clear BALLINFO struct
    			ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));
    			// set its parameters
    			g_ballInfo.width = bm.bmWidth;
    			g_ballInfo.height = bm.bmHeight;
    			g_ballInfo.dx = BALL_MOVE_DELTA;
    			g_ballInfo.dy = BALL_MOVE_DELTA;
    			// create a timer that have msg ID 'ID_TIMER'
    			if(SetTimer(hWnd, ID_TIMER, TIMER_DELAY, NULL) == 0)
    				MessageBox(hWnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);
    		}
    		break;
    	case WM_PAINT:
    		hdc = BeginPaint(hWnd, &ps);
    		//draw ball in window
    		RECT rcClient;
    		GetClientRect(hWnd, &rcClient);
    		DrawBall(hdc, &rcClient);
    		EndPaint(hWnd, &ps);
    		break;
    	// handle TIMER events by updating [moving] Ball then re-drawing it
    	case WM_TIMER:
    	{
    		HDC hdc = GetDC(hWnd);
    
    		RECT rcClient;
    		GetClientRect(hWnd, &rcClient);
    		UpdateBall(&rcClient);
    		DrawBall(hdc, &rcClient);
    
    		ReleaseDC(hWnd, hdc);
    	}
    	// 'tidying up' when window closed to relase GDI ojects
    	case WM_DESTROY:
    		KillTimer(hWnd, ID_TIMER);
    		DeleteObject(g_hbmBall);
    		DeleteObject(g_hbmMask);
    
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hWnd, message, wParam, lParam);
    	}
    	return 0;
    }
    
    // Message handler for about box.
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	UNREFERENCED_PARAMETER(lParam);
    	switch (message)
    	{
    	case WM_INITDIALOG:
    		return (INT_PTR)TRUE;
    
    	case WM_COMMAND:
    		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
    		{
    			EndDialog(hDlg, LOWORD(wParam));
    			return (INT_PTR)TRUE;
    		}
    		break;
    	}
    	return (INT_PTR)FALSE;
    }

  2. #2
    Or working on it anyways mramazing's Avatar
    Join Date
    Dec 2005
    Location
    Lehi, UT
    Posts
    121
    Perhaps you should put this in the Windows Programming section of the forums. Secondly what do you mean by nothing happens?
    Is the ball drawn on the screen at all?
    -- Will you show me how to c++?

  3. #3
    Registered User
    Join Date
    Jan 2010
    Posts
    412
    You're missing a break statement in the WM_TIMER case.. Instant death for the window

  4. #4
    Registered User
    Join Date
    Dec 2007
    Posts
    214
    You really should only be drawing in the WM_PAINT handler. In your timer all you need to do is update the ball position, then invalidate/update the window.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  3. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM