Красные точки на прозрачном изображении - PullRequest
2 голосов
/ 23 февраля 2010

У меня есть одна форма Windows с

this.BackColor = Color.Red

и

this.TransparencyKey = Color.Red

и в этой форме есть один PictureBox (png изображение с углами прозрачности),

PictureBox.SizeMode = Normal.

Затем я установил SizeMode для PictureBox на StretchImage и получил другой результат:
вы можете увидеть его здесь

(извините, я могу поставить только одну гиперссылку)

Вы можете видеть красные точки / точки, но это не Color.Red, потому что это ключ прозрачности формы.

Я пытался реализовать прозрачную форму, прозрачный элемент управления для удаления этих «красных» точек. В любом случае, я хотел бы спросить о моей последней точке - я пытался переопределить метод «OnPaintBackground», и когда я реализовал подобный код ниже:

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

Я сохранил масштабированный BitMap в файл перед тем, как поместить его в TextureBrush - это масштабированное изображение png не содержит «красных» точек, но они были нарисованы на форме.

Кто-нибудь знает, почему это происходит, и скажите мне, как это решить.

С уважением.

1 Ответ

1 голос
/ 23 февраля 2010

Это происходит потому, что GDI +, который рисует изображение, не знает, что красный становится прозрачным.

Поэтому он смешивает границы изображения с красным фоном, создавая красноватые (но не полностью красные) пиксели, которые не становятся прозрачными.

Чтобы решить эту проблему, вам нужно создать многослойное окно .

EDIT

Используйте следующие встроенные методы:

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