gpt4 book ai didi

c# - Windows 窗体 : Making a cursor bitmap partially transparent

转载 作者:太空狗 更新时间:2023-10-29 18:30:34 24 4
gpt4 key购买 nike

我想在拖放操作中使用部分透明的图像。这一切都已设置好并且工作正常,但实际转换为透明有一个奇怪的副作用。出于某种原因,像素似乎与黑色背景混合在一起。

下图描述了问题:

Transparency problem

图a)是原始位图。

图 b) 是执行 alpha 混合后的结果。显然,这比预期的 50% alpha 过滤器要暗很多。

图 c) 是所需的效果,图 a) 具有 50% 的透明度(使用绘图程序添加到合成中)。

我用来生成透明图像的代码如下:

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;

有谁知道为什么 alpha 混合不起作用?

更新一:

为清楚起见,如果我在绘制的表面上进行 alphablending,代码确实有效。问题是我想从现有图像创建一个完全半透明的图像,并在拖/放操作期间将其用作动态光标。即使跳过上面的步骤,只绘制一个颜色为 88ffffff 的填充矩形,也会产生深灰色。图标有问题。

更新二:

因为我已经研究了很多并且相信这与 Cursor 的创建有关,所以我也将在下面包含该代码。如果我在 CreateIconIndirect 调用之前对位图进行 GetPixel 采样,则四个颜色值似乎完好无损。因此我觉得罪魁祸首可能是 IconInfo 结构的 hbmColor 或 hbmMask 成员。

这是 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.

}

下面是实际创建 Cursor 的代码:

    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));
}

两个外部函数定义如下:

    [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);

最佳答案

在与 GDI(和 Win32)进行互操作时,GDI+ 有许多与 alpha 混合相关的问题。在这种情况下,调用 bmp.GetHbitmap() 会将您的图像与黑色背景混合。一个article on CodeProject提供了有关该问题的更多详细信息,以及用于将图像添加到图像列表的解决方案。

您应该能够使用类似的代码来获取用于掩码的 HBITMAP:

[DllImport("kernel32.dll")]
public static extern bool RtlMoveMemory(IntPtr dest, IntPtr source, int dwcount);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateDIBSection(IntPtr hdc, [In, MarshalAs(UnmanagedType.LPStruct)]BITMAPINFO pbmi, uint iUsage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);

public static IntPtr GetBlendedHBitmap(Bitmap bitmap)
{
BITMAPINFO bitmapInfo = new BITMAPINFO();
bitmapInfo.biSize = 40;
bitmapInfo.biBitCount = 32;
bitmapInfo.biPlanes = 1;

bitmapInfo.biWidth = bitmap.Width;
bitmapInfo.biHeight = -bitmap.Height;

IntPtr pixelData;
IntPtr hBitmap = CreateDIBSection(
IntPtr.Zero, bitmapInfo, 0, out pixelData, IntPtr.Zero, 0);

Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
BitmapData bitmapData = bitmap.LockBits(
bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb );
RtlMoveMemory(
pixelData, bitmapData.Scan0, bitmap.Height * bitmapData.Stride);

bitmap.UnlockBits(bitmapData);
return hBitmap;
}

关于c# - Windows 窗体 : Making a cursor bitmap partially transparent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1236473/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com