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

一个浮点型 Margin 结构,现已加入 TypeConverter

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (7投票s)

2007年3月15日

CPOL

4分钟阅读

viewsIcon

45935

downloadIcon

537

一个 Margin 结构,可用于各种情况,如布局、绘图和打印。现已加入自定义 TypeConverter 和使用示例。

Screenshot - Margin.png

目录

引言

这是一个结构,类似于 .NET 2.0 中的 "http://msdn2.microsoft.com/en-us/library/system.windows.forms.padding.aspx">System.Windows.Forms.Padding 结构。但它使用浮点值,而不是整数。我不得不用到一些自定义绘图,这些绘图需要浮点数。因此,我创建了这个结构。

这是我在 CP(或任何编程文章)上的第一篇文章,而且英语不是我的母语,所以只能尽力而为……

现在它能正常工作了,我还制作了一个示例。

背景

margin 和 padding 的区别

在我看来,margin 用于“外部”,而 padding 用于“内部”。这与 Windows Forms 中的概念类似,控件(如按钮)具有两个属性。Margin “指定此控件与另一个控件的 margin 之间的空间”。而 Padding “指定控件的内部间距”。HTML 的用法大体相同。不过,这个结构可以同时用于这两种目的,就像 Padding 结构一样。

边的顺序

Margin 的边的顺序始终是 **左、上、右、下**。这与 Padding 结构以及矩形的 FromLTRB 方法相同。但这与 CSS 样式不同,我相信 CSS 样式使用 **上、右、下、左** 的顺序。LTRB 顺序用于构造函数和 ToString

Margin 成员

构造函数

有几个构造函数可用,大多数都一目了然。但是有一个构造函数不太清楚:new Margin(RectangleF outer, RectangleF inner)。这会创建一个 new Margin,其各边是外部矩形和内部矩形之间的差值。您得到的是内部矩形相对于外部矩形的 margin,或者说是外部矩形相对于内部矩形的 padding。

属性

  • float Left
  • float Top
  • float Right
  • float Bottom

    这些代表 Margin 的每一条边。它们对应于 private ltrb 字段。

  • float HorizontalAverage
  • float VerticalAverage
  • float Average

    获取其中一个属性会返回边的平均值。设置一个属性会将相应的字段设置为该值。

  • Margin Negated

    返回一个 Margin ,其各边与此 Margin 的边相反(反转)。

    {1.4, -2, -19.5, 0}.Negated == {-1.4, 2, 19.5, 0} 

  • Margin Absolute

    返回一个 Margin ,其各边均大于或等于零。

    {1.4, -2, -19.5, 0}.Absolute == {1.4, 2, 19.5, 0} 
  • Margin Rounded

    返回一个 Margin ,其各边是此 Margin 的各边四舍五入后的值。此操作是从零开始向外舍入,而不是银行家舍入。

    {1.4, -2, -19.5, 0}.Rounded == {1, -2, -20, 0} 

  • bool IsRound

    如果此 Margin 的所有边值都是圆整的,则返回 true

  • bool IsEmpty

    如果此 Margin 的所有边都等于零,则返回 true

  • bool IsNaN

    如果此 Margin 的一个或多个边是 float.NaN,则返回 true 。请使用此项在某些计算后检查此 Margin 是否有效。

  • bool IsSymmetric

    如果左边等于右边,并且顶边等于底边,则返回 true

  • bool AllSidesEqual

    如果此 Margin 的所有四条边值都相同,则返回 true

Margin 本身的方法

我实现了一些常见的运算符重载和对应的静态方法。

  • - Negate

    此操作与 Negated 属性执行相同的操作。

    -{1.4, -2, -19.5, 0} == {-1.4, 2, 19.5, 0} 

  • + Add
  • - Subtract
  • * Multiply
  • / Divide

    这些操作将运算符应用于左侧 Margin 项的每个边。右侧可以是一个 Margin、一个 float 或一个 SizeF

    {1.4, -2, -19.5, 0} + 3.2F == {4.6, 1.2, -16.3, 3.2)
    {1.4, -2, -19.5, 0} * new SizeF(2F, 0.5F) == {2.8, -1, -39, 0}
    {1.4, -2, -19.5, 0} - {1.4, -2, -19.5, 0} == {0, 0, 0, 0}
    {1.4, -2, -19.5, 0} / 2F == {0.7, -1, 9.75, 0} 

    我还实现了一个 Translate 函数(没有运算符)。

  • Translate 此方法通过一个值“移动”Margin
    {0, 0, 0, 0}.Translate(1F, 3F) == {1, 3, -1, -3}
    {1.4, -2, -19.5, 0}.Translate(1F, 2F) == {2.4, -4, -20.5, -2}

其他方法

现在,所有这些属性、方法和运算符都很好,但也有一些使用 Margin 的方法会很方便。可用性方法数量有限;可以进行扩展,例如针对点。但是您有四种类型的点(矩形每个角一个),并且这四种点中的每一种都需要以不同的方式进行转换。这在待办事项列表中,当然也欢迎提出建议!

目前,我实现了这些方法:

  • InflateRectangle
  • DeflateRectangle
  • InflateSize
  • DeflateSize

    它们使用 Margin 修改矩形和大小。

我还重写和重载了常用的 object 方法。

  • Equals
  • GetHashCode
  • ToString

如何使用

TypeConverter

经过一番折腾,我终于让 TypeConverter 工作起来了。设计器不再出现错误,或者属性突然重置 Margin 属性。

诀窍是尽可能少地在 MarginConverter 类中使用 Margin 类型。确切原因我也不知道,我认为这与设计器在构建之间管理类型的版本有关。因此,不要这样做:

// The current margin value

Margin margin = (Margin)value;

// The value of each side

float left = margin.Left;
float top = margin.Top;
float right = margin.Right;
float bottom = margin.Bottom;

您必须这样做:

// The current Margin type (from value)

Type type = value.GetType();

// The value of each side, retrieved with reflection

float left = (float)type.GetProperty("Left").GetValue(value, null);
float top = (float)type.GetProperty("Top").GetValue(value, null);
float right = (float)type.GetProperty("Right").GetValue(value, null);
float bottom = (float)type.GetProperty("Bottom").GetValue(value, null);

无论如何,现在它能正常工作了,至少对我来说是这样。如果您发现任何错误,请告诉我。

示例

附带了一个演示项目,它“打印”一页。它用单元格填充页面,您可以调整列数和行数,以及 margin 和 padding。

Screenshot - MarginTest.png

结论

这就是我这个小的 margin 结构,以及我的第一篇文章。希望您能找到一些用途。当然,非常欢迎留下评论!

历史记录

  • 2007-03-15:版本 1.0 - 文章提交
  • 2007-03-16:代码无更改。将文章标题从“Margin 类”改为“Margin 结构”。真是的……
  • 2007-03-29:版本 1.1 - 现在 Margin 有一个(可选的)MarginConverter 用于 PropertyGrid 和设计器。还添加了一个示例。
© . All rights reserved.