Nachdem ich mich wie eine Million versucht und versagt fühlte, fand ich die Antwort. Microsofts Anweisungen zum Erstellen einer Bitmap-Deckkraftmaske in here und here sind sehr verwirrend und es klingt, als ob Sie ein Schwarz-Weiß-Bild als Maske benötigen, aber das ist weit von der Wahrheit entfernt. Was wir wirklich brauchen, ist ein Bild, das nur Alpha-Wert Informationen hat. Auch konnte ich keine Anweisung zum Umwandeln einer HRGN
in eine ID2D1Bitmap
finden. Also musste ich mir meine eigene ausdenken, die ich hier für jeden teilen werde, der das gleiche Problem haben könnte.
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);
}
}
Ich habe die meisten der Fehlerprüfung aus Gründen der Einfachheit weggelassen.
Wenn die Funktion zurückkehrt, sollte der letzte Parameter eine gültige Bitmap-Maske haben (wenn alles korrekt funktioniert hat), die von FillOpacityMask
Funktion von ID2D1RenderTarget
verwendet werden soll.
Jetzt müssen wir unsere ID2D1Bitmap
in eine ID2D1BitmapBrush
drehen.
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
ist das Bild, das wir um und bkBrush
ist ein Zeiger auf ID2D1BitmapBrush
verschieben möchten.
Wenn Sie einen HBITMAP
oder bei C++ Builder Jungs ein TBitmap
, können Sie den Befehl zum Umwandeln einer Bitmap ID2D1Bitmap
here finden.
Jetzt jedes Mal wollen Sie Ihre Fenster malen, können Sie einfach tun:
pRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
pRT->FillOpacityMask(pBmpMask, bkBrush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
pRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
Für das Bild bewegen wir SetTransform
verwenden.pBmpMask
ist eine ID2D1Bitmap
, die mit HRGN_to_D2Bitmap
erstellt wurde. ie:
ID2D1Bitmap* pBmpMask;
HRGN_to_D2Bitmap(bmpWidth, bmpHeight, hShape, pRT, &pBmpMask);
Ich hoffe, dies ist hilfreich.
Sam
Muss es AntiAliased sein? – kizeloo
Es wäre schön, wenn das möglich wäre, wenn nicht, ich würde mich freuen, es einfach ohne Anti-Aliasing anzuzeigen. – Sam
Wie wird es in Ihrem Fenster angezeigt? – kizeloo