2010-01-27 2 views
1

Я пытаюсь использовать функцию GDI GradientFill для рисования на экране растрового изображения, а затем BitBlt на экране.GDI GradientFill не работает с растровым изображением offscreen.

Но я всегда получаю черное растровое изображение ... если я 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; 
} 

ответ

4

проблемы здесь на самом деле из-за начальное состояние контекста устройства, с которого вы создаете совместимый точечный рисунок - в этой строке:

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

hdcOffscreen должен быть hdc - это потому, что контекст устройства создан здесь:

HDC hdcOffscreen = CreateCompatibleDC(hdc); 

имеет по умолчанию в 1х1 монохромный точечный рисунок, выбранный в него - при попытке создать совместимую растровое изображение из этого, вы получите монохромного растрового изображения также. так что если вы сделаете это вместо:

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

вы должны увидеть ваш градиент :) старый вопрос, который, как представляется, дать ответ, но я думал, что идентификатор только поможет прояснить, почему именно в ее не работает!

детали/ссылки:

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

+0

Спасибо, я только что протестировал его, и он работает! – ljbade

1

Создайте 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); 
+0

Это также работает, но один HDC даже лучше. – ljbade