【问题标题】:Red points on transparent image透明图像上的红点
【发布时间】:2010-02-23 15:23:06
【问题描述】:

我有一个带有

的 Windows 窗体
this.BackColor = Color.Red

this.TransparencyKey = Color.Red

在这个表单上有一个PictureBox(带有透明角的png图像),

PictureBox.SizeMode = Normal.

然后我将 PictureBox 的 SizeMode 设置为 StretchImage 并得到其他结果:
you can see it here

(对不起,我只能放一个超链接)

你可以看到红色的点/点,但它不是 Color.Red 因为它是表单的透明度键。

我尝试实现透明表单,透明控件去除这些“红”点。 无论如何,我想问一下我的最后一点 - 我试图覆盖“OnPaintBackground”方法,当我实现了一些类似下面的代码时:

e.Graphics.FillRectangle(Brushes.Red, ClientRectangle);
TextureBrush brush = ImageHelper.ScaleImage(BackgroundImage, ClientRectangle.Width, ClientRectangle.Height);
e.Graphics.FillRectangle(brush, ClientRectangle);

我在将缩放的位图放入 TextureBrush 之前将其保存到文件中 - 此 png 缩放图像不包含“红色”点,但它们是在表单上绘制的。

有人知道它为什么会发生并告诉我一些解决方法。

最好的问候。

【问题讨论】:

    标签: c# winforms transparent


    【解决方案1】:

    这是因为绘制图像的 GDI+ 不知道红色正在变得透明。

    因此,它将图像的边框与红色背景混合,创建了不透明的微红色(但不是完全红色)像素。

    要解决这个问题,您需要创建一个layered window

    编辑

    使用以下本地方法:

    static class NativeMethods {
        public const int LayeredWindow = 0x80000;//WS_EX_LAYERED
    
        #region Drawing
        [DllImport("User32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool UpdateLayeredWindow(IntPtr handle, IntPtr screenDc, ref Point windowLocation, ref Size windowSize, IntPtr imageDc, ref Point dcLocation, int colorKey, ref BlendFunction blendInfo, UlwType type);
    
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
    
        [DllImport("User32.dll")]
        public static extern IntPtr GetDC(IntPtr hWnd);
    
        [DllImport("User32.dll")]
        public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
    
        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DeleteDC(IntPtr hdc);
    
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    
        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DeleteObject(IntPtr hObject);
        #endregion
    }
    struct BlendFunction {
        public byte BlendOp;
        public byte BlendFlags;
        public byte SourceConstantAlpha;
        public byte AlphaFormat;
    }
    enum UlwType : int {
        None = 0,
        ColorKey = 0x00000001,
        Alpha = 0x00000002,
        Opaque = 0x00000004
    }
    

    覆盖表单的CreateParams:

    protected override CreateParams CreateParams {
        get {
            CreateParams createParams = base.CreateParams;
            createParams.ExStyle |= NativeMethods.LayeredWindow;
            return createParams;
        }
    }
    

    OnShown中调用如下函数:

    static Point Zero;
    [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults")]
    void UpdateWindow() {
        IntPtr screenDC = NativeMethods.GetDC(IntPtr.Zero);
        IntPtr imageDC = NativeMethods.CreateCompatibleDC(screenDC);
        IntPtr gdiBitmap = IntPtr.Zero;
        IntPtr oldBitmap = IntPtr.Zero;
    
        try {
            gdiBitmap = image.GetHbitmap(Color.FromArgb(0));                //Get a GDI handle to the image.
            oldBitmap = NativeMethods.SelectObject(imageDC, gdiBitmap);     //Select the image into the DC, and cache the old bitmap.
    
            Size size = image.Size;                                         //Get the size and location of the form, as integers.
            Point location = this.Location;
    
            BlendFunction alphaInfo = new BlendFunction { SourceConstantAlpha = 255, AlphaFormat = 1 }; //This struct provides information about the opacity of the form.
    
            NativeMethods.UpdateLayeredWindow(Handle, screenDC, ref location, ref size, imageDC, ref Zero, 0, ref alphaInfo, UlwType.Alpha);
        } finally {
            NativeMethods.ReleaseDC(IntPtr.Zero, screenDC);                 //Release the Screen's DC.
    
            if (gdiBitmap != IntPtr.Zero) {                                 //If we got a GDI bitmap,
                NativeMethods.SelectObject(imageDC, oldBitmap);             //Select the old bitmap into the DC
                NativeMethods.DeleteObject(gdiBitmap);                      //Delete the GDI bitmap,
            }
            NativeMethods.DeleteDC(imageDC);                                //And delete the DC.
        }
        Invalidate();
    }
    

    【讨论】:

    • TransparencyKey 属性已经使用分层窗口来实现其效果。
    • 是的,但它并没有按照他需要的方式进行。他需要给一个透明的图像用作窗口背景。
    • 这个解决方案不起作用(因为我需要:))。我创建了新项目,在上面添加了您的代码,插入了具有拉伸布局的背景图像(它具有透明角),将背景颜色和透明度键设置为红色 - 并看到了相同的红点...
    • 啊哈......你描述了透明窗口的解决方案 - blogs.msdn.com/mswanson/archive/2005/07/07/436618.aspx
    • 成功了,谢谢!!!一个问题:我需要做什么才能看到我之前添加到窗体的 Windows 控件,因为窗体只显示背景图像。
    猜你喜欢
    • 1970-01-01
    • 2010-12-01
    • 2010-11-22
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 2011-07-20
    相关资源
    最近更新 更多