绘制和创建内存缓冲区(Windows GDI)

时间:2014-11-26 23:55:27

标签: c++ windows graphics gdi

我正在尝试在窗口内显示用户监视器,这些监视器都缩小到最大可能的大小。目前它没有使用缓冲区,我不确定如何创建一个我需要的。

由于它动态绘制显示器,不再需要使用WM_ERASEBKGND重绘整个窗口白色,当调整大小时我想,经过大量阅读后,绘制整个虚拟桌面的缩放表示& #39;作为内存DIB是最好的方法:因此我可以填充显示器之间的空白区域,从而使它不必重绘它们。

多部分问题。是否正在建议一个可以BitBlt显示的内存规模虚拟桌面?要做到这一点,我会使用CreateDIBSection吗?

目前我的WM_PAINT看起来像这样:

    hdc = BeginPaint(hwnd, &ps);

    innerBorder = 2;
    additional = 350;
    ratio = (static_cast<double>(sA.getDesktop()->right - sA.getDesktop()->left) / (sA.getDesktop()->bottom - sA.getDesktop()->top));

    cxMax = max((innerBorder * 2), min((cA.right - border), (((cA.bottom - border - additional) * ratio))));
    cyMax = max((innerBorder * 2) , min((cA.bottom - border - additional), (((cA.right - border) / ratio))));

    cxBorder = (cA.right - cxMax) / 2;

    SelectObject(hdc, GetStockObject(DC_PEN));
    SelectObject(hdc, GetStockObject(DC_BRUSH));

    SetDCPenColor(hdc, RGB(255, 255, 255));

    //Draw Borders around virtual desktop
    Rectangle(hdc, cA.left, cA.top, cxBorder, cA.bottom);
    Rectangle(hdc, cA.right - cxBorder, cA.top, cA.right, cA.bottom);

    //Draw Borders around virtual desktop
    Rectangle(hdc, cxBorder, cA.top, cA.right - cxBorder, (border / 2));
    Rectangle(hdc, cxBorder, cyMax + (border / 2), cA.right - cxBorder, cA.bottom);

    for (i = 0; i < sA.getNumberOfMonitors(); i++)
    {
        rT = {
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.left - sA.getDesktop()->left) / (sA.getDesktop()->right - sA.getDesktop()->left)) * cxMax) + cxBorder + innerBorder,
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.top - sA.getDesktop()->top) / (sA.getDesktop()->bottom - sA.getDesktop()->top)) * cyMax) + (border / 2) + innerBorder,
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.right - sA.getDesktop()->left) / (sA.getDesktop()->right - sA.getDesktop()->left)) * cxMax) + cxBorder - innerBorder,
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.bottom - sA.getDesktop()->top) / (sA.getDesktop()->bottom - sA.getDesktop()->top)) * cyMax) + (border / 2) - innerBorder,
        };

        SetDCPenColor(hdc, RGB(255, 255, 255));

        //Draw Borders around Monitor RECT
        Rectangle(hdc, rT.left - innerBorder, rT.top, rT.left, rT.bottom);
        Rectangle(hdc, rT.right, rT.top, rT.right + innerBorder, rT.bottom);
        Rectangle(hdc, rT.left - innerBorder, rT.bottom, rT.right + innerBorder, rT.bottom + innerBorder);
        Rectangle(hdc, rT.left - innerBorder, rT.top - innerBorder, rT.right + innerBorder, rT.top);


        //Draw Monitor RECT
        SetDCPenColor(hdc, RGB(0, 0, 0));

        Rectangle(hdc, rT.left, rT.top, rT.right, rT.bottom);

        DrawText(hdc, sA.getMonitor(i)->szDevice, strlen(sA.getMonitor(i)->szDevice), &rT, DT_CENTER | DT_BOTTOM | DT_NOPREFIX | DT_SINGLELINE);
    }

    EndPaint(hwnd, &ps);

其中大部分只是计算显示器与窗口的相对大小,而且绘图很少。我确实希望它从图像加载填充和边框。我想我几乎撞到了一堵砖墙。我不知道如何继续创建内存缓冲区。

编辑:我创建内存缓冲区的许多尝试之一,这会导致单色位图。

    hdcDisplay = BeginPaint(hwnd, &ps);
    hdcBuffer = CreateCompatibleDC(hdcDisplay);

    innerBorder = 2;
    additional = 350;
    ratio = (static_cast<double>(sA.getDesktop()->right - sA.getDesktop()->left) / (sA.getDesktop()->bottom - sA.getDesktop()->top));

    cxMax = max((innerBorder * 2), min((cA.right - border), (((cA.bottom - border - additional) * ratio))));
    cyMax = max((innerBorder * 2) , min((cA.bottom - border - additional), (((cA.right - border) / ratio))));

    cxBorder = (cA.right - cxMax) / 2;

    hBitmapDraw = CreateCompatibleBitmap(hdcDisplay, cxMax, cyMax);
    hBitmapPrevious = static_cast<HBITMAP>(SelectObject(hdcBuffer, hBitmapDraw));
    GetObject(hBitmapDraw, sizeof(BITMAP), &bmpDraw);

    BITMAPINFOHEADER bmpInfo;

    bmpInfo.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.biWidth = cxMax;
    bmpInfo.biHeight = cyMax;
    bmpInfo.biPlanes = 1;
    bmpInfo.biBitCount = 32;
    bmpInfo.biCompression = BI_RGB;
    bmpInfo.biSizeImage = 0;
    bmpInfo.biXPelsPerMeter = 0;
    bmpInfo.biYPelsPerMeter = 0;
    bmpInfo.biClrUsed = 0;
    bmpInfo.biClrImportant = 0;

    //pBitmapBits = (BYTE*)malloc(sizeof(BYTE)* cxMax * 3 * cyMax);
    //hBitmapDraw = CreateDIBSection(hdcDisplay, (BITMAPINFO *)&bmpInfo, DIB_RGB_COLORS, NULL, NULL, 0);
    SelectObject(hdcBuffer, hBitmapDraw);

    SelectObject(hdcBuffer, GetStockObject(DC_PEN));
    SelectObject(hdcBuffer, GetStockObject(DC_BRUSH));

    SetDCPenColor(hdcBuffer, RGB(255, 255, 255));

    for (i = 0; i < sA.getNumberOfMonitors(); i++)
    {
        rT = {
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.left - sA.getDesktop()->left) / (sA.getDesktop()->right - sA.getDesktop()->left)) * cxMax) + cxBorder + innerBorder,
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.top - sA.getDesktop()->top) / (sA.getDesktop()->bottom - sA.getDesktop()->top)) * cyMax) + (border / 2) + innerBorder,
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.right - sA.getDesktop()->left) / (sA.getDesktop()->right - sA.getDesktop()->left)) * cxMax) + cxBorder - innerBorder,
            ((static_cast<float>(sA.getMonitor(i)->rcMonitor.bottom - sA.getDesktop()->top) / (sA.getDesktop()->bottom - sA.getDesktop()->top)) * cyMax) + (border / 2) - innerBorder,
        };

        SetDCPenColor(hdcBuffer, RGB(255, 255, 255));

        //Draw Borders
        Rectangle(hdcBuffer, rT.left - innerBorder, rT.top, rT.left, rT.bottom);
        Rectangle(hdcBuffer, rT.right, rT.top, rT.right + innerBorder, rT.bottom);
        Rectangle(hdcBuffer, rT.left - innerBorder, rT.bottom, rT.right + innerBorder, rT.bottom + innerBorder);
        Rectangle(hdcBuffer, rT.left - innerBorder, rT.top - innerBorder, rT.right + innerBorder, rT.top);


        SetDCPenColor(hdcBuffer, RGB(0, 0, 0));

        Rectangle(hdcBuffer, rT.left, rT.top, rT.right, rT.bottom);

        DrawText(hdcBuffer, sA.getMonitor(i)->szDevice, strlen(sA.getMonitor(i)->szDevice), &rT, DT_CENTER | DT_BOTTOM | DT_NOPREFIX | DT_SINGLELINE);
    }

    BitBlt(hdcDisplay, cxBorder, (border / 2), cxMax - cxBorder, cyMax, hdcBuffer, cxBorder, border/2, SRCCOPY);
    SelectObject(hdcBuffer, hBitmapPrevious);
    DeleteDC(hdcBuffer);
    EndPaint(hwnd, &ps);

1 个答案:

答案 0 :(得分:1)

您可以通过执行以下操作绘制位图:

HDC memDC = CreateCompatibleDC(hdc);
HBITMAP memBM = CreateCompatibleBitmap(hdc, nWidth, nHeight);
SelectObject(memDC, memBM);

只需使用hdc替换代码中的memDC来电。然后,您可以使用memDC作为源DC来呼叫StretchBlt

完成内存DC后,使用DeleteDC进行清理。

MSDN有一个Scaling an image使用此技术的示例。您可以使用绘图逻辑替换DrawBitmap代码。