4

我正在寻找一种将字符缓冲区渲染到窗口内容区域的方法。这只是伪的,但旨在展示我真正想做的事情:

char buffer[300][200][3];    // 300px x 200px x RGB bytes
// ... render stuff into buffer
FancyWindowsFunctionToRenderBufferOnWindow(my_hwnd, buffer, 300, 200, offset_x, offset_y);

有没有办法做类似的事情?

4

2 回答 2

8

我认为您需要创建一个与设备无关的位图(DIB)。如果您已经准备好放置在应用程序窗口上的像素数组,您可能需要将整个数组复制到由 CreateDIBSection API 分配的缓冲区并调用 BitBlt 将 DIB 传输到窗口。这是我所知道的在 Win32 平台的计算机屏幕上将像素阵列显示为可见图片的唯一方法,它非常复杂且难以理解。

以下是我用来测试类似于您想要做的事情的步骤:

创建DIB:

BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = /* Width of your image buffer */
bmi.bmiHeader.biHeight = - /* Height of your image buffer */
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;

HDC hDesktopDC = GetDC(GetDesktopWindow());
HBITMAP hDib = CreateDIBSection(hDesktopDC, &bmi, DIB_RGB_COLORS, (void **)&buffer, 0, 0);
if (buffer == NULL) { /* ERROR */ }
HDC hDibDC = CreateCompatibleDC(hDesktopDC);
HGDIOBJ hOldObj = SelectObject(hDibDC, hDib);

/* Copy your array of pixels to buffer allocated above. */

ReleaseDC(GetDesktopWindow(), hDesktopDC);

实现 WM_PAINT 事件处理程序(hWnd 变量保存下面的窗口句柄):

case WM_PAINT:
    PAINTSTRUCT paint;
    HDC hWndDc = BeginPaint(hWnd, &paint);
    BitBlt(hWndDC, 0, 0, /* Width of DIB */, /* Height of DIB */,
           /* HDC of DIB (hDibDC in the above) */, 0, 0, SRCCOPY);
    EndPaint(hWnd, &paint);
    break;

我真的不指望上面的代码片段会直接帮助你。如果您确定要使用上述片段中的 GDI 函数,我建议您仔细阅读 MSDN 上的 API 文档。因为在使用 API 时正确释放或删除 DC 或 GDI 对象是非常棘手的。

于 2012-04-07T12:44:56.780 回答
5

It sounds like you have an image (raster) stored as an array of chars (which is an odd choice, since you'd usually want an array of unsigned chars for raw bitmap images).

If you meet certain alignment constraints, you can display your bitmap pretty directly with SetDIBits. You fill out a BITMAPINFO structure that describes the pixel format and image dimensions, and then you pass that along with your data to SetDIBits. It'll paint them to a DC. It can be a little tricky to get all the parameters right.

The alignment requirement is that each scanline must begin on a 4-byte boundary. If you don't meet that requirement, you'll get garbage similar to having the wrong stride. You can make a copy of the data with the correct alignment if necessary.

于 2012-04-05T22:57:59.393 回答