如何在覆盖表单上显示自定义按钮
注意:GitHub上提供了完整的示例项目,网址为:
概述
覆盖表单是一个半透明的启动界面,它在后台线程中运行并覆盖控件或表单来防止对其进行访问,覆盖表单仅包含一个等待指示器。
本示例演示如何显示:
- 等待指示器下方的百分比标签;
- 一个自定义按钮,该按钮终止已处理的任务并关闭覆盖表单。
本示例使您可以更改标签文本、按钮字形以及单击按钮时执行的操作。
实现细节
您可以按以下方式自定义覆盖表单图形:
- 从OverlayWindowPainterBase类继承它;
- 重写Draw方法;
- 将创建的对象作为参数传递给SplashScreenManager.ShowOverlayForm方法。
本示例使用OverlayImagePainter和OverlayTextPainter对象(OverlayWindowPainterBase后代),它们实现了图像和文本的绘制逻辑,并且可以使用它们的属性来自定义图像和文本。
OverlayImagePainter对象在覆盖表单的顶部中心绘制一个自定义图像,并处理该图像上的单击,您可以指定以下属性:
- Image——正常状态下的图像;
- HoverImage——处于悬停状态的图片;
- ClickAction ——单击图像时执行的操作。
OverlayTextPainter对象在等待指示器下方绘制一个自定义标签,您可以指定以下属性:
- Text ——标签文本;
- Font ——文本字体(默认使用Tahoma,18);
- Color ——文本颜色(默认为黑色)。
OverlayWindowCompositePainter对象在OverlayImagePainter和OverlayTextPainter对象中组成绘图逻辑,该复合绘制器作为参数传递给SplashScreenManager.ShowOverlayForm方法。
显示覆盖表单时执行的操作是使用.Net Framework类库(任务并行库(TPL))中可用的可取消任务来实现的。
自定义按钮和标签位置
按钮图像显示在覆盖表单的顶部中央,标签显示在等待指示器下方,您可以重写以下方法来指定其位置:
- OverlayTextPainter.CalcTextBounds —— 返回一个矩形,该矩形指定标签的位置;
- OverlayImagePainter.CalcImageBounds ———返回一个矩形,它指定按钮的位置。
每次需要重新绘制叠加表单时(例如,当用户调整重叠控件的大小时),都会调用这些方法,drawArgs方法参数包含绘制覆盖图所需的信息。本示例使用以下属性:
- Bounds —— 获取Overlay Form边界;
- ImageBounds —— 获取等待指示器的范围;
下面的代码段显示了如何更新当前示例来在自定义位置显示按钮和标签。
C# :
using DevExpress.Utils.Extensions; using DevExpress.XtraSplashScreen; class OverlayImagePainterEx : OverlayImagePainter { public OverlayImagePainterEx(Image image, Image hoverImage = null, Action clickAction = null) : base(image, hoverImage, clickAction) { } protected override Rectangle CalcImageBounds(OverlayLayeredWindowObjectInfoArgs drawArgs) { int indent = 10; return Image.Size.AlignWith(drawArgs.Bounds).WithY(indent).WithX(drawArgs.Bounds.Width - Image.Height - indent); } } class OverlayTextPainterEx: OverlayTextPainter { protected override Rectangle CalcTextBounds(OverlayLayeredWindowObjectInfoArgs drawArgs) { Size textSz = CalcTextSize(drawArgs); return textSz.AlignWith(drawArgs.Bounds).WithY(drawArgs.ImageBounds.Top - textSz.Height); } } public partial class Form1 : RibbonForm { //.. OverlayTextPainter overlayLabel; OverlayImagePainter overlayButton; public Form1() { //... this.overlayLabel = new OverlayTextPainterEx(); this.overlayButton = new OverlayImagePainterEx(buttonImage, hotButtonImage, OnCancelButtonClick); InitializeComponent(); } async void OnRunTaskItemClick(object sender, ItemClickEventArgs e) { //... //Pass the created descendants to the SplashScreenManager.ShowOverlayForm method. IOverlaySplashScreenHandle overlayHandle = SplashScreenManager.ShowOverlayForm(contentPanel, customPainter: new OverlayWindowCompositePainter(overlayLabel, overlayButton)); //...
VB.NET:
Imports DevExpress.XtraSplashScreen Imports DevExpress.Utils.Extensions Friend Class OverlayImagePainterEx Inherits OverlayImagePainter Public Sub New(ByVal image As Image, Optional ByVal hoverImage As Image = Nothing, Optional ByVal clickAction As Action = Nothing) MyBase.New(image, hoverImage, clickAction) End Sub Protected Overrides Function CalcImageBounds(ByVal drawArgs As OverlayLayeredWindowObjectInfoArgs) As Rectangle Dim indent As Integer = 10 Return Image.Size.AlignWith(drawArgs.Bounds).WithY(indent).WithX(drawArgs.Bounds.Width - Image.Height - indent) End Function End Class Friend Class OverlayTextPainterEx Inherits OverlayTextPainter Protected Overrides Function CalcTextBounds(ByVal drawArgs As OverlayLayeredWindowObjectInfoArgs) As Rectangle Dim textSz As Size = CalcTextSize(drawArgs) Return textSz.AlignWith(drawArgs.Bounds).WithY(drawArgs.ImageBounds.Top - textSz.Height) End Function End Class Partial Public Class Form1 Inherits RibbonForm '... Private overlayLabel As OverlayTextPainter Private overlayButton As OverlayImagePainter Public Sub New() '... Me.overlayLabel = New OverlayTextPainterEx() Me.overlayButton = New OverlayImagePainterEx(buttonImage, hotButtonImage, AddressOf OnCancelButtonClick) InitializeComponent() End Sub Private Async Sub OnRunTaskItemClick(ByVal sender As Object, ByVal e As ItemClickEventArgs) Handles biRunTask.ItemClick '... 'Pass the created descendants to the SplashScreenManager.ShowOverlayForm method. Dim overlayHandle As IOverlaySplashScreenHandle = SplashScreenManager.ShowOverlayForm(contentPanel, customPainter:=New OverlayWindowCompositePainter(overlayLabel, overlayButton)) '... End Sub
下图说明了生成的布局。