首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >设置窗口像素的正确(且无闪烁)方式?

设置窗口像素的正确(且无闪烁)方式?
EN

Stack Overflow用户
提问于 2018-06-02 18:46:21
回答 2查看 228关注 0票数 3

我正在努力找出在WM_PAINT期间将一组普通的RGBA值转储到Win32窗口的工作区的正确方法。我有以下代码,但它看起来很复杂,甚至还没有完成:

代码语言:javascript
运行
复制
case WM_ERASEBKGND:
  return 1;
case WM_PAINT:
{
  PAINTSTRUCT paintInfo{};
  HDC device = BeginPaint(window, &paintInfo);
  if (device == nullptr)
    throw runtime_error(RG_LOCATION());
  ScopeExit endPaint([&] { EndPaint(window, &paintInfo); });

  HDC offscreenDevice = CreateCompatibleDC(device);
  ScopeExit deleteOffscreenDevice([&] { DeleteDC(offscreenDevice); });
  HBITMAP offscreenBitmap = CreateCompatibleBitmap(device, Distance(paintInfo.rcPaint.left, paintInfo.rcPaint.right),
                                                   Distance(paintInfo.rcPaint.top, paintInfo.rcPaint.bottom));
  ScopeExit deleteOffscreenBitmap([&] { DeleteObject(offscreenBitmap); });
  HBITMAP previousBitmap = reinterpret_cast<HBITMAP>(SelectObject(offscreenDevice, offscreenBitmap));

  // now I need to blit the available pixel data...
  vector<array<uint8_t, 4>> mypixels;
  // ...onto the client area of the window.

  // What do I do next?
  // CreateDIBSection ?
  // BitBlt ?

  return 0;
}

我有一些关于源“图像”内存格式的回旋余地,所以我可以让它匹配目标所需的任何内容。

我这样做正确吗?有没有更好的方法?

附言:很明显,每次出现WM_PAINT时,我都会存储而不是重新创建大多数对象。这只是一个示例/WIP。

编辑:添加了对WM_ERASEBKGND的处理。

编辑2:好的,看起来我需要更具体一些。我不是在寻找我发布的代码的实际问题。这只是我到目前为止在工作流方面的一个例子。这意味着我有一个窗口HDC,一个屏幕外HDC,一个屏幕外HBITMAP和一个指向我的像素的指针,假设是在一个假设的R8G8B8A8内存布局中。我该如何处理这些对象?我是否要通过CreateDIBSection创建另一个HBITMAP并将我的像素写入其中?之后我该怎么处理它?

编辑3:请参阅Barmak Shemirani的答案以获得适当的解决方案(我的示例代码有问题)。也可以看看保罗·桑德斯的回答,了解一些现代的WinAPI技巧。

谢谢大家!

EN

Stack Overflow用户

回答已采纳

发布于 2018-06-03 02:01:04

要打印mypixels矢量,请使用SetDIBitsToDevice绘制到设备上下文。或者使用SetDIBits创建一个新的HBITMAP对象。

为简单起见,此示例直接绘制到HDC中。但是您可以使用CreateCompatibleDC进行缓冲,或者使用另一个答案中所示的buffer方法。

代码语言:javascript
运行
复制
case WM_PAINT:
{
    //int w = width of source bitmap
    //int h = height of source bitmap
    //optional: make sure width and height are correct
    assert(mypixels.size() == w * h);

    PAINTSTRUCT ps;
    auto hdc = BeginPaint(hwnd, &ps);

    BITMAPINFOHEADER bi{ sizeof(bi) };
    bi.biWidth = w;
    bi.biHeight = h;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;

    SetDIBitsToDevice(hdc, 0, 0, w, h, 0, 0, 0, h, &mypixels[0],
        (BITMAPINFO*)&bi, DIB_RGB_COLORS);

    EndPaint(hwnd, &ps);

    return 0;
}

使用内存dc:

代码语言:javascript
运行
复制
case WM_PAINT:
{
    RECT rc;
    GetClientRect(hwnd, &rc);
    int canvas_width = rc.right;
    int canvas_height = rc.bottom;

    PAINTSTRUCT ps;
    auto hdc = BeginPaint(hwnd, &ps);

    //create memory dc:
    auto memdc = CreateCompatibleDC(hdc);
    auto hbmp = CreateCompatibleBitmap(hdc, canvas_width, canvas_height);
    auto oldbmp = SelectObject(memdc, hbmp); //<- memdc is ready

    //draw on memory dc:
    BITMAPINFOHEADER bi{ sizeof(bi), w, h, 1, 32, BI_RGB };
    SetDIBitsToDevice(memdc, 0, 0, w, h, 0, 0, 0, h, mypixels.data(),
        (BITMAPINFO*)&bi, DIB_RGB_COLORS);

    //draw on actual dc:
    BitBlt(hdc, 0, 0, canvas_width, canvas_height, memdc, 0, 0, SRCCOPY);

    //clean up:
    SelectObject(memdc, oldbmp);
    DeleteObject(hbmp);
    DeleteDC(memdc);
    EndPaint(hwnd, &ps);

    return 0;
}
票数 3
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50656080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档