c++ - Win32 - 使用 GDI 对象的正确方法是什么?

标签 c++ winapi gdi

我正在 Win32 中制作一个简单的游戏。目前,我在主文件中全局声明了我的大部分绘图对象,这样我就不必删除它们或重新加载位图。所以基本上我所有的位图都加载到 WM_CREATE 中,然后不需要删除任何东西 - 有人告诉我,我可以只依靠系统在项目终止时清理我的资源。在 WM_PAINT(每秒调用 10 次左右)中,我有很多 BitBlt() 调用,以及相当多的 SelectObject() 调用。运行大约 10 - 15 分钟后,SelectObject()。什么会导致 SelectObject() 失败,我是否错误地使用了 GDI 对象?

示例:

// Top of the file
HDC hdc;
HDC hdcmem;
HDC hbcmem;
HBITMAP colorsprites, blackwhitesprites, nums;
HBITMAP hdcold, hdcbmold, hdcbm;

// Some functions to get the window ready

// More variables used for drawing:
HBITMAP bg, side, mainCont, tmpbm, tmpold, bm_left, bm_right, sidebg, win_bm;
PAINTSTRUCT ps;
RECT rc;
HDC tmphdc;
HDC tmp;
HFONT font;
HBRUSH hbr;
HPEN pen;
BITMAP structBitmapHeader;
HGDIOBJ hBitmap;
HCURSOR crosshairs = LoadCursorW(hInst, IDC_CROSS);
HCURSOR normal = LoadCursorW(hInst, IDC_ARROW);
POINT cursor;
bool addPass = false, ignorePass;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_CREATE:
            hdc = GetDC(hWnd);
            hdcmem = CreateCompatibleDC(hdc);
            GetClientRect(hWnd, &rc);
            hdcbm = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
            hbcmem = CreateCompatibleDC(hdcmem);
            hdcbmold = (HBITMAP)SelectObject(hdcmem, hdcbm);

            // Load bitmaps
            bg                  = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BACKGROUND));
            mainCont            = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_GAME_CONT));
            side                = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SIDEINFO));
            colorsprites        = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_COLOR_SPRITES));
            blackwhitesprites   = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BLACKWHITE_SPRITES));
            sidebg              = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SIDEBG));
            nums                = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NUMBERS));
            bm_left             = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_LEFT));
            bm_right            = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_RIGHT));
            win_bm              = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_VICTORY));
            if(bg == NULL || mainCont == NULL || side == NULL || colorsprites == NULL 
            || blackwhitesprites == NULL || sidebg == NULL || nums == NULL || bm_left == NULL 
            || bm_right == NULL)
                ThrowError("A bitmap failed to load.");

            break;

        case WM_PAINT:
            BeginPaint(hWnd, &ps);

            // SelectObject() and BitBlt() are called a lot in here

            EndPaint(hWnd, &ps);

            break;

        case WM_DESTROY:
            // System will clean up all GDI stuff - no need to delete anything
            PostQuitMessage(0);
            break;
    }
}

最佳答案

确保当您销毁 DC 时,您已将原始位图选回其中。当您的位图仍处于选中状态时,您永远不应销毁 DC。

关于c++ - Win32 - 使用 GDI 对象的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16931047/

相关文章:

c# - 自定义绘制下拉面板在控制范围之外

c++ - 我可以退回拷贝作为引用吗?

c++ - 在一维容器上使用 STL 算法函数

c++ opencv在窗口上显示图像

winapi - GetDeviceCaps 的 HORZSIZE

winapi - 我是否需要调用 SelectObject() 来恢复使用 GetStockObject() 检索的对象?

c++ - 无符号和有符号短整型的位宽

c++ - runtime 和 constexpr nan 比较可以不一致吗?

c - 使用 Win32 函数基于用户输入动态滚动

c++ - C++ 中不存在从 "std::wstring"到 "LPWSTR"的合适转换函数