Which is better Double Buffering or assigning to a Static Control. I would like an example of double buffering or both.
This is my bitmap code.
#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <string.h>
#include "Menu.h"
#include "Icon.h"
LPCTSTR ClsName = L"App"; // Class name
LPCTSTR WndName = L"WindowsAPI"; // Window title
HWND hwnd; // Handle to our main window
////////////////////////////////////////////////////
LRESULT CALLBACK WndProcedure(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam);
////////////////////////////////////////////////////
INT WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG Msg; // Structure to hold messages for our WinProc
WNDCLASSEX WndClsEx; // Our WNDCLASSEX structure used to define a window
// Define our window
WndClsEx.cbSize = sizeof(WNDCLASSEX); // The size in bytes of the structure
WndClsEx.style = CS_HREDRAW | CS_VREDRAW; // Style flags: CS_HREDRAW | CS_VREDRAW redraws the window on resize
WndClsEx.lpfnWndProc = WndProcedure; // Pointer to the windows procedure
WndClsEx.cbClsExtra = 0; // Extra bytes to allocate the window class structure
WndClsEx.cbWndExtra = 0; // Extra bytes to allocate the window instance structure
WndClsEx.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_ICON); // A handle to the window class's icon
WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW); // A handle to the window class's cursor, this uses default
WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // A handle to the brush used to paint the background, we use white
WndClsEx.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN_MENU); // We use the menu we created (IDR_MAIN_MENU)
WndClsEx.lpszClassName = ClsName; // Class name
WndClsEx.hInstance = hInstance; // handle to the instance that contains the WinProc for the class
WndClsEx.hIconSm = LoadIcon(WndClsEx.hInstance, (LPCTSTR)IDI_ICON); // A handle to the window class's small icon
// If register class fails, exit with error message
if (!RegisterClassEx(&WndClsEx))
{
MessageBox(NULL,L"Call to RegisterClassEx failed!",L"Win32 Guided Tour",NULL);
return 1;
}
// Create the window
hwnd = CreateWindowEx(0,
ClsName, WndName, // Class name, Window title
WS_OVERLAPPEDWINDOW, // Window style, WS_OVERLAPPEDWINDOW allows resizing
100, 100, // x coord , y coord
600, 500, // Width, Height
NULL, // Parent (if child)
NULL, // hMenu
hInstance, // Instance
NULL); // Additional info not needed
// Actually display the window
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Decode and treat the messages
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
bool LoadAndBlitBitmap(HDC hWinDC, LPCWSTR szFileName, int x, int y)
{
// Load the bitmap image file
HBITMAP hBitmap;
hBitmap = (HBITMAP)::LoadImage(NULL, szFileName, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE);
// Verify that the image was loaded
if (hBitmap == NULL) {
::MessageBox(NULL, __T("LoadImage Failed"), __T("Error"), MB_OK);
return false;
}
// Create a device context that is compatible with the window
HDC hLocalDC;
hLocalDC = ::CreateCompatibleDC(hWinDC);
// Verify that the device context was created
if (hLocalDC == NULL) {
::MessageBox(NULL, __T("CreateCompatibleDC Failed"), __T("Error"), MB_OK);
return false;
}
// Get the bitmap's parameters and verify the get
BITMAP qBitmap;
int iReturn = GetObject(reinterpret_cast<HGDIOBJ>(hBitmap), sizeof(BITMAP),
reinterpret_cast<LPVOID>(&qBitmap));
if (!iReturn) {
::MessageBox(NULL, __T("GetObject Failed"), __T("Error"), MB_OK);
return false;
}
// Select the loaded bitmap into the device context
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hLocalDC, hBitmap);
if (hOldBmp == NULL) {
::MessageBox(NULL, __T("SelectObject Failed"), __T("Error"), MB_OK);
return false;
}
// Blit the dc which holds the bitmap onto the window's dc
BOOL qRetBlit = ::BitBlt(hWinDC, x, y, qBitmap.bmWidth, qBitmap.bmHeight,
hLocalDC, 0, 0, SRCCOPY);
if (!qRetBlit) {
::MessageBox(NULL, __T("Blit Failed"), __T("Error"), MB_OK);
return false;
}
// Unitialize and deallocate resources
::SelectObject(hLocalDC, hOldBmp);
::DeleteDC(hLocalDC);
::DeleteObject(hBitmap);
return true;
}
////////////////////////////////////////////////////
struct
{
int x, y;
} pos = {0};
LRESULT CALLBACK WndProcedure(HWND hwnd, // Handle to our main window
UINT Msg, // Our message that needs to be processed
WPARAM wParam, // Extra values of message (Mouse for example might have x and y coord values)
LPARAM lParam) // Extra values of message (Mouse for example might have x and y coord values)
{
PAINTSTRUCT ps;
HDC hdc;
switch(Msg)
{
case WM_DESTROY: // If a close message is sent to the message loop
PostQuitMessage(WM_QUIT); // Exit
break;
case WM_KEYDOWN:
{
switch (wParam) {
case VK_LEFT:
{
pos.x--;
InvalidateRect(hwnd, NULL, TRUE);
break;
}
case VK_RIGHT:
{
pos.x++;
InvalidateRect(hwnd, NULL, TRUE);
break;
}
case VK_UP:
{
pos.y--;
InvalidateRect(hwnd, NULL, TRUE);
break;
}
case VK_DOWN:
{
pos.y++;
InvalidateRect(hwnd, NULL, TRUE);
break;
}
}
break;
}
case WM_CLOSE:
if (MessageBox(hwnd, L"Really quit?", L"My application", MB_YESNO|MB_ICONQUESTION) == IDYES)
{
DestroyWindow(hwnd);
}
// Else: User canceled. Do nothing.
return 0;
break;
case WM_INITDIALOG:
return TRUE;
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
LoadAndBlitBitmap(hdc, __T("Rocket.bmp"), 0, 0);
LoadAndBlitBitmap(hdc, __T("Rocket2.bmp"), pos.x, pos.y);
HPEN hPenOld;
// Draw a red line
HPEN hLinePen;
COLORREF qLineColor;
qLineColor = RGB(255, 0, 0);
hLinePen = CreatePen(PS_SOLID, 7, qLineColor);
hPenOld = (HPEN)SelectObject(hdc, hLinePen);
MoveToEx(hdc, 500, 100, NULL);
LineTo(hdc, 100, 250);
MoveToEx(hdc, 100, 100, NULL);
LineTo(hdc, 500, 250);
SelectObject(hdc, hPenOld);
DeleteObject(hLinePen);
break;
}
// This message is sent when the user selects a command item from a menu,
// when a control sends a message to its parent window,
// or when an accelerator keystroke is translated.
case WM_COMMAND:
{
// Value of the low-order word of wParam.
// Specifies the identifier of the menu item, control, or accelerator.
switch(LOWORD(wParam))
{
case IDM_EXIT:
if (MessageBox(hwnd, L"Really quit?", L"My application", MB_YESNO|MB_ICONQUESTION) == IDYES)
{
DestroyWindow(hwnd);
}
// Else: User canceled. Do nothing.
return 0;
break;
case IDM_ABOUT:
{
::MessageBox(hwnd, _T("This is the start of a game") , _T("About"), MB_OK|MB_ICONASTERISK);
break;
}
}
}
break;
default: // Handle all other messages in a normal way
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
return 0;
}