一个托管的c++按钮控件
如果你喜欢这篇文章,请为它投票。如果你不喜欢这篇文章,请投票,并告诉我你为什么不喜欢它。 介绍 我开始这个项目是为了了解如何开发一个在质量上类似于标准。net按钮控件的管理自定义控件。像大多数。net初学者一样,我从UserControl类开始继承,但很快就了解到我想实现的一些概念有很大的局限性。 在对谷歌和MSDN文档进行了大量的搜索之后,我决定开发一个继承自ButtonBase和IButtonControl的按钮控件。继承ButtonBase的一个问题是这个类是抽象的。这意味着不能在设计器中直接获取按钮控件。但是,可以将它添加到工具箱中,并且它在表单设计器中工作得非常好。 该控制是为灵活性而设计的。它允许圆角或正方形控件。此外,您可以指定哪些角是圆角,哪些角是正方形。您还可以更改角的半径。我使许多颜色可配置。我还包括了为悬停和普通颜色绘制渐变的能力。我实现了标准。net按钮控件可以响应的大多数事件。通过实现IButtonControl接口,还公开了几个标准的按钮行为。 背景 有很多。net自定义控件上传到CodeProject。我们为什么需要另一个?部分原因是因为我是一个c++程序员。我想知道将我的WTL和ATL技能转移到。net需要什么。我想了解在WTL中设计一个控件和在VB中设计一个控件之间的区别。净或c#。我大量使用属性来描述属性和分配默认值。我还添加了XML文档标签,这样当在表单中使用控件时,Intellisense就会很有意义。 我基于WiB和Alan Zhao的工作建立了这个控制模型。他们的两篇文章都提供了大量的灵感和教育。 编译和使用源代码 下载并解压缩演示项目。请确保保留源文件的目录结构。 第一次加载解决方案时,可能会看到许多关于缺少引用的消息。这是因为该程序集尚未在您的机器上构建。(我没有在源分发版中包含任何二进制文件,因此缺少引用。)只需选择发布或调试模式,然后重新编译。将构建程序集,并验证所有引用。此时,可以通过将程序集拖动到工具箱表面或从上下文菜单中选择“add Item…”并导航到根目录dir> \mehControls
elease并选择mehButton.dll将控件添加到工具箱中。
使用组件
将控件添加到工具箱后,可以将其拖动到任何窗体。我实现了一个设计器组件,因此所有属性都正确地显示在“properties”视图中。您会注意到,我在设计器的PostFilterProperties方法中删除了一些最难实现的属性。其他属性,比如“平面”属性,是多余的。编程mehControl是相当标准的。下面的代码说明了表单设计器向导是如何在c#项目中初始化控件的:
隐藏,收缩,复制Code
// // mehButton1 // this.mehButton1.BackColor = System.Drawing.SystemColors.Control; this.mehButton1.ButtonStyle = mehControls.mehButton.ButtonStyles.Rectangle; this.mehButton1.CurveMode = mehControls.mehButton.CornerCurveStyle.None; this.mehButton1.DialogResult = System.Windows.Forms.DialogResult.None; this.mehButton1.GradientStyle = mehControls.mehButton.GradientStyles.None; this.mehButton1.HoverBorderColor = System.Drawing.SystemColors.ControlDark; this.mehButton1.HoverColorA = System.Drawing.SystemColors.ButtonFace; this.mehButton1.HoverColorB = System.Drawing.SystemColors.ButtonHighlight; this.mehButton1.Image = null; this.mehButton1.Location = new System.Drawing.Point(12, 122); this.mehButton1.Name = "mehButton1"; this.mehButton1.NormalBorderColor = System.Drawing.SystemColors.WindowFrame; this.mehButton1.NormalColorA = System.Drawing.SystemColors.ButtonHighlight; this.mehButton1.NormalColorB = System.Drawing.SystemColors.ButtonFace; this.mehButton1.Radius = 0; this.mehButton1.Size = new System.Drawing.Size(127, 38); this.mehButton1.SmoothingQuality = mehControls.mehButton.SmoothingQualities.AntiAlias; this.mehButton1.TabIndex = 4; this.mehButton1.Text = "m&ehButton Flat"; this.mehButton1.UseVisualStyleBackColor = false; this.mehButton1.MouseLeave += new System.EventHandler(this.mehButton1_MouseLeave); ... // The control's events are implmented in a standard fashion. // The C# design wizard is able to auto-fill the events // properly from the "Properties" sheet. private void mehButton1_MouseLeave(object sender, EventArgs e) { this.lblEventText.Text = "Mouse has left mehButton1"; }
实现一个设计师 当您为。net开发自定义可视化控件时,您将需要实现一个设计器。设计器可以很简单(就像我实现的那样),也可以很复杂。下面的代码说明了最小设计器的定义: 隐藏,复制Code
namespace mehControls { ref class mehButtonDesigner : public System::Windows::Forms::Design::ControlDesigner { public: mehButtonDesigner(void) { }; ~mehButtonDesigner(void) { }; protected: virtual void PostFilterProperties(IDictionary ^) override; virtual void OnPaintAdornments(PaintEventArgs ^e) override; }; }
将属性 您需要正确地设置属性。这将允许您控制属性在属性显示中的分组位置以及属性的默认值。 隐藏,复制Code
[DefaultValue(System::Drawing::Color::typeid, "System::Drawing::SystemColors::Control")] [Description("Background Color for button"), Category("Appearance")] // This is how you split a property definition // This is useful if the property has many lines of // code or you do not want to expose the // inner workings of your code in the header. property virtual Color BackColor { // The property function prototypes are specified here Color get() override; void set(Color value) override; }
处理控件的OnPaint事件 与本机模式编程一样,大多数工作是在控件的OnPaint(或OnPaintBackground)事件中处理的。在控件的情况下,DrawRoundRectangle完成了大部分繁重的工作。为了实现圆角,我大量使用了gp->AddArc(arc, angle1, angle2),其中GraphicsPath ^gp = gcnew GraphicsPath()。 总结 该按钮实现了。net 2.0按钮的许多属性。弄清楚如何添加“热”边界的绘画是一件很有趣的事情。在画圆角的时候,我必须使用我十年级的几何知识来计算出正确的圆角中心。这是我用于开发圆角算法的基本图: 我也能够实现背景的渐变绘制,当鼠标在按钮上或点击事件时,允许一些非常酷的效果。下面的枚举说明了i的梯度类型mplemented: 隐藏,复制Code
enum class GradientStyles { None, Horizontal, Vertical, ForwardDiagonal, BackwardDiagonal };
控制还远远没有完成。我已经为所有属性添加了属性。但是,使用XML文档标记还有很多工作要做。我还没有在这个版本的控件中实现主题。 你应该知道的事情 我发现在管理模式和混合模式的c++中,有一些项要容易得多。首先,您不必担心导入API调用。您可以包含来自平台SDK的任何头文件,Visual c++将为您处理调用。这是一个巨大的帮助,可以在处理API调用时节省大量时间。在托管的c++项目中,在wchar_t和String之间来回移动要简单得多。 VS 2005没有像c#那样的漂亮的c++向导。当您选择一个Windows控件项目时,就会得到这样的结果。没有设计师。没有铃铛和哨子。在早期,您必须经常查阅文档。然而,我发现我通过艰苦的方式学习了很多关于我的环境的东西。在我知道之前,我并没有经常查阅文档。 在c++和c#之间,向项目添加引用是不同的。您可以使用项目属性页添加引用。只需导航到通用属性,然后单击添加新引用…按钮。 指定名称空间和解析引用的名称:在托管c++中,解析名称时使用"::"而不是"."。 隐藏,复制Code
// You'll use this syntax in managed C++ using namespace System::Windows::Forms; // Instead of the C# syntax //using System.Windows.Forms;
历史 版本1.0—2008年4月11日—控件的初始版本。 本文转载于:http://www.diyabc.com/frontweb/news458.html