使用Direct2d绘制和创建无矩形位图

时间:2016-05-17 20:19:39

标签: c++ windows direct2d

我需要使用Direct2D绘制位图(非矩形)的部分,如下图所示。就像Photoshop用户可以根据所选区域("2016-12-01@12am")创建新图层并移动它一样。我能找到的最接近的例子是here,但我无法使其发挥作用。有谁知道怎么做?

谢谢

enter image description here enter image description here

  

修改

看起来人们误解了我想要实现的目标。这个新的动画GIF应该更好地解释它。

enter image description here

2 个答案:

答案 0 :(得分:1)

在经历了一百万次尝试和失败之后,我找到了答案。微软关于如何在herehere中创建位图不透明蒙版的说明非常令人困惑,并且听起来像是需要黑白图像作为蒙版,但这远非事实。我们真正需要的是只有alpha值信息的图像。此外,我无法找到任何将HRGN转换为ID2D1Bitmap的说明。所以我不得不拿出自己的,我将在这里分享给那些可能遇到同样问题的人。

void HRGN_to_D2Bitmap(const DWORD bmpWidth, const DWORD bmpHeight, HRGN hShape, ID2D1RenderTarget* pRT, ID2D1Bitmap** ppBmpMask)
{
    boost::scoped_ptr<unsigned char> pBmpBuff(new unsigned char[bmpWidth * bmpHeight]);
    DWORD dwCount;
    LPRGNDATA pRgnData;

    memset(pBmpBuff.get(), 0, bmpWidth * bmpHeight);
    dwCount = ::GetRegionData(hShape, 0, NULL);
    boost::scoped_ptr<unsigned char> pRgnBuff(new unsigned char[dwCount]);
    pRgnData = reinterpret_cast<LPRGNDATA>(pRgnBuff.get());
    if (dwCount == ::GetRegionData(hShape, dwCount, pRgnData))
    {
        DWORD i, y;
        RECT* pRect;
        D2D1_BITMAP_PROPERTIES bmpPorp;
        D2D1_SIZE_U bmpSize = D2D1::SizeU(bmpWidth, bmpHeight);

        pRect = (RECT*)pRgnData->Buffer;
        for (i = 0; i < pRgnData->rdh.nCount; i++)
        {
            for (y = (DWORD)pRect->top; ((y < (DWORD)pRect->bottom) && (y < bmpHeight)); y++)
                memset(&pBmpBuff.get()[(y * bmpWidth) + pRect->left], 0xFFFFFFFF, pRect->right - pRect->left);
            pRect++;
        }
        bmpPorp.dpiX = 0.0f;
        bmpPorp.dpiY = 0.0f;
        bmpPorp.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
        bmpPorp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_STRAIGHT;
        pRT->CreateBitmap(bmpSize, pBmpBuff.get(), bmpWidth, bmpPorp, ppBmpMask);
    }
}

为简单起见,我省略了大部分错误检查 当函数返回时,最后一个参数应该有一个有效的位图掩码(如果一切正常),由FillOpacityMask的{​​{1}}函数使用。
现在我们需要将ID2D1RenderTarget转换为ID2D1Bitmap

ID2D1BitmapBrush

D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = D2D1::BitmapBrushProperties( D2D1_EXTEND_MODE_CLAMP, D2D1_EXTEND_MODE_CLAMP, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR ); pRT->CreateBitmapBrush(pOrigBmp, propertiesXClampYClamp, &bkBrush); 是我们要移动的图片,pOrigBmp是指向bkBrush的指针。
如果您有ID2D1BitmapBrush C ++ Builder 的人HBITMAP,您可以找到将位图转换为{{1}的说明}} here
现在,每当您想要绘制窗口时,您只需执行此操作:

TBitmap

要移动图像,我们必须使用ID2D1BitmappRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); pRT->FillOpacityMask(pBmpMask, bkBrush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS); pRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); 是使用SetTransform创建的pBmpMask。即:

ID2D1Bitmap

希望这有用。
萨姆

答案 1 :(得分:0)

好的,我明白了。您是否希望我通过电子邮件向您发送项目来源?它是C ++ Builder 6,因此您的版本应该能够转换它。对于TPanel,我需要将FullRepaint设置为false。

基本思想是在TPanel上放置一个TImage,然后根据您要使用的图像的透明颜色“剪切”面板的hRGN。另外,一定要将TPanel的“FullRepaint”属性设置为false,否则你会得到你注意到的闪烁。这就是我为几场比赛做动画动画的方法。