Ich möchte teilweise transparente Bilder in Drag/Drop-Operationen verwenden. Dies ist alles eingerichtet und funktioniert gut, aber die eigentliche Transformation zu Transparenz hat eine seltsame Nebenwirkung. Aus irgendeinem Grund scheinen die Pixel vor einem schwarzen Hintergrund zu liegen.Windows Forms: Eine Cursor-Bitmap teilweise transparent machen
Das folgende Bild beschreibt, das Problem:
Abbildung a) das ursprüngliche Bitmap ist.
Abbildung b) ist, was nach dem Alpha-Blending erzeugt wurde. Offensichtlich ist dies viel dunkler als der beabsichtigte 50% Alpha-Filter.
Abbildung c) ist der gewünschte Effekt, Bild a) mit 50% Transparenz (mit einem Zeichenprogramm der Komposition hinzugefügt).
Der Code, den ich die trasparent Bild zu erzeugen, verwenden ist folgende:
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;
Weiß jemand, warum das Alpha-Blending nicht funktioniert?
Update I:
Aus Gründen der Klarheit wird der Code funktioniert, wenn ich auf einer gezogenen Oberfläche Alphablending. Das Problem ist, dass ich ein vollständig semitransparentes Bild aus einem vorhandenen Bild erstellen und dieses als dynamischen Cursor während Drag & Drop-Operationen verwenden möchte. Selbst wenn man das obige überspringt und nur ein gefülltes Rechteck der Farbe 88ffffff malt, erhält man eine dunkelgraue Farbe. Etwas Fischiges geht mit dem Icon vor sich.
Update II:
Da ich eine ganze Menge reseached haben und glauben, dass dies hat etwas mit dem Cursor Schöpfung zu tun, ich werde schließen, dass Code unten zu. Wenn ich GetPixel die Bitmap kurz vor dem CreateIconIndirect-Aufruf sample, scheinen die vier Farbwerte intakt zu sein. So habe ich das Gefühl, die Täter könnten die hbmColor- oder die hbmMask-Mitglieder der IconInfo-Struktur sein.
Hier ist die ICONINFO Struktur:
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.
}
Und hier ist der Code, der den Cursor tatsächlich erstellt:
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));
}
Die beiden externen Funktionen sind wie folgt definiert:
[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);
ich weiß nicht die Antwort, aber das ist eine _very_ gute Frage. :) –
Danke! Es erscheint mir * wirklich * komisch, dass selbst nach fünfzehn Jahren Drag/Drop-Operationen und benutzerdefinierten Cursorn diese Sache nicht einfach gelöst werden kann. Ich bekomme * einige * Transparenz, so dass zumindest das System darauf hinweist, dass es möglich ist. Nachdem ich drei Tage lang hart auf meine Tastatur geklopft und Artikel gelesen habe, habe ich einen kleinen Verdacht, den man vielleicht braucht, um die BITMAPV5HEADER-Struktur anzuzapfen. Hier ist ein C++ - Artikel, der das Problem lösen könnte: http://support.microsoft.com/default.aspx?scid=kb;en-us;318876. Wenn jemand dies portieren kann, werde ich gerne die angenommene Antwort abgeben. – Pedery