如何在 GDI 中翻译简单的位图

How to translate a simple bitmap in GDI

本文关键字:简单 位图 翻译 GDI      更新时间:2023-10-16

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

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);

创建一个子窗口并覆盖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;
}

更改 X/Y 在BitBlt中的位置以在其他位置打印位图