GDI GradientFill 不适用于屏幕外位图

发布于 2024-08-19 04:27:41 字数 2333 浏览 6 评论 0原文

我正在尝试使用 GDI GradientFill 函数在屏幕外位图上绘制,然后将其 BitBlt 到屏幕上。

但我总是得到一个黑色位图...如果我直接将 GradientFill 填充到屏幕上,它就可以工作。

下面是一个示例应用程序,您可以了解我的意思。

#pragma comment(lib, "msimg32.lib")
#include <windows.h>

const CHAR c_szWndClass[] = "GradientTestWnd";
const CHAR c_szWndTitle[] = "GradientTest";
const int c_nWndWidth = 1024;
const int c_nWndHeight = 768;

int WINAPI WinMain(      
                   HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow
                   )
{
    WNDCLASSEX wcx;
    ZeroMemory(&wcx, sizeof(wcx));
    wcx.cbSize = sizeof(wcx);
    wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcx.lpfnWndProc = DefWindowProc;
    wcx.hInstance = hInstance;
    wcx.lpszClassName = c_szWndClass;

    RegisterClassEx(&wcx);

    HWND hwndMain = CreateWindowEx(
        0,
        c_szWndClass,
        c_szWndTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        c_nWndWidth,
        c_nWndHeight,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hwndMain, SW_SHOW);

    HDC hdc;
    hdc = GetDC(hwndMain);

    HDC hdcOffscreen = CreateCompatibleDC(hdc);
    HBITMAP bitmap = CreateCompatibleBitmap(hdcOffscreen, c_nWndWidth, c_nWndHeight);
    HBITMAP old_bitmap = (HBITMAP) SelectObject(hdcOffscreen, bitmap);

    TRIVERTEX vertices[2];
    ZeroMemory(&vertices, sizeof(vertices));
    vertices[0].Red = 0xFF00;
    vertices[0].Green = 0x0000;
    vertices[0].Blue = 0x0000;
    vertices[0].x = 0;
    vertices[0].y = 0;

    vertices[1].Red = 0x0000;
    vertices[1].Green = 0x0000;
    vertices[1].Blue = 0xFF00;
    vertices[1].x = c_nWndWidth;
    vertices[1].y = c_nWndHeight;

    GRADIENT_RECT rects[1];
    ZeroMemory(&rects, sizeof(rects));
    rects[0].UpperLeft = 0;
    rects[0].LowerRight = 1;

    // This works
    //GradientFill(hdc, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V);

    // This doesn't
    GradientFill(hdcOffscreen, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V);
    BitBlt(hdc, 0, 0, c_nWndWidth, c_nWndHeight, hdcOffscreen, 0, 0, SRCCOPY);

    Sleep(5000);

    SelectObject(hdcOffscreen, old_bitmap);
    DeleteObject(bitmap);
    DeleteDC(hdcOffscreen);

    return 0;
}

I am trying to use the GDI GradientFill function to draw on a offscreen bitmap, then BitBlt that to the screen.

But I always get a black bitmap... if I GradientFill directly to the screen it works.

Below is a sample app to see what I mean.

#pragma comment(lib, "msimg32.lib")
#include <windows.h>

const CHAR c_szWndClass[] = "GradientTestWnd";
const CHAR c_szWndTitle[] = "GradientTest";
const int c_nWndWidth = 1024;
const int c_nWndHeight = 768;

int WINAPI WinMain(      
                   HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow
                   )
{
    WNDCLASSEX wcx;
    ZeroMemory(&wcx, sizeof(wcx));
    wcx.cbSize = sizeof(wcx);
    wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcx.lpfnWndProc = DefWindowProc;
    wcx.hInstance = hInstance;
    wcx.lpszClassName = c_szWndClass;

    RegisterClassEx(&wcx);

    HWND hwndMain = CreateWindowEx(
        0,
        c_szWndClass,
        c_szWndTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        c_nWndWidth,
        c_nWndHeight,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hwndMain, SW_SHOW);

    HDC hdc;
    hdc = GetDC(hwndMain);

    HDC hdcOffscreen = CreateCompatibleDC(hdc);
    HBITMAP bitmap = CreateCompatibleBitmap(hdcOffscreen, c_nWndWidth, c_nWndHeight);
    HBITMAP old_bitmap = (HBITMAP) SelectObject(hdcOffscreen, bitmap);

    TRIVERTEX vertices[2];
    ZeroMemory(&vertices, sizeof(vertices));
    vertices[0].Red = 0xFF00;
    vertices[0].Green = 0x0000;
    vertices[0].Blue = 0x0000;
    vertices[0].x = 0;
    vertices[0].y = 0;

    vertices[1].Red = 0x0000;
    vertices[1].Green = 0x0000;
    vertices[1].Blue = 0xFF00;
    vertices[1].x = c_nWndWidth;
    vertices[1].y = c_nWndHeight;

    GRADIENT_RECT rects[1];
    ZeroMemory(&rects, sizeof(rects));
    rects[0].UpperLeft = 0;
    rects[0].LowerRight = 1;

    // This works
    //GradientFill(hdc, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V);

    // This doesn't
    GradientFill(hdcOffscreen, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V);
    BitBlt(hdc, 0, 0, c_nWndWidth, c_nWndHeight, hdcOffscreen, 0, 0, SRCCOPY);

    Sleep(5000);

    SelectObject(hdcOffscreen, old_bitmap);
    DeleteObject(bitmap);
    DeleteDC(hdcOffscreen);

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

流云如水 2024-08-26 04:27:41

这里的问题实际上是由于您从中创建兼容位图的设备上下文的初始状态 - 在这一行中:

HBITMAP bitmap = CreateCompatibleBitmap(hdcOffscreen, c_nWndWidth, c_nWndHeight);

hdcOffscreen 应改为 hdc - 这是因为此处创建的设备上下文:

HDC hdcOffscreen = CreateCompatibleDC(hdc);

默认选择了一个 1x1 单色位图进入它 - 当您尝试从中创建兼容的位图时,您也会获得单色位图。所以如果你这样做:

HBITMAP bitmap = CreateCompatibleBitmap(hdc, c_nWndWidth, c_nWndHeight);

应该看到你的渐变:)老问题似乎得到了回答,但我认为id只是帮助澄清为什么它不起作用!

详细信息/链接:

http://msdn.microsoft.com /en-us/library/dd183489%28VS.85%29.aspx

当内存DC被创建时,它的
显示面正好是一个
单色像素宽和一
单色像素高

http://msdn.microsoft。 com/en-us/library/dd183488%28v=VS.85%29.aspx

创建的位图的颜色格式
通过 CreateCompatibleBitmap 函数
与设备的颜色格式匹配
由hdc参数标识

hth 标识:)

the problem here is actually due to the initial state of the device context from which you are creating the compatible bitmap - in this line:

HBITMAP bitmap = CreateCompatibleBitmap(hdcOffscreen, c_nWndWidth, c_nWndHeight);

hdcOffscreen should instead be hdc - this is because the device context created here:

HDC hdcOffscreen = CreateCompatibleDC(hdc);

has by default a 1x1 monochrome bitmap selected into it - when you attempt to create a compatible bitmap from that, you will get a monochrome bitmap also. so if you do this instead:

HBITMAP bitmap = CreateCompatibleBitmap(hdc, c_nWndWidth, c_nWndHeight);

you should see your gradient :) old question that appears to be answered but i thought id just help clarify on exactly why its not working!

details/links:

http://msdn.microsoft.com/en-us/library/dd183489%28VS.85%29.aspx

When the memory DC is created, its
display surface is exactly one
monochrome pixel wide and one
monochrome pixel high

http://msdn.microsoft.com/en-us/library/dd183488%28v=VS.85%29.aspx

The color format of the bitmap created
by the CreateCompatibleBitmap function
matches the color format of the device
identified by the hdc parameter

hth :)

耳钉梦 2024-08-26 04:27:41

创建 DIB 而不是兼容位图。

替换

HBITMAP bitmap = CreateCompatibleBitmap(hdcOffscreen, c_nWndWidth, c_nWndHeight);

BITMAPINFO BitmapInfo;
memset(&BitmapInfo, 0, sizeof(BITMAPINFOHEADER));
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = c_nWndWidth;
BitmapInfo.bmiHeader.biHeight = c_nWndHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
HBITMAP bitmap = CreateDIBSection(hdcOffscreen, &BitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);

Create a DIB instead of a compatible bitmap.

Replace

HBITMAP bitmap = CreateCompatibleBitmap(hdcOffscreen, c_nWndWidth, c_nWndHeight);

with

BITMAPINFO BitmapInfo;
memset(&BitmapInfo, 0, sizeof(BITMAPINFOHEADER));
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = c_nWndWidth;
BitmapInfo.bmiHeader.biHeight = c_nWndHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
HBITMAP bitmap = CreateDIBSection(hdcOffscreen, &BitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文