Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用UpdateLayeredWindow绘图控件的C#透明窗体_C#_Winforms_Png_Transparent - Fatal编程技术网

使用UpdateLayeredWindow绘图控件的C#透明窗体

使用UpdateLayeredWindow绘图控件的C#透明窗体,c#,winforms,png,transparent,C#,Winforms,Png,Transparent,我正在开发一个exe,我需要有一个透明的背景。我在Photoshop中制作了这张图片,它包含了所有整洁的东西(阴影/不透明度、反射等) 我一直在努力使用透明色+背景色+背景图像使其正常工作,但我总是以一些像素不透明而告终。因此,我切换到UpdateLayeredWindow,它工作正常,但现在没有绘制任何控件 这是我的一些代码 private void Form1_Load(object sender, EventArgs e) { UpdateFormDispl

我正在开发一个exe,我需要有一个透明的背景。我在Photoshop中制作了这张图片,它包含了所有整洁的东西(阴影/不透明度、反射等)

我一直在努力使用透明色+背景色+背景图像使其正常工作,但我总是以一些像素不透明而告终。因此,我切换到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)
        {
        }
    }
这里有一些图片可以更好地解释


如果要在使用
UpdateLayeredWindow
API的分层窗口中使用常规控件,则需要重写控件的
OnPaint
方法,将图形重定向到屏幕外位图,稍后使用
UpdateLayeredWindow
方法更新窗口外观

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


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

您需要调用
base.OnPaint(e)从覆盖的OnPaint中调用。是在UpdateFormDisplay之后还是之前调用它?我尝试了这两种方法,但似乎都不适用于非托管结构。@user2920222请尝试将
UpdateFormDisplay
放在
OnPaintBackground
中?顺便说一句,您不应该尝试过多地定制
winforms
,如果您想要更好的解决方案,请尝试使用
WPF