【问题标题】:How to translate a simple bitmap in GDI如何在 GDI 中翻译简单的位图
【发布时间】:2016-05-09 09:34:30
【问题描述】:

我希望能够在屏幕上移动图像。这是我显示图像的代码,但它始终显示从原点开始的图像。

void drawBitmap(HDC hdc, int x1, int y1, int x2, int y2, LPWSTR path) {
    HBITMAP bmp = (HBITMAP)::LoadImage(NULL, path, IMAGE_BITMAP, SCREEN_WIDTH, SCREEN_HEIGHT, LR_LOADFROMFILE);
    HGDIOBJ B1 = CreatePatternBrush(bmp);
    SelectObject(hdc, B1);
    Rectangle(hdc, x1, y1, x2, y2);
    DeleteObject(B1);
}

感谢 Barmak Shemirani 的回答。对于任何好奇我的代码现在是什么样子的人,我已经用回答我问题的人的代码替换了原始代码,现在看起来像这样:

HBITMAP hbitmap = (HBITMAP)LoadImage(NULL, path, IMAGE_BITMAP, x2-x1, y2-y1, LR_LOADFROMFILE);
HDC memdc = CreateCompatibleDC(hdc);
SelectObject(memdc, hbitmap);
BitBlt(hdc, x1, y1, x2, y2, memdc, 0, 0, SRCCOPY);
DeleteDC(memdc);

【问题讨论】:

    标签: c++ windows bitmap gdi


    【解决方案1】:

    创建一个子窗口并覆盖WM_NCHITTEST以返回HTCAPTION,这将导致子窗口在单击时在主窗口中移动。

    接下来,在子窗口中绘制位图

    #include "windows.h"
    
    LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
    {
        if (msg == WM_DESTROY)
        {
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, msg, wp, lp);
    }
    
    LRESULT CALLBACK bitmapProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
    {
        if (msg == WM_NCHITTEST)
        {
            return HTCAPTION;
        }
    
        if (msg == WM_PAINT)
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
    
            RECT rc;
            GetClientRect(hwnd, &rc);
            HBITMAP hbitmap = (HBITMAP)LoadImage(NULL, L"c:\\test\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    
            HDC memdc = CreateCompatibleDC(hdc);
            HBITMAP saveOldBitmap = (HBITMAP)SelectObject(memdc, hbitmap);
            BitBlt(hdc, 0, 0, rc.right, rc.bottom, memdc, 0, 0, SRCCOPY);
    
            SelectObject(memdc, saveOldBitmap); //add this
            DeleteObject(hbitmap); //*** add this, important
            DeleteDC(memdc);
    
            EndPaint(hwnd, &ps);
        }
    
        return DefWindowProc(hwnd, msg, wp, lp);
    }
    
    int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
    {
        WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.hInstance = hInstance;
        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
        wcex.lpszClassName = L"mainWnd-bitmapWnd";
        wcex.lpfnWndProc = wndProc;
        if (!RegisterClassEx(&wcex))
        {
            MessageBox(0, L"error 1", 0, 0);
        }
    
        HWND hmain = CreateWindow(wcex.lpszClassName, L"w32", WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, 0, 0, hInstance, 0);
    
        wcex.lpszClassName = L"bitmapWnd";
        wcex.lpfnWndProc = bitmapProc;
        if (!RegisterClassEx(&wcex))
        {
            MessageBox(0, L"error 2", 0, 0);
        }
    
        CreateWindow(wcex.lpszClassName, L"w32", WS_VISIBLE | WS_CHILD | WS_BORDER, 0, 0, 50, 50, hmain, 0, hInstance, 0);
    
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return (int)msg.wParam;
    }
    

    更改BitBlt 中的 X/Y 位置以在不同位置打印位图

    【讨论】:

    • 我忘了加上重要的DeleteObject(hbitmap),否则会导致资源泄漏。查看更新的代码 --- 它也应该保存旧的位图,然后用SelectObject(memdc, oldbitmap)恢复它
    猜你喜欢
    • 2015-06-07
    • 1970-01-01
    • 2011-12-05
    • 2011-01-17
    • 2017-12-26
    • 2012-05-10
    • 2012-02-25
    • 2019-08-15
    • 1970-01-01
    相关资源
    最近更新 更多