65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 GDI+ 创建非矩形窗体

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (37投票s)

2004年12月23日

2分钟阅读

viewsIcon

108002

downloadIcon

3538

本文介绍了使用 GDI+ 创建非矩形窗体的方法。

Sample Image

引言

这是我在 CodeProject 上发表的第一篇文章,我在这里花费了大量时间阅读文章。请原谅我任何拼写错误,因为英语不是我的母语。

在本文中,我将向您展示创建非矩形窗体的不同方法,这将使您的应用程序更具吸引力,并且不会浪费您的时间,因为它是一项非常简单的任务。

背景

虽然我不知道如何使用 Visual Studio 6 创建非矩形窗体,但我相信这并非易事。它需要大量的 API 调用。但是使用 Visual Studio .NET,您会发现这非常容易,并且有预定义的步骤可以执行。有两种不同的方法

  1. 使用 Windows Forms 中的 transparency key 属性。
  2. 使用 GDI+ 技术

使用 Windows Forms 中的 transparency key 属性

这是一个简单的解决方案,只需按照以下步骤操作

  • FormBorderStyle 属性设置为 None(这将删除边框)。
  • 创建一个位图,将其设置为窗体的背景图像。
  • 用特定颜色(例如:黑色)填充您希望显示为透明的区域。
  • BackgroundImage 属性设置为您的位图。
  • TransparencyKey 属性设置为指定的颜色(在我们的示例中为黑色)。

因为我们删除了边框,您会发现我们无法关闭或移动我们的窗体,所以我们必须创建鼠标事件,我将在本文后面讨论。

如果这种方式不起作用并且您可以看到整个背景,请检查您显示器的颜色质量是否低于 32 位。如果您使用特定颜色更改 BackColor 属性并将 TransparencyKey 属性设置为相同的颜色,您会发现您的窗体消失了,因为这种方式取决于一些系统设置。我在 MSDN 上搜索了一种制作非矩形窗体的替代方法,我找到了我想要的。

使用 GDI+ 技术

这是一种简单的方法。它也依赖于 TransparencyKey。步骤如下

  • FormBorderStyle 设置为 None
  • 使用指定的颜色设置 BackColor 属性
  • 使用相同的颜色设置 TransparancyKey 属性
  • 现在整个窗体都是透明的
  • 然后使用 GraphicsPath 类指定窗体的可见区域
  • 然后调用 SetClip 方法以使用 GraphicsPath 区域替换裁剪区域
  • 用颜色或图像填充该区域
// The namesapces used 
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

然后,我们必须覆盖 onpaint 事件,该事件在必须重新绘制窗口时调用。

protected override void OnPaint(PaintEventArgs e)
{
    // First we create a graphics object using
    // the PiantEventArgs e that will use the form
    Graphics grfx = e.Graphics;

    // Make Antialiasing which avoid stepped
    // look for circular path and curves you may 
    // use the SmoothingMode.AntiAlias
    grfx.SmoothingMode = SmoothingMode.HighQuality;

    // The GraphicsPath class is a sealed class
    // that Represents a series of connected 
    // lines and curves used to close
    // a path which will be tarnsparent
    GraphicsPath grfxPath1 = new GraphicsPath();

    // To make a circular form we will darw
    // an ellipse that is bounded inside a square which
    // will be simply a circle if it is bounded
    // to a rectangle it will draw an ellipse
    // i will make a form that is formed from 2 ellipses 
    Rectangle rec1 = new Rectangle(0,0,300,100);
    grfxPath1.AddEllipse(rec1);
    Rectangle rec2 = new Rectangle(120,99,60,40);
    grfxPath1.AddEllipse(rec2);

    // setclip Sets the clipping region of this
    // Graphics object to the result of the specified
    // operation combining the current clip region
    // and the specified  GraphicsPath object.
    grfx.SetClip(grfxPath1,CombineMode.Replace);

    // now we replace the clipping region with
    // the region specified in the graphicspath
    // we can fill this region with a color -even
    // the color specified in the TransparensyKey-
    // because the fill method is simply not detected by the TransparensyKey
    Brush b = new SolidBrush(Color.Green);
    grfx.FillEllipse(b,rec1);
    grfx.FillEllipse(b,rec2);

    // u may use the following 2 lines to put
    // an image instead the last four lines 
    // which fill the form with a normal color
    // note: the BackgrounImage can't be used because
    // it is detected by the TransparensyKey
    // Rectangle frmRectangle = new Rectangle(0,0,this.Width,this.Height);
    // grfx.DrawImage(Image.FromFile("zerosones.jpg"), frmRectangle);

    // then we may make a border to our from by using a thick pen
    Pen p = new Pen(Color.Yellow,5f);
    grfx.DrawPath(p,grfxPath1);
}

鼠标事件

因为我们删除了边框,所以我们无法移动我们的窗体,因此我们必须添加鼠标处理程序来替换默认值。

// points to hold the current position
// and the new position for the form and the mouse
Point MouseCurrrnetPos,MouseNewPos,formPos,formNewPos;

bool mouseDown=false;
private void Form1_MouseDown(object sender, 
             System.Windows.Forms.MouseEventArgs e)
{
    // when the mouse is down we must activate
    // a flag to say that the left button is down
    // and then store the current position
    // of the mouse and the form and we will 
    // use these posotions to calculate the offset
    // that must be added to the loaction
    if(e.Button==MouseButtons.Left)
    {
        mouseDown = true;
        MouseCurrrnetPos = Control.MousePosition;
        formPos = Location;
    }
}

// when the user release the mouse button we must update the flag
private void Form1_MouseUp(object sender, 
             System.Windows.Forms.MouseEventArgs e)
{
    if(e.Button==MouseButtons.Left)
        mouseDown=false;
}

// when the mouse moves we get its new position
// then calculate the new location that the form 
// should be moved to 
// and then set the current position of the form
// and the mouse with the new ones 
private void Form1_MouseMove(object sender, 
             System.Windows.Forms.MouseEventArgs e)
{
    if(mouseDown==true)
    {
        // get the position of the mouse in the screen
        MouseNewPos=Control.MousePosition;
        formNewPos.X=MouseNewPos.X-MouseCurrrnetPos.X+formPos.X;
        formNewPos.Y=MouseNewPos.Y-MouseCurrrnetPos.Y+formPos.Y;
        Location=formNewPos;
        formPos=formNewPos;
        MouseCurrrnetPos=MouseNewPos;
    }
}

参考

© . All rights reserved.