我需要使用Direct2D绘制位图(非矩形)的部分,如下图所示。就像Photoshop用户可以根据所选区域("2016-12-01@12am"
)创建新图层并移动它一样。我能找到的最接近的例子是here,但我无法使其发挥作用。有谁知道怎么做?
谢谢
修改
看起来人们误解了我想要实现的目标。这个新的动画GIF应该更好地解释它。
答案 0 :(得分:1)
在经历了一百万次尝试和失败之后,我找到了答案。微软关于如何在here和here中创建位图不透明蒙版的说明非常令人困惑,并且听起来像是需要黑白图像作为蒙版,但这远非事实。我们真正需要的是只有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
要移动图像,我们必须使用ID2D1Bitmap
。 pRT->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,否则你会得到你注意到的闪烁。这就是我为几场比赛做动画动画的方法。