Windows Forms: Dokonywanie częściowej przezroczystości bitmapy kursora

Chcę używać częściowo przezroczystych obrazów w operacjach przeciągania / upuszczania. To wszystko jest skonfigurowane i działa dobrze, ale rzeczywista transformacja w przezroczystość ma dziwny efekt uboczny. Z jakiegoś powodu piksele wydają się być zmieszane na czarnym tle.

Poniższy obraz opisuje problem:

Rysunek a) to oryginalna mapa bitowa.

Rysunek b) przedstawia to, co powstaje po wykonaniu mieszania alfa. Oczywiście jest to dużo ciemniejsze niż zamierzony 50% filtr alfa przeznaczony.

Rysunek c) to pożądany efekt, obraz a) z 50% przezroczystością (dodany do kompozycji za pomocą programu do rysowania).

Kod, którego używam do tworzenia przezroczystego obrazu, jest następujący:

Bitmap bmpNew = new Bitmap(bmpOriginal.Width, bmpOriginal.Height);
Graphics g = Graphics.FromImage(bmpNew);

// Making the bitmap 50% transparent:
float[][] ptsArray ={ 
    new float[] {1, 0, 0, 0, 0},        // Red
    new float[] {0, 1, 0, 0, 0},        // Green
    new float[] {0, 0, 1, 0, 0},        // Blue
    new float[] {0, 0, 0, 0.5f, 0},     // Alpha
    new float[] {0, 0, 0, 0, 1}         // Brightness
};
ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
ImageAttributes imgAttributes = new ImageAttributes();
imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
g.DrawImage(bmpOriginal, new Rectangle(0, 0, bmpOriginal.Width, bmpOriginal.Height), 0, 0, bmpOriginal.Width, bmpOriginal.Height, GraphicsUnit.Pixel, imgAttributes);
Cursors.Default.Draw(g, new Rectangle(bmpOriginal.Width / 2 - 8, bmpOriginal.Height / 2 - 8, 32, 32));
g.Dispose();
imgAttributes.Dispose();
return bmpNew;

Czy ktoś wie, dlaczego mieszanie alfa nie działa?

Aktualizacja I:

Dla jasności kod działa, jeśli wykonuję alfabet na wierzchu narysowanej powierzchni. Problem polega na tym, że chcę stworzyć całkowicie półprzezroczysty obraz z istniejącego obrazu i użyć go jako dynamicznego kursora podczas operacji przeciągania / upuszczania. Nawet pomijanie powyższego i tylko malowanie wypełnionego prostokąta koloru 88ffffff daje ciemnoszary kolor. Z ikoną dzieje się coś podejrzanego.

Aktualizacja II:

Odkąd przeszedłem cały proces i wierzę, że ma to coś wspólnego z tworzeniem kursora, dołączę ten kod również poniżej. Jeśli pobiorę próbkę bitmapową Pixel tuż przed wywołaniem CreateIconIndirect, cztery wartości kolorów wydają się być nienaruszone. Mam więc poczucie, że sprawcami mogą być członkowie hbmColor lub hbmMask struktury IconInfo.

Oto struktura IconInfo:

public struct IconInfo {    // http://msdn.microsoft.com/en-us/library/ms648052(VS.85).aspx
    public bool fIcon;      // Icon or cursor. True = Icon, False = Cursor
    public int xHotspot;
    public int yHotspot;
    public IntPtr hbmMask;  // Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
                            // this bitmask is formatted so that the upper half is the icon AND bitmask and the lower 
                            // half is the icon XOR bitmask. Under this condition, the height should be an even multiple of two. 
                            // If this structure defines a color icon, this mask only defines the AND bitmask of the icon.
    public IntPtr hbmColor; // Handle to the icon color bitmap. This member can be optional if this structure defines a black 
                            // and white icon. The AND bitmask of hbmMask is applied with the SRCAND flag to the destination; 
                            // subsequently, the color bitmap is applied (using XOR) to the destination by using the SRCINVERT flag. 

}

A oto kod, który faktycznie tworzy kursor:

    public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot) {
        IconInfo iconInfo = new IconInfo();
        GetIconInfo(bmp.GetHicon(), ref iconInfo);
        iconInfo.hbmColor = (IntPtr)0;
        iconInfo.hbmMask = bmp.GetHbitmap();
        iconInfo.xHotspot = xHotSpot;
        iconInfo.yHotspot = yHotSpot;
        iconInfo.fIcon = false;

        return new Cursor(CreateIconIndirect(ref iconInfo));
    }

Dwie funkcje zewnętrzne są zdefiniowane w następujący sposób:

    [DllImport("user32.dll", EntryPoint = "CreateIconIndirect")]
    public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);

questionAnswers(5)

yourAnswerToTheQuestion