W jednym z poprzednich artykułów opisywałem sposób wyrysowywania grafik z użyciem ColorKey aby uzyskać efekt przezroczystości. W tym artykule chciałbym poruszyć temat grafik o stałym ustalonym przez nas kanale alfa.
Aby uzyskać efekt półprzezroczystości wykorzystamy funkcję AlphaBlend z biblioteki coredll.dll. Po szczegóły na temat tej metody zapraszam na http://www.pinvoke.net ponieważ ja w tym artykule ograniczę się tylko do części wspieranej przez .NET CF:
[DllImport("coredll.dll")]
private extern static int AlphaBlend(IntPtr hdcDest, int xDest, int yDest, int cxDest, int cyDest, IntPtr hdcSrc, int xSrc, int ySrc, int cxSrc, int cySrc, BlendFunction blendFunction);
private struct BlendFunction
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
W BlendFunction możemy tylko ustawić SourceConstantAlpha, czyli stałe alfa dla grafiki. Poniżej prosty class extension:
internal static class GraphicsExtensions
{
internal static void AlphaBlend(this Graphics source, Graphics destination, byte alpha, int xSrc, int ySrc, int wSrc, int hSrc, int xDest, int yDest, int wDest, int hDest)
{
IntPtr hdcDst = source.GetHdc();
IntPtr hdcSrc = destination.GetHdc();
BlendFunction blendFunction = new BlendFunction();
blendFunction.BlendOp = 0; // jedyna wspierana operacja
blendFunction.BlendFlags = 0; // dokumentacja zaleca wstawienie tutaj ?0?
blendFunction.SourceConstantAlpha = alpha; // nasze alfa
blendFunction.AlphaFormat = 0; // wyłączone alfa na pixel
AlphaBlend(hdcDst, xDest, yDest, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, blendFunction);
source.ReleaseHdc(hdcSrc);
destination.ReleaseHdc(hdcDst);
}
}
Teraz wystarczy tylko na istniejącego Graphics-a nałożyć drugiego z określoną grafiką:
using (Bitmap colorImage = new Bitmap(128, 128))
{
using (Graphics gCi = Graphics.FromImage(colorImage))
{
gCi.Clear(Color.Red);
g.AlphaBlend(gCi, 192,
0, 0, colorImage.Width, colorImage.Height,
0, 0, colorImage.Width, colorImage.Height);
}
}
W przypadku jak powyżej g jest naszym aktualnym graphicsem na którym rysujemy. Graphics gCi to jest pokolorowany na czerwono kwadrat, któremu nadajemy alfa o wartości 192. Oczywiście nic nie stoi na przeszkodzie aby używać dowolnych “rysowalnych” elementów jak w screenie poniżej:



Adam Ciszewski
/ 2009-09-23Witam chciałbym zapytać czy grafiki (górne cztery) są wyrysowywane bezpośrednio na formie i potem pola jakie zajmują służą jako przyciski ? czy może na jakimś przezroczystym tle komponentu ? próbuje wykorzystac picturebox z transparentną grafiką uzyskana wg. Pana wczesniejszego przepisu (colorKey), ale wyrysowuje grafike podczas “Paint” i pozostaje mi niestety backcolor PictureBox’a (caly obszar niezajęty przez wyrysowywany obraz) :/ (ale przynajmniej z pominięciem koloru transparentnego) czy mogę prosić o poradę ?
Jakub Florczyk
/ 2009-10-21@Adam Ciszewski
Po pierwsze to nie Pan :p Sorka ale umknął mi jakoś ten komentarz. Całość jest rysowana na jednym formie i to bardzo pokombinowane, żeby taki efekt uzyskać a do tego koszmarnie wolne.
Co do PictureBox to takiego efektu nie uzyskasz. Musisz sam rysować grafikę na Formie, przeciążając metodę OnPaint i wtedy rysować z ColorKey.
Piotr G
/ 2009-12-25Witam
Nie mogę dodać referencji coredll.dll dla visual studio 2008 co może być tego powodem ?
Jakub Florczyk
/ 2009-12-25@Piotr G
Nie można dodać referencji do tej biblioteki. Musisz znać definicję funkcji i się odwoływać przez DllIpmort. Jak np. w pierwszym przykładzie z tego wpisu.
Piotr G
/ 2009-12-25Dzięki wielkie
A może Pan w wolnym czasie opisać przykładową implementacje biblioteki Winsock Orcas.dll dla windows mobile pod Visual Studio 2008 ? Bo nigdzie nie mogę jej znaleźć. Lub jak sprawdzić w system.net.socket czy doszedł cały pakiet z serwera do clienta na programie(cliencie) ?