如何使用透明表单,您可以点击

时间:2014-07-18 02:20:40

标签: c# winforms

我下面的内容是运行时提供的pos,pic和透明度的dll。将在屏幕上显示图片,图片将是最重要的对象,无论如何。您还可以点击图片。我遇到的问题是,当使用圆形图片时,它在圆的边缘周围有白色,使其成为正方形。我想摆脱图片的那些白色边缘,所以我只剩下一个最顶部的圆圈,我可以点击。下面的代码中的所有内容都有效,除非我有f.TransparencyKey = BackColor;我无法再点击图片,但它确实使它成为一个圆圈。现在我将如何制作它以便我可以点击图片,同时将其变成圆形而不是方形?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace pic
{
public class Class1
{
    [DllImport("user32.dll", SetLastError = true)]
    private static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    [DllImport("user32.dll")]
    static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
    public const int GWL_EXSTYLE = -20;
    public const int WS_EX_LAYERED = 0x80000;
    public const int WS_EX_TRANSPARENT = 0x20;
    public const int LWA_ALPHA = 0x2;
    public const int LWA_COLORKEY = 0x1;


    public void t(int LocalX, int LocalY, string PicLocal, byte transparency)
    {
        Bitmap bitmap;
        Form f = new Form();
        f.BackColor = Color.White;
        f.FormBorderStyle = FormBorderStyle.None;
        f.Bounds = Screen.PrimaryScreen.Bounds;
        f.TopMost = true;
        bitmap = new Bitmap(PicLocal);
        f.Size = new Size(bitmap.Size.Width, bitmap.Size.Height);
        f.StartPosition = FormStartPosition.Manual;
        f.SetDesktopLocation(LocalX, LocalY);
        Application.EnableVisualStyles();
        SetWindowLong(f.Handle, GWL_EXSTYLE,
        (IntPtr)(GetWindowLong(f.Handle, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT));
        // set transparency to 50% (128)
        SetLayeredWindowAttributes(f.Handle, 0, transparency, LWA_ALPHA);
        f.BackgroundImage = Bitmap.FromFile(PicLocal);
        //f.AllowTransparency = true;
        //Color BackColor = Color.White;
        // Make the background color of form display transparently. 
        //f.TransparencyKey = BackColor;
        Application.Run(f);

    }

}
}

3 个答案:

答案 0 :(得分:3)

试试这个

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
static class Program
{
    [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
    private static extern IntPtr CreateRoundRectRgn
    (
        int nLeftRect, // x-coordinate of upper-left corner
        int nTopRect, // y-coordinate of upper-left corner
        int nRightRect, // x-coordinate of lower-right corner
        int nBottomRect, // y-coordinate of lower-right corner
        int nWidthEllipse, // height of ellipse
        int nHeightEllipse // width of ellipse
     );

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        string PicLocal = @"C:\Projects\Screenshot_1.bmp";

        Form f = new Form() {  FormBorderStyle = FormBorderStyle.None, StartPosition = FormStartPosition.CenterScreen};
        f.BackgroundImage = new Bitmap(PicLocal);
        f.Size = new Size(f.BackgroundImage.Size.Width, f.BackgroundImage.Size.Height);
        f.Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, 200, 200, 2000, 2000));
        f.Click += (s, e) => { System.Windows.Forms.MessageBox.Show("Clicked"); };

        Application.Run(f);

    }
}

}

我在这里找到了一个更简单的解决方案 Make a form's background transparent

您不必使用Region Property和CreateRoundRectRgn,只需确保您有圆形透明图像

 f.BackColor = Color.Magenta;
 f.TransparencyKey = Color.Magenta;

答案 1 :(得分:3)

    SetWindowLong(f.Handle, GWL_EXSTYLE,
    (IntPtr)(GetWindowLong(f.Handle, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT));

这是问题的开始。这是一个非常麻烦的陈述,有太多的副作用。核心问题是您使用Handle属性,强制Winforms创建本机窗口。太早了,并带有错误的风格标志。 WS_EX_LAYERED已经是Winforms本身使用的样式标志,需要实现Form.Opacity和Form.TransparencyKey属性。

此代码将在Windows XP以及任何后续关闭Aero的Windows版本上完全出错。在这种情况下创建分层窗口需要更多的工作,Windows必须在视频适配器中创建视频覆盖。这提供了alpha和颜色键控效果,视频适配器有一个简单的混音器,它将帧缓冲器中的像素与覆盖中的像素组合在一起。无法通过使用SetWindowLong()设置样式标志来创建该叠加层,它必须由CreateWindowEx()完成。

换句话说,您必须覆盖CreateParams属性。出于这个原因,它是虚拟的,在用于创建窗口之前覆盖窗口样式标志。之后设置TransparencyKey属性将没有所需的效果,窗口创建得太早。

解决方案非常简单,只需完全摆脱此代码即可。 SetWindowLong()和SetLayeredWindowAttributes()都是pinvokes。因为Winforms已经实现了你想要做的事情。修正:

    Color BackColor = Color.White;
    f.TransparencyKey = BackColor;
    f.Opacity = transparency/255f;

考虑将透明度除以100f,这是真正的百分比。将其重命名为“不透明度”也不会造成伤害。

答案 2 :(得分:0)

我最终使用了一个图片框来显示图片,这让我可以点击一张图片,同时在图片上有透明度。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace pic
{
public class Class1
{
    [DllImport("user32.dll", SetLastError = true)]
    private static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    [DllImport("user32.dll")]
    static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
    public const int GWL_EXSTYLE = -20;
    public const int WS_EX_LAYERED = 0x80000;
    public const int WS_EX_TRANSPARENT = 0x20;
    public const int LWA_ALPHA = 0x2;
    public const int LWA_COLORKEY = 0x1;


    public void t(int LocalX, int LocalY, string PicLocal, byte transparency)
    {
        Bitmap bitmap;
        Form f = new Form();
        f.BackColor = Color.White;
        f.FormBorderStyle = FormBorderStyle.None;
        f.Bounds = Screen.PrimaryScreen.Bounds;
        f.TopMost = true;
        bitmap = new Bitmap(PicLocal);
        f.Size = new Size(600, 600);
        f.StartPosition = FormStartPosition.Manual;
        f.SetDesktopLocation(LocalX, LocalY);
        Application.EnableVisualStyles();



        PictureBox PictureBox1 = new PictureBox();

        PictureBox1.Location = new System.Drawing.Point(70, 120);
        PictureBox1.Image = bitmap;

       PictureBox1.Size = new System.Drawing.Size(140, 140);

        PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;

        f.Controls.Add(PictureBox1);

        f.AllowTransparency = true;
        SetWindowLong(f.Handle, GWL_EXSTYLE,
        (IntPtr)(GetWindowLong(f.Handle, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT));
        // set transparency to 50% (128)
        SetLayeredWindowAttributes(f.Handle, 0, transparency, LWA_ALPHA);

        Color BackColor = Color.White;
        f.TransparencyKey = BackColor;
        f.Opacity = transparency / 255f;

        Application.Run(f);

    }

}
}