Original Post
OK....I don't know what to do. I've searched you forums and I feel like i've done everything correctly and I just can't get it to double buffer correctly. The main concerns are WM_PAINT and WM_CREATE. For some reason, it actually paints correctly the first time when CreateWindow is run, but any repainting after results in a white screen. ANy help is appreciated Thanks in advance Code........................... [Edited by - LessBread on March 7, 2007 9:38:48 PM]
/* animation_shell.c
** -- Bare bones windows animation program.
** cs230 2/07
*/
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define SCREEN_SIZE_X 320
#define SCREEN_SIZE_Y 240
#define BOARD_SIZE_X 200
#define BOARD_SIZE_Y 220
#define BLOCK1_SIZE_X 20
#define BLOCK1_SIZE_Y 20
void draw(HWND win);
char *block1 = "block1.bmp";
char *board1 = "board1.bmp";
char *background = "background.bmp";
COORD block1Coord = {20, 20};
;
LRESULT CALLBACK WinProc(HWND win, UINT msg, WPARAM wp, LPARAM lp) {
HDC dc;
PAINTSTRUCT ps;
static HBITMAP g_hbmBackground = NULL;
static HBITMAP g_hbmBoard1 = NULL;
static HBITMAP g_hbmBlock1 = NULL;
static BITMAP bmp_Board1;
static BITMAP bmp_Background;
static BITMAP bmp_Block1;
static HDC hdcMem;
static HDC tempDC;
RECT redrawRect;
switch (msg) {
case WM_CREATE:
dc = GetDC(win);
// Create the HANDLES for all my bitmaps
g_hbmBoard1 = (HBITMAP) LoadImage(NULL, board1, IMAGE_BITMAP, BOARD_SIZE_X, BOARD_SIZE_Y, LR_VGACOLOR | LR_LOADFROMFILE | LR_LOADTRANSPARENT);
g_hbmBackground = (HBITMAP) LoadImage(NULL, background, IMAGE_BITMAP, SCREEN_SIZE_X, SCREEN_SIZE_Y, LR_LOADFROMFILE | LR_VGACOLOR );
g_hbmBlock1 = (HBITMAP) LoadImage(NULL, block1, IMAGE_BITMAP, block1Coord.X, block1Coord.Y, LR_LOADFROMFILE);
// Make sure the Handles were created
if(g_hbmBackground == NULL || g_hbmBoard1 == NULL || g_hbmBlock1 == NULL)
MessageBox(win, "Image Loaded Incorrectly", "Error", MB_OK | MB_ICONEXCLAMATION);
// Place the bitmaps into there proper place
GetObject(g_hbmBackground , sizeof(bmp_Background), &bmp_Background);
GetObject(g_hbmBlock1 , sizeof(bmp_Block1) , &bmp_Block1);
GetObject(g_hbmBoard1 , sizeof(bmp_Board1) , &bmp_Board1);
ReleaseDC(win, dc);
srand((unsigned int)time(NULL));
break;
case WM_PAINT:
{
dc = BeginPaint(win, &ps);
// Setup 2 Temp DC for writting
HDC tempDC_1 = CreateCompatibleDC(dc); // This one will hold the final screen to be BitBlt'ed
HDC tempDC_2 = CreateCompatibleDC(dc); // This one will temporarily hold the bitmaps
// These should not be monocrome bitmaps since there loaded with the same DC as the windows
HBITMAP hTempBmp1 = CreateCompatibleBitmap(dc, SCREEN_SIZE_X, SCREEN_SIZE_Y);
HBITMAP hTempBmp2 = CreateCompatibleBitmap(dc, SCREEN_SIZE_X, SCREEN_SIZE_Y);
// Load these compatible BMP's into each tempDC
HBITMAP hOldBmp1 = (HBITMAP) SelectObject(tempDC_1, hTempBmp1);
HBITMAP hOldBmp2 = (HBITMAP) SelectObject(tempDC_2, hTempBmp2);
// Color in the tempDC's before I load anything in
// I will use the Default White Brush
Rectangle(tempDC_1, 0, 0, SCREEN_SIZE_X, SCREEN_SIZE_Y);
Rectangle(tempDC_2, 0, 0, SCREEN_SIZE_X, SCREEN_SIZE_Y);
// Select a bitmap and write it to the temporary DC
SelectObject(tempDC_1, g_hbmBackground );
// Write to the Temp Screen
BitBlt(tempDC_2, 0, 0, 320, 240, tempDC_1, 0, 0, SRCCOPY);
// Do the same as above
SelectObject(tempDC_1, g_hbmBoard1);
BitBlt(tempDC_2, 0, 0, BOARD_SIZE_X, BOARD_SIZE_Y, tempDC_1, 0, 0, SRCCOPY);
//SelectObject(tempDC_1, g_hbmBlock1);
//BitBlt(tempDC_2, block1Coord.X, block1Coord.Y,
// BLOCK1_SIZE_X,
// BLOCK1_SIZE_Y,
// tempDC_1, 0, 0, SRCCOPY);
BitBlt(dc, 0, 0, 320, 240, tempDC_2, 0, 0, SRCCOPY);
// Always select the old bitmap back into the device context
SelectObject(tempDC_1, hOldBmp1);
SelectObject(tempDC_2, hOldBmp2);
DeleteObject(hTempBmp1);
DeleteObject(hTempBmp2);
DeleteDC(tempDC_1);
DeleteDC(tempDC_2);
EndPaint(win, &ps);
break;
}
case WM_CHAR:
if (wp == 0x1b)
DestroyWindow(win);
break;
case WM_KEYDOWN:
switch (wp)
{
case VK_RIGHT:
block1Coord.X += 3;
InvalidateRect(win, NULL, true);
break;
case VK_LEFT:
block1Coord.X -= 3;
InvalidateRect(win, NULL, true);
break;
case VK_UP:
block1Coord.Y -= 3;
InvalidateRect(win, NULL, true);
break;
case VK_DOWN:
block1Coord.Y += 3;
InvalidateRect(win, NULL, true);
break;
default:
break;
}
case WM_DESTROY:
DeleteObject(g_hbmBackground);
DeleteObject(g_hbmBoard1);
DeleteObject(g_hbmBlock1);
PostQuitMessage(0);
break;
default:
return DefWindowProc(win,msg,wp,lp);
}
return 0;
}
int WINAPI WinMain(HINSTANCE instance, HINSTANCE ignore,
LPSTR command_line, int show) {
char *window_title = "Tetris Initial Development",
*class_name = "Tetris";
WNDCLASS wc;
HWND win;
MSG msg;
wc.style = 0;//CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instance;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = class_name;
RegisterClass(&wc);
win = CreateWindow(class_name,window_title,
WS_VISIBLE | WS_CAPTION | WS_SYSMENU ,0 ,0,
320, 240,NULL,NULL,instance,NULL);
ShowWindow(win,show);
// Animation Styple "greedy" event loop
while (IsWindow(win)) {
if (PeekMessage(&msg,win,0,0,PM_REMOVE)) {
//^^^^^^^^^^^ Non-Blocking - looks at event queue, returns nonzero
// if there is no message; zero otherwise
// Note: it is possible to look for a specific message
// or messages; however,
//
TranslateMessage(&msg);
DispatchMessage(&msg); }
//else
// draw stuff if there is no messages on the queue:
//draw(win);
// give some cycles back to the CPU
//Sleep(10);
}
UnregisterClass(class_name,instance);
return msg.wParam;
}