使用带有透明色区域的图像按钮

时间:2015-05-31 14:28:04

标签: c# button png

我在PNG中有一张透明和正常颜色的照片。

我将它用于一个按钮:

this.Button1.BackColor = System.Drawing.Color.Transparent;
this.Button1.BackgroundImage = Image;
this.Button1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.Button1.FlatAppearance.BorderSize = 0;
this.Button1.FlatAppearance.MouseDownBackColor = System.Drawing.Color.Transparent;
this.Button1.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent;
this.Button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.Button1.Location = new System.Drawing.Point(0, 0);
this.Button1.Margin = new System.Windows.Forms.Padding(0);
this.Button1.Name = "Skin";
this.Button1.Size = new System.Drawing.Size(294, 194);
this.Button1.TabIndex = 7;
this.Button1.UseVisualStyleBackColor = false;

当我点击透明区域时,它仍然算作单击按钮。

当我点击彩色区域时,如何才能使此按钮仅调用点击事件?

当我点击透明区域时,我希望将其视为点击此按钮后面的对象。

1 个答案:

答案 0 :(得分:2)

您有两种选择:

  • Button使用Region

  • ButtonBackgroundImage一起使用,并检查用户点击的内容Click

选项一只有可行如果你可以创建一个Region,它需要GraphicsPath,这意味着你需要创建形状你需要Graphics这些原始的线条和曲线等。

如果您只有Bitmap具有透明度,那么最好不要将ButtonRegion一起使用。

相反,您可以使用Button1,并在每次点击时检查点击像素的透明度。

如果它是透明的,你可以调用它下面控件的click事件..

private void Button1_MouseClick(object sender, MouseEventArgs e)
{
    Size r = Button1.BackgroundImage.Size;
    // check that we have hit the image and hit a non-transparent pixel
    if ((e.X < r.Width && e.Y < r.Height) &&
            ((Bitmap)Button1.BackgroundImage).GetPixel(e.X, e.Y).A != 0)
    {
        Console.WriteLine("BUTTON clicked");  // test
        // do or call your click actions here!
    }
    // else pass the click on..
    else
    {
        // create a valid MouseEventArgs
        MouseEventArgs ee = new MouseEventArgs(e.Button, e.Clicks, 
                                e.X + Button1.Left, e.Y + Button1.Top, e.Delta);
        // pass it on to the stuff below us
        pictureBox1_MouseClick(pictureBox1, ee);

        Console.WriteLine("BUTTON NOT clicked");  // test
    }
}

请注意,检查假定您的布局正常,左上角的按钮图像没有缩放。如果你需要缩放图像,你应该保留一个缩放的位图来进行检查。但是如果你可以使用非尺度图像,你应该这样做,因为这看起来会更好。

请注意我为下面的控件创建了一个正确的MouseEventArgs参数,因此您也可以访问该按钮或鼠标的位置。

另请注意,使用MouseClick事件代替Click事件会更容易,因为它已经有鼠标位置..

如果您需要/想要使用Click事件,则可以跳过创建EventArgs,因为它没有有意义的数据;只需从点击中传出e

以下是Click事件的开始方式:

private void Button1_Click(object sender, EventArgs e)
{
    // we need the location of the clicked pixel:
    Point clickLocation = Button1.PointToClient(Control.MousePosition);
    // the rest can proceed as above, just with simple EventArgs..

如果您想检查所有鼠标点击事件并将每个事件传递给父母,则必须对它们进行全部编码。

首先让我们看一下order of events on MSDN

  
      
  1. MouseDown事件。
  2.   
  3. 点击活动。
  4.   
  5. 鼠标点击
  6.   
  7. MouseUp事件。
  8.   

所以我们需要从MouseDown开始。我们可以在辅助函数hitTest中进行测试,因此我们可以重复使用它..:

Button clickedButton = null;
MouseEventArgs ee = null;

void hitTest(Button btn, MouseEventArgs e)
{
    Size r = btn.BackgroundImage.Size;
    // check that we have hit the image and hit a non-transparent pixel
    if ((e.X < r.Width && e.Y < r.Height) &&
            ((Bitmap)btn.BackgroundImage).GetPixel(e.X, e.Y).A != 0)
    {
        clickedButton = btn;
        ee = new MouseEventArgs(e.Button, e.Clicks, e.X + btn.Left, e.Y + btn.Top, e.Delta);
    }
    else clickedButton = null;
}

现在我们编写所有四个事件的代码。我们只需拨打hitTest一次,我们就会在e事件中传递简单的,未经修改的Click参数:

private void Button1_MouseDown(object sender, MouseEventArgs e)
{
    hitTest(sender as Button, e);
    if (sender != clickedButton)
        yourParent_MouseDown((sender as Button).Parent, ee);
    else // do your stuff
}

private void Button1_Click(object sender, EventArgs e)
{
    if (sender != clickedButton)
        yourParent_Click((sender as Button).Parent, e);
    else // do your stuff
}

private void Button1_MouseClick(object sender, MouseEventArgs e)
{
    if (sender != clickedButton)
        yourParent_MouseClick((sender as Button).Parent, ee);
    else // do your stuff
}

private void Button1_MouseUp(object sender, MouseEventArgs e)
{
    if (sender != clickedButton)
        yourParent_MouseUp((sender as Button).Parent, ee);
    else // do your stuff
}

当然,您还需要为yourParent编码所有四个事件..