Crumb -面包屑状的嵌套按钮

下载source code and demo project, and an executable in the debug folder – 70.3 KB

介绍

这么长时间以来,我一直在尝试寻找一个类似于Ubuntu软件中心的breadcrumb控件,但我就是找不到,所以我决定自己去做一个。所以,在几个小时的工作之后,这就是它!

背景

这张图片显示了我的想法是从哪里来的。

使用的代码

这个类继承了System.Windows.Forms。控件类,而不是来自System.Windows.Forms。按钮,但行为和大多数功能是相同的。System.Windows.Forms.Vercas。Crumb类具有以下特性:

NameDescription显示在按钮上的文本。按钮上显示的图像。文本对齐按钮上文本的对齐方式。图像在按钮上的对齐方式。textimagealign确定图像和文本是否都将按照文本的对齐方式进行对齐,并并排显示。checkbox确定是否应该在按钮上绘制复选框以显示其已选中的属性。否则,按钮将显示有焦点或无焦点。确定单击按钮时是否会更改其选中属性。checked确定按钮是集中显示还是选中了按钮上显示的复选框。获取巢中碎屑的索引。孩子:在水流之后的碎屑。

嵌套行为允许最多检查一个碎屑。在示例表单中,有一个对CrumbClick默认事件的订阅,该事件将始终在嵌套中保留选中的crumb。顺便说一下,截图中蓝色的按钮是选中的碎屑。

我还必须补充一点,背景图像被绘制了多次,以实现背景,因为,正如下面指出的,它没有正常拉伸,右边是透明的。

现在是技术部分…具体来说,就是绘制按钮。嗯,因为我缺乏绘画技巧,我决定使用图像。

隐藏,复制代码static Image Left_Edge = Properties.Resources.crumb_left_end;
static Image Body = Properties.Resources.crumb_body;
static Image Right_Edge = Properties.Resources.crumb_right_end;
static Image Right_Triangle = Properties.Resources.crumb_right_point;

static Image Selected_Left_Edge = Properties.Resources.selected_crumb_left_end;
static Image Selected_Body = Properties.Resources.selected_crumb_body;
static Image Selected_Right_Edge = Properties.Resources.selected_crumb_right_end;
static Image Selected_Right_Triangle = Properties.Resources.selected_crumb_right_point;

static Image Hovered_Left_Edge = Properties.Resources.hovered_crumb_left_end;
static Image Hovered_Body = Properties.Resources.hovered_crumb_body;
static Image Hovered_Right_Edge = Properties.Resources.hovered_crumb_right_end;
static Image Hovered_Right_Triangle = Properties.Resources.hovered_crumb_right_point;

static Image Clicked_Left_Edge = Properties.Resources.clicked_crumb_left_end;
static Image Clicked_Body = Properties.Resources.clicked_crumb_body;
static Image Clicked_Right_Edge = Properties.Resources.clicked_crumb_right_end;
static Image Clicked_Right_Triangle = Properties.Resources.clicked_crumb_right_point;

放置这些静态变量是为了让您可以给它们另一个值。例如,如果您将图像放在外部文件中,这将非常有用。顺便说一下,这些是图片:

它们被用来占用(磁盘上)最小的空间。正如我所说,我必须绘制填充/身体图像多次,因为拉伸它会在上面放置一个透明渐变。

设置这么多设置会带来很多可能性:一个面包屑可能会有/可能没有孩子;可能/可能没有复选框;可能/可能没有图像;可能/可能没有文本。为此,有DefaultSize覆盖属性:

隐藏,复制代码protected override Size DefaultSize
{
get
{
var w = (c == null this.Controls.Count == 0 : 15) :
Math.Max(15, c.Width)) + (this.CheckBox 4 : 0) +
(this.img != null mg.Width : 0) +
(!string.IsNullOrEmpty(this.Text) r> TextRenderer.MeasureText(this.Text, this.Font).Width : 0) +
(this.Parent is Crumb 3 : 0);
return new Size(this.Controls.Count > 0 :
Math.Max(w, this.Width), 24);
}
}

你可能已经注意到了,我把所有的可能性都考虑进去了。最重要的是,如果crumb有一个子节点,它将自动调整大小,因为我有一些bug。文本的字体也很重要。文本被测量,大小也根据它计算。

控件中有一个名为CrumbClick的事件。此事件通过嵌套的碎屑重定向自身。所以任何点击的碎屑会启动所有碎屑的事件。订阅第一个crumb事件将实际上帮助您跟踪所有的crumb。该事件是按标准的,并具有一个EventArgs类称为CrumbClickEventArgs,它有以下属性:

索引嵌套中被单击的碎屑的索引。点击了SenderThe crumb。在被点击之前是否检查了crumb。获取或设置事件后碎屑的检查状态。如果ChecksOnClick为真,则没有任何效果。ChecksOnClickGets或设置crumb是否应该在单击时切换其检查状态。如果这个属性为真,那么不管您在事件参数中说什么,crumb的检查状态总是会转移到另一个状态。

此事件通过订阅子节点的CrumbClick事件传递给父节点。事件的代码是这样的:

隐藏,复制代码EventHandler childClick =
new EventHandler(c_Click);
static void c_Click(object sender, CrumbClickEventArgs e)
{
if ((sender as Crumb).Parent is Crumb)
{ ((sender as Crumb).Parent as Crumb).OnCrumbClick(e); }
}

事件被重新调用,但这次是在父屑上。保留事件参数。

我还提到过,巢里只有一个碎屑可以被检查。这应该是模拟一个选择系统。

隐藏,复制代码public Boolean Checked
{
get
{
return chk;
}
set
{
if (!nocc)
{
nocc = true;

}

nocc是一个静态布尔值,用来声明其他的碎屑不应该更新它们在巢中的同伴,因此会避免溢出异常。

现在,绘图部分:

隐藏,缩小,复制代码public static float dc(PaintEventArgs e, Color foreColor, float x = 0f,
string text = “”, Image img = null, bool clicked = false,
bool hovered = false, bool chk = false, bool chkbox = false,
float width = 0f, Font font = null, bool tai = true,
ContentAlignment ta = ContentAlignment.MiddleCenter,
ContentAlignment ia = ContentAlignment.MiddleLeft,
bool pt = false, bool ch = true)
{
if (font == null) { font = SystemFonts.MessageBoxFont; }
width = Math.Max((ch 5 : 3) + (chkbox 4 : 0) +
(img != null mg.Width : 0) + (!string.IsNullOrEmpty(text) r> TextRenderer.MeasureText(text, font).Width : 0) + (pt 3 : 0), width);

}

这里我绘制按钮的组件图像,然后是文本/图像。不要哭,没有那么难。它只是需要做很多检查,以确保一切都很酷。在最后一行中,有三种不同的方法:dit(绘制图像文本)、di(绘制图像)和dt(绘制文本)。它们都是静态方法,需要很多变量来决定在哪里绘制。以下是守则:

隐藏,缩小,复制代码private static void dt(PaintEventArgs e, Color foreColor, float x = 0f,
ContentAlignment txta = ContentAlignment.MiddleCenter,
string text = “”, Font font = null,
bool chkbox = false, float width = 0f)
{
if (!string.IsNullOrEmpty(text))
{
PointF p = new PointF();

}

这里我根据TextAlign属性绘制文本:

隐藏,缩小,复制代码private static void di(PaintEventArgs e, float x = 0f, Image img = null,
ContentAlignment imga = ContentAlignment.MiddleLeft,
bool chkbox = false, float width = 0f)
{
if (img != null)
{
PointF p = new Point();

}

这里我根据ImageAlign属性绘制图像:

隐藏,缩小,复制代码private static void dit(PaintEventArgs e, Color foreColor, float x = 0f,
ContentAlignment txta = ContentAlignment.MiddleCenter,
string text = “”, Font font = null, bool chkbox = false,
float width = 0f,
ContentAlignment imga = ContentAlignment.MiddleLeft, Image img = null)
{
if (!string.IsNullOrEmpty(text))
{
if (img != null)
{
if (!string.IsNullOrEmpty(text))
{
float w = 0, h = 0, ht = 0;

}

这里我根据TextAlign属性绘制图像和文本。同样,这个混乱被用在控件的OnPaint(…)方法上:

隐藏,复制代码protected override void OnPaint(PaintEventArgs e)
{
Crumb.dc(e, this.ForeColor, 0, Text, this.img, this.clicked,
this.hovered, this.chk, this.chkbox, this.c == null r> this.Width : (this.Width – this.c.Width), this.Font,
this.tai, this.txta, this.imga, this.Parent is Crumb,
this.Controls.Count > 0);
base.OnPaint(e);
}

这里我传递了dc绘制面包屑所需的参数。

同样,dit方法只在TextImageAlign属性设置为true时使用。

在绘制按钮(不是复选框、文本或图像)时,有4个(或3个)可能的选择(取决于是否有复选框):

ClickedHoveredChecked/Selected(如果没有复选框)(如果有,复选框将显示已选中/未选中)正常

当嵌套一个屑,尖的(右)边的父被画在子上面。这可以在子组件的绘制事件的订阅中找到。的代码是:

隐藏,复制代码PaintEventHandler childPaint = new PaintEventHandler(c_Paint);
//Really, this is required for unsubscribing from the event.
//Does it sound right to unsubscribe a NEW DELEGATE from an eventp>

static void c_Paint(object sender, PaintEventArgs e)
{
var c = sender as Crumb;

}

我真的在寻找一种更快的绘图方式,因为,在这个例子中,我在选择面包屑时得到了一些剪切。

的兴趣点

我已经学会了那个图形。在拉伸糟透了。

历史

11/28/2010 -首次发布。12/1/2010 -更新的文章与代码讨论。

请告诉我你发现的bug !此外,如果有些事情似乎不太好,在低评价之前问我!

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年7月8日
下一篇 2020年7月8日

相关推荐