0

我正在开发一个需要透明背景的 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)
        {
        }
    }

这里有一些图像可以更好地解释

在此处输入图像描述

在此处输入图像描述

4

1 回答 1

1

如果您想在使用UpdateLayeredWindowAPI 的分层窗口内使用常规控件,则需要覆盖控件的OnPaint方法以将绘图重定向到屏幕外位图,稍后您可以使用该UpdateLayeredWindow方法更新窗口外观。

如果您不想深入研究控件代码,或者没有太多自定义控件,则WM_PRINT可以使用消息来强制控件将自己绘制到提供的设备上下文中。经典窗口子类化 ( SetWindowLong/ GetWindowLong) 用于捕捉控件自身失效的时刻是有用的,但可能有点危险 - 你必须注意回调链。

最后,您可以使用轻量级(无窗口)控件。他们使用表单消息队列来接收事件并绘制自己,因此只需要修改表单绘制代码。一些标准的 winforms 控件支持这种模式。

于 2015-10-14T23:41:30.713 回答