Прозрачная форма C# с использованием элементов управления рисованием UpdateLayeredWindow

Я разрабатываю exe, где мне нужно иметь прозрачный фон. Я сделал изображение в Photoshop и в нем есть все аккуратные вещи (тени / непрозрачность, отражение и т. д.).

Я изо всех сил пытался заставить это работать, используя TransparentColor + BackColor + Background Image, но я всегда заканчиваю с некоторым пикселем, не прозрачным. Таким образом, я переключился на UpdateLayeredWindow, который работает нормально, но никакой элемент управления не рисуется.

Вот часть моего кода

    private void Form1_Load(object sender, EventArgs e)
    {
        UpdateFormDisplay(this.BackgroundImage);
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        UpdateFormDisplay(this.BackgroundImage);

    }
    public void UpdateFormDisplay(Image backgroundImage)
    {
        IntPtr screenDc = API.GetDC(IntPtr.Zero);
        IntPtr memDc = API.CreateCompatibleDC(screenDc);
        IntPtr hBitmap = IntPtr.Zero;
        IntPtr oldBitmap = IntPtr.Zero;

        try
        {
            //Display-image
            Bitmap bmp = new Bitmap(backgroundImage);
            hBitmap = bmp.GetHbitmap(Color.FromArgb(0));  //Set the fact that background is transparent
            oldBitmap = API.SelectObject(memDc, hBitmap);

            //Display-rectangle
            Size size = bmp.Size;
            Point pointSource = new Point(0, 0);
            Point topPos = new Point(this.Left, this.Top);

            //Set up blending options
            API.BLENDFUNCTION blend = new API.BLENDFUNCTION();
            blend.BlendOp = API.AC_SRC_OVER;
            blend.BlendFlags = 0;
            blend.SourceConstantAlpha = 255;
            blend.AlphaFormat = API.AC_SRC_ALPHA;

            API.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, API.ULW_ALPHA);

            //Clean-up
            bmp.Dispose();
            API.ReleaseDC(IntPtr.Zero, screenDc);
            if (hBitmap != IntPtr.Zero)
            {
                API.SelectObject(memDc, oldBitmap);
                API.DeleteObject(hBitmap);
            }
            API.DeleteDC(memDc);
        }
        catch (Exception)
        {
        }
    }

Вот несколько изображений, чтобы объяснить лучше

1 ответ

Если вы хотите использовать регулярное управление внутри многоуровневого окна, которое использует UpdateLayeredWindow API, вам нужно переопределить контроль OnPaint метод для перенаправления рисунка в закадровый рисунок, который вы позже используете с UpdateLayeredWindow способ обновить внешний вид окна.

Если вы не хотите копаться в коде элементов управления или не имеете много пользовательских элементов управления, WM_PRINT сообщение может быть использовано, чтобы заставить элементы управления рисовать себя в предоставленном контексте устройства. Классическое оконное наследование (SetWindowLong/GetWindowLong) для ловли моментов, когда элементы управления аннулируют себя, полезно, но может быть немного опасно - вы должны следить за цепочкой обратных вызовов.

Наконец, вы можете использовать легкие (без окон) элементы управления. Они используют очередь сообщений формы для получения событий и отрисовки самих себя, поэтому необходимы только модификации кода отрисовки формы. Некоторые стандартные элементы управления winforms поддерживают этот режим.

Другие вопросы по тегам