AquaButton:一个具有Mac OS X外观的定制按钮控件示例

  • 下载demo app - 12 KB
  • 下载source files - 20.1 KB

介绍 通过构建自定义控件,您可以了解。net Windows窗体编程的很多知识。关于这个主题有好几本书籍,但是你很快就会发现自己去谷歌那里回答关于表单、GDI+和Visual Studio的问题,你甚至不知道怎么问。当你找到答案的时候,它们会令人沮丧地不完整。 还有什么更好的学习方法吗? 这就是我写Aqua Button时的感受。由于这是一个学习项目,我不受实用性的限制,所以我着手设计了一个看起来和感觉上都像苹果Mac OS x中的按钮的按钮。苹果的用户界面叫做Aqua®,它具有透明的、彩色的控件。Aqua按钮和Windows按钮有一些共同之处,但它们也有一些相当大的区别: Aqua按钮是默认按钮时的脉冲Aqua按钮不在标签顺序中Aqua按钮通常没有键盘等价物点击Aqua按钮时不会按下,而是会改变颜色 因此,可以肯定地说,AquaButton不会满足Windows界面指导原则。但它可以帮助您实现从使用Windows窗体控件到设计和构建自己的自定义控件的跨越。 绘制3D按钮 AquaButton具有具有文本阴影、按钮阴影和高光的3D外观。虽然可以在OnPaint中使用GDI+重新创建这个外观,但我选择了更简单的方法,在Photoshop中创建了按钮位图。我使用PixelJerk的Photoshop操作来创建我的初始源位图,然后删除背景层,合并剩余的图层,使按钮部分透明。我将该位图分割为三个部分:左端帽(left.png)、右端帽(right.png)和中间的单个像素列(fill.png)。每次AquaButton绘制自己时,它使用DrawImage快速绘制两个end caps,并使用FillRectangle填充主体。这意味着您可以设置AquaButton的宽度,但不能设置高度。 如果您需要更高或更薄的按钮,用您自己的源位图替换,然后将ButtonHeight类常量设置为您的位图的高度。如果你的位图有阴影,设置ButtonShadowOffset类常量,以便它指定从按钮底部到图像底部的距离。AquaButton使用最后这个常量来居中按钮上的标签。 当Aqua按钮是默认按钮(由表单指定)时,它们是浅黄色的。AcceptButton属性)。非默认按钮以灰度绘制。我不需要管理单独的源位图来以灰度绘制按钮——使用GDI+ ImageAttributes以灰度绘制按钮很容易。AquaButton为每个状态声明ImageAttribute和ColorMatrix变量: 隐藏,复制Code

protected ImageAttributes iaDefault, iaNormal;

protected ColorMatrix cmDefault, cmNormal;

我在InitializeGraphics中设置了图像属性和颜色矩阵。我使用cmDefault颜色矩阵使按钮更亮(你将看到为什么在一分钟内,当我解释我如何使用gamma校正来模拟脉冲效果): 隐藏,复制Code

// lighten the default image by reducing opacity
cmDefault = new ColorMatrix();
cmDefault.Matrix33 = 0.5f;

隐藏,复制Code

iaDefault = new ImageAttributes();
iaDefault.SetColorMatrix( cmDefault, ColorMatrixFlag.Default,
                          ColorAdjustType.Bitmap );

我使用cmNormal颜色矩阵来降低饱和度和减轻图像: 隐藏,复制Code

// desaturate the normal image
cmNormal = new ColorMatrix();
cmNormal.Matrix00 = 1/3f;
cmNormal.Matrix01 = 1/3f;
cmNormal.Matrix02 = 1/3f;
cmNormal.Matrix10 = 1/3f;
cmNormal.Matrix11 = 1/3f;
cmNormal.Matrix12 = 1/3f;
cmNormal.Matrix20 = 1/3f;
cmNormal.Matrix21 = 1/3f;
cmNormal.Matrix22 = 1/3f;

// lighten the normal image by reducing opacity
cmNormal.Matrix33 = 0.5f;

iaNormal = new ImageAttributes();
iaNormal.SetColorMatrix( cmNormal, ColorMatrixFlag.Default,
  ColorAdjustType.Bitmap );

现在我所要做的就是绘制三个按钮位图(左边)。png。使用iaDefault或iaNormal,这是DrawButtonState的一个参数: 隐藏,复制Code

protected virtual void DrawButtonState (Graphics g, ImageAttributes ia)
{
   TextureBrush tb;

   // Draw the left end cap
   g.DrawImage( imgLeft, rcLeft, 0, 0, imgLeft.Width, imgLeft.Height,
               GraphicsUnit.Pixel, ia );

   // Draw the right end cap
   g.DrawImage( imgRight, rcRight, 0, 0, imgRight.Width, imgRight.Height,
               GraphicsUnit.Pixel, ia );

   // Draw the middle
   tb = new TextureBrush( imgFill, new Rectangle( 0, 0,
                                imgFill.Width, imgFill.Height ), ia );
   tb.WrapMode = WrapMode.Tile;

   g.FillRectangle ( tb, imgLeft.Width, 0,
                     this.Width - (imgLeft.Width + imgRight.Width),
                     imgFill.Height);

   tb.Dispose( );
}

这就是绘制AquaButton的基本状态。只要再多一点代码,我们就可以扩展它使AquaButton脉冲。 制作按钮脉冲 Aqua按钮脉冲与辉光,似乎起源内部的按钮。我考虑过使用一个类似gif的动画和一个位图序列来显示按钮在照明的几个中间状态,由计时器控制。虽然这将允许我在Photoshop中创建真实的光照,但我将需要许多中间位图来创建流体动画。 我决定使用Gamma校正,这是一种更简单的技术,但牺牲了一些光照质量。前面,我演示了如何使用颜色矩阵来增加默认和普通按钮图像的亮度。我这样做是为了使用gamma校正来绘制图像的亮(1.8 gamma)和暗(0.7 gamma)两个版本。如果太亮或太暗,改变PulseGammaMax和PulseGammaMax。 这就是它的工作原理。AquaButton每70毫秒(脉冲间隔)启动一个计时器使自己失效。在每一个计时器滴答,AquaButton使用伽玛校正绘制自己逐渐轻或深,几乎无缝过渡。我的第一次尝试看起来更像是在眨眼,而不是在搏动——按键几乎是在瞬间从亮到暗。所以我在接近最小或最大伽马时添加了一些逻辑来减缓灯光的变化。如果你对它的样子不满意,可以调整脉冲伽马转移、脉冲伽马传导阈值和脉冲伽马传导常数。下面是TimeOnTick的伽玛移位逻辑: 隐藏,复制Code

if ((gamma - Button.PulseGammaMin < Button.PulseGammaReductionThreshold ) || 
    (Button.PulseGammaMax - gamma < Button.PulseGammaReductionThreshold ))
    gamma += gammaShift * Button.PulseGammaShiftReduction;
else
    gamma += gammaShift;

if ( gamma <= Button.PulseGammaMin || gamma >= Button.PulseGammaMax )
    gammaShift = -gammaShift;

现在我们所要做的就是用新的伽马值更新ImageAttributes并重新绘制按钮。在Aqua中,只有默认的按钮脉冲,所以我只需要更新iaDefault: 隐藏,复制Code

iaDefault.SetGamma( gamma, ColorAdjustType.Bitmap );

Invalidate( );
Update( );

支持视觉设计 AquaButton公开了几个属性来支持Visual Studio设计器: 脉冲-确定AquaButton是否脉冲时,它是默认的按钮。SizeToLabel—确定AquaButton是否根据标签自动设置其宽度。将其设置为true,然后设置按钮标签。AquaButton会在设计时自动调整大小。 AquaButton还在system . window . forms . control中阴影了几个属性: Size - AquaButtons有一个固定的高度,所以允许你在Visual Studio属性网格中设置大小(包括高度)没有意义。由于没有更好的解决方案,我使用自定义设计器将此属性从Visual Studio属性网格中隐藏起来(见下文)。高度- AquaButtons不显示其大小属性,所以你需要另一种方式来查看高度。我跟踪控制。高度,并使其在属性网格中可浏览和只读。宽度-和高度一样,我将这个属性阴影化,并使它在属性网格中可浏览。您可以决定是显式设置宽度,还是使用SizeToLabel自动调整按钮的大小。 我还编写了一个自定义设计器:wildgrap. aqua . controls。ButtonDesigner,过滤掉那些对AquaButton没有意义的属性:AllowDrop, BackColor, BackgroundImage, ContextMenu, FlatStyle, ForeColor,图像,ImageAlign, ImageIndex, ImageList,大小和TextAlign。我这样做是为了简化可视化设计,但我并没有费心对它们进行阴影处理,以防止调用者在代码中设置它们。 延长AquaButton 我已经提到了一些定制AquaButton的方法。如果你正在寻找一个学习项目,这里有一些想法。 AquaButton看起来像一个Aqua按钮,但在选择时表现不同。你可以扩展AquaButton来实现这些缺失的行为,让AquaButton更加忠实于Aqua的外观和感觉: Aqua按钮不在标签顺序中,但AquaButton会把决定权留给你。Aqua按钮不接收焦点,所以默认按钮始终是默认按钮,即使另一个控件有焦点也会脉冲。AquaButton继承了。net按钮选择行为,这意味着您可以简单地通过tab或鼠标悬空使另一个按钮成为默认按钮。 或者你可以用另一种方式,让AquaButton的行为更像。net Windows窗体按钮: 添加焦点提示使所选按钮跳动(即使它不是默认按钮)允许用户设置按钮的高度(一位读者提出了一个解决方案——请参阅本文的反馈) 我对你如何扩展AquaButton很感兴趣。我很乐意在这里发布你的改进,并给予你肯定。 参考文献 CodeProject, www.codeproject.com gotdotnet, www.gotdotnet.com微软。net Windows窗体新闻组,microsoft.public.dotnet。windowsforms microsoft.public.dotnet.windowsforms。微软开发者网络控制,msdn.microsoft.com苹果电脑,浅绿色,www.apple.com/macosx/technologies/aqua.html apple|0>>>>电脑,Aqua人机界面指南,developer.apple.com/techpubs/macosx/essentials/aquahiguidelines/查尔斯的作品,与c#编程Microsoft Windows,微软出版社,2002年理查德·l·周。net Windows表单自定义控件,sam出版,2002年ted百基于组件的开发与Visual c#, M& T书籍,2002年安德鲁•Troelsenc#和。net平台,Apress, 2001 学分 AquaButton是一个独立的创造,没有授权,赞助,或其他批准的苹果电脑公司。Aqua是苹果电脑公司的商标。 修正 2002年9月12日——读者指出这个按钮并没有把点击事件转发到表单中。问题是我在鼠标跟踪代码中做了太多,没有给基类处理事件的机会。在试验了按钮事件之后,我重写了鼠标跟踪逻辑,使其更加简单。 许可证 本文没有附带明确的许可,但可能包含文章文本或下载文件本身的使用条款。如果有疑问,请通过下面的讨论区联系作者。可以在这里找到作者可能使用的许可证列表。 本文转载于:http://www.diyabc.com/frontweb/news1014.html

你可能感兴趣的:(AquaButton:一个具有Mac OS X外观的定制按钮控件示例)