将气球Windows添加到. net应用程序

介绍 计算形状 制约该地区 突出一个影子 结论 类结构 建立历史 版权 介绍 本文介绍了BalloonWindow类。BalloonWindow的设计目标是允许任何。net应用程序显示功能类似于操作系统的气球,如图2所示。 用c#编写的,BalloonWindow公开了必要的功能来完全定制气球的外观。自定义的例子包括:设置背景样式或颜色;通过调整锚点位置、角曲率或阴影效果来定义气球的布局;并像所有其他表单类一样在气球中放置控件。 计算形状 气球的形状由GraphicsPath对象维护,并通过RecalcLayout方法计算。隐藏,复制Code

private GraphicsPath RecalcLayout(Rectangle rect, Point target)
{
   GraphicsPath gp = new GraphicsPath();

两个独立的部件控制锚的形状和位置:锚象限指示四个边中的一个,锚偏移指示沿指定锚象限增加的距离。图3显示了这两个组件与气球整体之间的关系。 一个重要的设计考虑是让它们独立,因为如图4所示,有12种锚点排列。在任何象限中,锚点的位置可以是前中心、中心或后中心。中心是最小和最大偏移量之间的精确位置。当锚点居中时,它的扫描角是90度,而所有其他位置的角度都是45度,垂直边总是背向中心。 下面的代码片段计算锚象限的必要调整。象限的计算简单,只需要使用矩阵和锚翻转变量,这是简单的解释。这个编码是基于一个旋转的“*”气球为了确定其他锚的位置,也就是说如果他需要锚的三个“*”锚位置,不会利用旋转,然而,如果需要锚左右两边的气球,一个90度或90度旋转,分别将被使用。隐藏,收缩,复制Code

switch(anchorQuadrant)
{
   case AnchorQuadrant.Top:
      break;
   case AnchorQuadrant.Bottom:
      matrix.Translate(balloonBounds.Width, balloonBounds.Height);
      matrix.Rotate(180);

      anchorFlipped = true;
      break;
   case AnchorQuadrant.Left:
      balloonBounds.Size = 
         new Size(balloonBounds.Height, balloonBounds.Width);

      matrix.Translate(0, balloonBounds.Width);
      matrix.Rotate(-90);

      anchorFlipped = true;
      break;
   case AnchorQuadrant.Right:
      balloonBounds.Size =
         new Size(balloonBounds.Height, balloonBounds.Width);

      matrix.Translate(balloonBounds.Height, 0);
      matrix.Rotate(90);

      break;
}

如前所述,当构建路径时,所有的计算都假设锚在上象限。这样做是为了使计算简单和可预测。一旦路径完成,它被调整使用矩阵变量旋转气球,使锚在正确的象限。然而,使用底部锚的象限的顶部提出了一个有趣的问题。当气球旋转180度或270度时,锚定偏移会在需要的中心的另一边结束。图5演示了这种情况。锚翻转变量标记此条件,允许锚的偏移量重新计算,如下所示。从图5可以看出,当锚被旋转180度时,锚被拉到“右下角”。在锚点被放置到正确的位置之前,需要进行一个后续的移动,在这个例子中是“左下角”。“隐藏,复制Code

if(anchorFlipped)
   anchorOffset =
      (int)balloonBounds.Width-(offsetFromEdge*2)-anchorOffset;

不管偏移是前中心,中心还是后中心,锚总是有三个点。下面的代码计算这三个点。隐藏,收缩,复制Code

if(anchorOffset < balloonEdgeCenter)
{
   anchorPoints[0] =
      new Point(anchorOffset+offsetFromEdge,
         (int)balloonBounds.Y+anchorMargin);
   anchorPoints[1] =
      new Point(anchorOffset+offsetFromEdge,
         (int)balloonBounds.Y);
   anchorPoints[2] =
      new Point(anchorOffset+anchorMargin+offsetFromEdge,
         (int)balloonBounds.Y+anchorMargin);
}
else if(anchorOffset > balloonEdgeCenter)
{
   anchorPoints[0] =
      new Point(anchorOffset-anchorMargin+offsetFromEdge,
         (int)balloonBounds.Y+anchorMargin);
   anchorPoints[1] =
      new Point(anchorOffset+offsetFromEdge,
         (int)balloonBounds.Y);
   anchorPoints[2] =
      new Point(anchorOffset+offsetFromEdge,
         (int)balloonBounds.Y+anchorMargin);
}
else
{
   anchorPoints[0] =
      new Point(anchorOffset-anchorMargin+offsetFromEdge,
         (int)balloonBounds.Y+anchorMargin);
   anchorPoints[1] =
      new Point(anchorOffset+offsetFromEdge,
         (int)balloonBounds.Y);
   anchorPoints[2] =
      new Point(anchorOffset+anchorMargin+offsetFromEdge,
         (int)balloonBounds.Y+anchorMargin);
}

计算完成后,路径最终可以构建如下所示。隐藏,复制Code

gp.AddArc(balloonBounds.Left, balloonBounds.Top+anchorMargin,
   cornerDiameter, cornerDiameter,180, 90);

gp.AddLine(anchorPoints[0], anchorPoints[1]);
gp.AddLine(anchorPoints[1], anchorPoints[2]);

gp.AddArc(balloonBounds.Width-cornerDiameter,
   balloonBounds.Top+anchorMargin,
   cornerDiameter, cornerDiameter, -90, 90);
gp.AddArc(balloonBounds.Width-cornerDiameter,
   balloonBounds.Bottom-cornerDiameter,
   cornerDiameter, cornerDiameter, 0, 90);
gp.AddArc(balloonBounds.Left, balloonBounds.Bottom-cornerDiameter,
   cornerDiameter, cornerDiameter, 90, 90);

最后一个问题;调整路径,使锚点位于正确的象限。隐藏,复制Code

gp.Transform(matrix);

制约该地区 GraphicsPathWindow类提供了对非标准窗口形状的支持。这个类本身并不知道窗口的形状;相反,在需要时调用虚拟PreparePath方法,如下所示。这里的GetPath方法检查路径是否被缓存,如果没有,它要求派生类提供路径。隐藏,复制Code

public GraphicsPath GetPath()
{
   GraphicsPath gp = __graphicsPath;

   if(gp == null) gp = PreparePath();

   SetPath(gp);
   return gp;
}

这为所有派生类提供了根据需要定义路径的能力。下面是BalloonWindow用来定义其路径的代码。隐藏,复制Code

protected override GraphicsPath PreparePath()
{
   return __layout.Path;
}

窗口定义了一个区域,该区域指示操作系统仅在该区域内绘制。下面的代码约束该区域并确保窗口看起来像一个气球。从GraphicsPath对象定义区域时,该区域被定义为路径的内部区域。下面的代码包括了路径边界的调整。隐藏,复制Code

private Region RegionFromPath(GraphicsPath gp)
{
   if(gp == null) throw(new ArgumentNullException("gp"));
   Region region = new Region(gp);

   float inflateBy = 1F+2F/(float)Width;
   Matrix matrix = new Matrix();
   matrix.Scale(inflateBy, inflateBy);
   matrix.Translate(-1, -1);
   region.Transform(matrix);

   return region;
}

突出一个影子 Windows 2000引入了分层Windows。层窗口允许操作系统将窗口的内容与背景进行字母混合。这方面的一个例子就是windows 2000和XP中气球窗口投射的阴影。 BalloonWindow的设计目标就是支持同样的阴影效果。几个设计,标本口粮研究并最终最好的方法是实现内容背后的阴影在单独的窗口中定位窗口如图6所示。 类ShadowedWindow维护BalloonWindow继承的阴影效果。当一个影子是第一次显示,CreateShadowProjection创建一个投影对象。记住,ShadowedWindow不是影子本身。影子窗口本身实际上是封装的投影对象由ShadowedWindow维护。隐藏,复制Code

private Projection CreateShadowProjection()
{
   Projection shadow = new Projection(this);
              shadow.BackColor = Color.White;

   BindShadowToOwner(shadow, this);

   return shadow;
}

投射的影子总是背后的内容窗口,具有相同的尺寸。因此,阴影需要抵消略这是可见的。隐藏,复制Code

public void ShowShadow()
{
   GraphicsPathWindow shadow = __shadow;

   if(shadow == null) shadow = __shadow = CreateShadowProjection();

   int shadowMargin = ShadowMargin;
   Point shadowLocation =
      new Point(Location.X+shadowMargin, Location.Y+shadowMargin);
   Size shadowSize = Size;

   shadow.Location = shadowLocation;
   shadow.Size = shadowSize;

   shadow.Show();
}

一个影子上创建一个屏幕位图呈现梯度模式。隐藏,复制Code

Bitmap img = new Bitmap(Width, Height);
GraphicsPath path = GetPath();
Graphics grx = Graphics.FromImage(img);
float scaleFactor = 1F-((float)__owner.ShadowMargin*2/(float)Width);

PathGradientBrush backStyle = new PathGradientBrush(path);
                  backStyle.CenterPoint = new Point(0, 0);
                  backStyle.CenterColor = __owner.ShadowColor;
                  backStyle.FocusScales = 
                      new PointF(scaleFactor, scaleFactor);
                  backStyle.SurroundColors = 
                      new Color[]{Color.Transparent};

Region region = new Region(path);
       region.Translate(-__owner.ShadowMargin, -__owner.ShadowMargin);

grx.SetClip(region, CombineMode.Xor);

grx.FillPath(backStyle, path);

SetBitmap方法初始化和更新层面板使用代码提供的鲁伊Godinho Lopes解释在他每像素α融入c#文件”。“隐藏,复制Code

SetBitmap(img);

结论 BalloonWindow是一个强大的库生成一个简单的UI元素。 类结构 BalloonWindow被设计成一个健壮的和任何应用程序的关键组件。图7显示了用于BalloonWindow公共对象模型。 构建HistoryFor每个构建的信息,请参阅BalloonWindow图书馆为。net门户。 版权 版权©2002 - 2003由彼得·倾斜层的开采 源文件和二进制文件可能会重新分配以任何方式修改的提供他们不卖利润没有作者表达的书面同意,并提供此通知和作者的名字和所有版权声明保持不变。 任何使用软件的源代码或二进制形式,有或没有修改,必须包括,在用户文档(“关于“盒子和打印文档)和内部注释代码,对最终用户通知如下: ”彼得部分版权©2002 - 2003可选里林” 电子邮件让我知道你是使用它就好了。这不是多问考虑进这个的工作量。 这个软件提供了“是”,没有任何类型的保证,明示或默示。使用它在你自己的风险。作者不接受任何责任这种产品可能会导致数据损坏/损失。 本文转载于:http://www.diyabc.com/frontweb/news5016.html