StretchBlt 绘制空白位图

Posted

技术标签:

【中文标题】StretchBlt 绘制空白位图【英文标题】:StretchBlt draw a blank bitmap 【发布时间】:2021-01-26 04:11:15 【问题描述】:

我使用默认的 Windows.h 函数进行绘制。我使用 StretchBlt 来绘制位图。但它(StretchBlt)绘制了一个空白位图(即,如果我不在 rop 中使用 WHITENESS,它的总黑度)。

我有一个结构来绘制组件

VM_PAINT 部分

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
SetStretchBltMode(hdc, WHITEONBLACK);
cv.DrawComponents(hdc);
EndPaint(hwnd, &ps);

在 DrawComponents() 上:

HDC hdcMem = CreateCompatibleDC(hdc);
            for (int i = 0; i < size; i++)
            
                if (spaceFlags[i]) components[i]->Draw(hdc, hdcMem, Screen_Multiplier);
            
            DeleteDC(hdcMem);

最后是组件:

class ElectriComp
    
    protected:
        unsigned short connectionNum;
        float x = 0, y = 0, cx = 0.5, cy = 0.5; 
        COORD dimentions;
        PBITMAP bitmap;

    public:
        
        unsigned int* Connections;
        ElectriComp(unsigned short connectionnum, PBITMAP b) 
            : connectionNum connectionnum 
        
            bitmap = b;
            Connections = new unsigned int[connectionNum];
        

        void SetPlace(int x, int y)
        
            this->x = x;
            this->y = y;
        

        void Draw(HDC hdc, HDC hdcMem, float ScreenMul)
        
            HGDIOBJ old = SelectObject(hdcMem, CreateBitmapIndirect(bitmap));
            StretchBlt(hdc, (x - cx) * ScreenMul, (y - cy) * ScreenMul, dimentions.X * ScreenMul, dimentions.Y * ScreenMul, hdcMem, 0, 0, bitmap->bmWidth, bitmap->bmHeight, SRCCOPY);
            SelectObject(hdcMem, old);
        
        ~ElectriComp()
        
            delete Connections;
        
    ;

Edit#1:正如所指出的,我通过 PBITMAP 而不是 HBITMAP。我通过 CreateBitmapIndirect 获得了句柄。问题依然存在,屏幕上的图像仍然是空白,而 SelectObject 没有返回 NULL。

Edit#2:将绘图循环更改为:

void DrawComponents(HDC hdc)
        
            HDC hdcMem = CreateCompatibleDC(hdc);
            COLORREF prevC = SetTextColor(hdc, RGB(255, 0, 0));
            COLORREF prevB = SetBkColor(hdc, RGB(0, 255, 0));
            for (int i = 0; i < size; i++)
            
                if (spaceFlags[i])
                
                    components[i]->Draw(hdc, hdcMem, Screen_Multiplier, benchSpace.left, benchSpace.top);
                
            
            DeleteDC(hdcMem);
        

我得到一个红色方块。所以我认为问题出在加载位图中。 这是它的轮播:

case WM_CREATE:
        GetObject(LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(ResistorBMP)), sizeof(resistorBM), &resistorBM);
        return 0;

ResistorBMP 是我资源中的位图。

【问题讨论】:

您没有显示足够的代码。您的位图是如何创建的? @JonathanPotter 我从资源中加载它。它是一个 1 位 25x25 位图。 在对单色位图进行位图传输时,您可能需要设置文本/背景颜色。见devblogs.microsoft.com/oldnewthing/20061114-01/?p=29013。 PBITMAPHBITMAP 根本不是一回事。 SelectObject 想要后者,但您正在通过前者。检查SelectObject的返回值;我预测它会失败。 【参考方案1】:

正如@IgorTandetnik 指出的那样,SelectObject 期望HBITMAP 而不是PBITMAP

此外,请确保位图是有效位图。例如,如果您使用LoadImage 加载位图,请确保返回值是有效句柄而不是NULL

以下是您可以参考的工作示例:

        HBITMAP HBitmap = (HBITMAP)LoadImage(NULL, L"test.bmp", IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);

        BITMAP bitmap;
        int iReturn = GetObject(HBitmap, sizeof(BITMAP), (LPSTR)(&bitmap));

        RECT client;
        GetClientRect(hWnd, &client);

        HGDIOBJ old = SelectObject(hdcMem, HBitmap);
        StretchBlt(hdc, 0, 0, client.right, client.bottom, hdcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);

最后,为函数调用添加错误检查将帮助您找到问题。

【讨论】:

你好,我检查了,加载位图时没有报错。 @Warmagedon007 基于您更新的代码的当前问题似乎GetObject 仅返回位图的宽度、高度和颜色格式信息,而没有位图的位值。 (BITMAP 结构的bmBits 将是NULL。)使用LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(ResistorBMP)) 替换CreateBitmapIndirect(bitmap) 将起作用。

以上是关于StretchBlt 绘制空白位图的主要内容,如果未能解决你的问题,请参考以下文章

StretchBlt 收缩损坏

如何通过 Bitmap::GetHBITMAP 将位图转换为带有 alpha 的 HBITMAP?

用OpenGL绘制位图字体,glRasterPos2i()是做啥的?

Android 在位图上绘制文本

如何从视频中捕获位图图像

vc中如何让背景图片随窗体的大小变化而改变 mfc