Vitek
Vitek

Reputation: 11

GDI sprite shown some time and disappear

I'm studying sprite drawing with GDI in Visual Studio 2013 with C++. I can draw sprite using two bmp files, image with black background, and black mask. But after program start, sprite shown some time (about 15 second) and disappear. I can't find the reason. Here is my code.

#include <Windows.h>
#include "resource.h"
using namespace std;

LRESULT WINAPI WinProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
HWND hWnd = 0;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    WNDCLASS wc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_HAND));
    wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ASTERISK));
    wc.hInstance = hInst;
    wc.lpfnWndProc = WinProc;
    wc.lpszClassName = "ClassName";
    wc.lpszMenuName = 0;
    wc.style = CS_VREDRAW | CS_HREDRAW;

    if (!RegisterClass(&wc))
        MessageBox(0, "Class was not registered!", "Error", 0);

    hWnd=CreateWindow("ClassName", "WindowName", WS_OVERLAPPEDWINDOW, 100, 100, 640, 480, 0, 0, hInst, 0);
    if (hWnd==0)
        MessageBox(0, "Window was not created!", "Error", 0);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (msg.message!=WM_QUIT)
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else
    {
        HDC hdc = GetDC(hWnd);
        HDC hBuffDC = CreateCompatibleDC(hdc);
        HDC hMemDC = CreateCompatibleDC(hdc);
        HBITMAP hBuffBitmap = CreateCompatibleBitmap(hdc, 640, 480);
        HBITMAP hSpriteBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_MASK));

        SelectObject(hBuffDC, hBuffBitmap);
        SelectObject(hBuffDC, (HBRUSH)GetStockObject(GRAY_BRUSH));
        Rectangle(hBuffDC, 0, 0, 640, 480);
        SelectObject(hMemDC, hSpriteBitmap);
        BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCAND);
        hSpriteBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SPRITE));
        SelectObject(hMemDC, hSpriteBitmap);
        BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCPAINT);
        BitBlt(hdc, 0, 0, 640, 480, hBuffDC, 0, 0, SRCCOPY);

        DeleteObject(hBuffBitmap);
        DeleteObject(hSpriteBitmap);
        DeleteDC(hMemDC);
        DeleteDC(hBuffDC);
        ReleaseDC(hWnd, hdc);
    }

    return 0;
}

LRESULT WINAPI WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_ESCAPE:
            DestroyWindow(hWnd);
            break;
        }
        break;
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

images are just a black circle with white background (mask), and green circle with black background.

Upvotes: 0

Views: 370

Answers (1)

Vitek
Vitek

Reputation: 11

//Here is corrected code without memory leak and ReleaseDc return 1

#include <Windows.h>
#include "resource.h"
using namespace std;

LRESULT WINAPI WinProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
HWND hWnd = 0;
HDC hdc = 0;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    WNDCLASS wc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    wc.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_HAND));
    wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ASTERISK));
    wc.hInstance = hInst;
    wc.lpfnWndProc = WinProc;
    wc.lpszClassName = "ClassName";
    wc.lpszMenuName = 0;
    wc.style = CS_VREDRAW | CS_HREDRAW;

    if (!RegisterClass(&wc))
        MessageBox(0, "Class was not registered!", "Error", 0);

    hWnd=CreateWindow("ClassName", "WindowName", WS_OVERLAPPEDWINDOW, 100, 100, 640, 480, 0, 0, hInst, 0);
    if (hWnd==0)
        MessageBox(0, "Window was not created!", "Error", 0);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    hdc = GetDC(hWnd);

    while (msg.message!=WM_QUIT)
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else
    {
        HDC hBuffDC = CreateCompatibleDC(hdc);
        HDC hMemDC = CreateCompatibleDC(hdc);
        HBITMAP hBuffBitmap = CreateCompatibleBitmap(hdc, 640, 480);
        HBITMAP hSpriteBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SPRITE));
        HBITMAP hMaskBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_MASK));

        HBITMAP hOldBuffBitmap= (HBITMAP)SelectObject(hBuffDC, hBuffBitmap);
        HBRUSH hOldBrush= (HBRUSH)SelectObject(hBuffDC, (HBRUSH)GetStockObject(GRAY_BRUSH));
        Rectangle(hBuffDC, 0, 0, 640, 480);
        HBITMAP hOldSpriteBitmap= (HBITMAP)SelectObject(hMemDC, hMaskBitmap);
        BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCAND);
        SelectObject(hMemDC, hSpriteBitmap);
        BitBlt(hBuffDC, 0, 0, 640, 480, hMemDC, 0, 0, SRCPAINT);
        BitBlt(hdc, 0, 0, 640, 480, hBuffDC, 0, 0, SRCCOPY);
        SelectObject(hBuffDC, hOldBuffBitmap);
        SelectObject(hMemDC, hOldSpriteBitmap);
        SelectObject(hBuffDC, hOldBrush);

        DeleteObject(hBuffBitmap);
        DeleteObject(hSpriteBitmap);
        DeleteObject(hMaskBitmap);
        DeleteDC(hMemDC);
        DeleteDC(hBuffDC);
    }
    return 0;
}

LRESULT WINAPI WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_ESCAPE:
            DestroyWindow(hWnd);
            break;
        }
        return 0;
    case WM_CLOSE:
        DestroyWindow(hWnd);
        return 0;
    case WM_DESTROY:
        int Res = ReleaseDC(hWnd, hdc); //Release main window device context before destroying window
        DWORD err = GetLastError();
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Upvotes: 1

Related Questions