您的位置:首页 > 其它

WPF 自定义等待对话框、多线程等待的问题

2015-08-19 10:17 375 查看
从网上找个等待对话框的程序实例,找了好几次依然不怎么满意。于是自己写一个好了。并且封装一下。

目前仅适用于WPF。winform的可以稍微改一下也行

不说废话了。

一、等待对话框界面设计

<span style="font-size:14px;color:#333333;"><Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="DialogEx.Controls.WaittingDlg"
Title="WaittingDlg"
Height="45" Width="150"
WindowStyle="None"
AllowsTransparency="True"
WindowStartupLocation="CenterScreen"
Loaded="Window_Loaded">

<Grid>
<Border x:Name="bDlgBorder" Grid.ColumnSpan="2" BorderThickness="1" CornerRadius="3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Width="35" Height="35" Grid.Column="0" HorizontalAlignment="Left">
<Grid.Resources>
<DrawingBrush x:Key="brush" Stretch="None" AlignmentX="Center" AlignmentY="Top">
<DrawingBrush.Drawing>
<GeometryDrawing x:Name="bBrushColor" Brush="Red">
<GeometryDrawing.Geometry>
<EllipseGeometry RadiusX="2" RadiusY="5"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="r01" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.00000" To="0"/>
<DoubleAnimation Storyboard.TargetName="r02" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.08333" To="0"/>
<DoubleAnimation Storyboard.TargetName="r03" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.16666" To="0"/>
<DoubleAnimation Storyboard.TargetName="r04" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.24999" To="0"/>
<DoubleAnimation Storyboard.TargetName="r05" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.33332" To="0"/>
<DoubleAnimation Storyboard.TargetName="r06" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.41665" To="0"/>
<DoubleAnimation Storyboard.TargetName="r07" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.49998" To="0"/>
<DoubleAnimation Storyboard.TargetName="r08" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.58331" To="0"/>
<DoubleAnimation Storyboard.TargetName="r09" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.66664" To="0"/>
<DoubleAnimation Storyboard.TargetName="r10" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.74997" To="0"/>
<DoubleAnimation Storyboard.TargetName="r11" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.83330" To="0"/>
<DoubleAnimation Storyboard.TargetName="r12" Storyboard.TargetProperty="Opacity" AutoReverse="True" Duration="0:0:0.08333" BeginTime="0:0:0.91663" To="0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Rectangle x:Name="r01" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="0"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r02" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="30"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r03" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="60"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r04" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="90"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r05" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="120"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r06" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="150"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r07" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="180"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r08" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="210"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r09" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="240"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r10" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="270"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r11" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="300"/>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="r12" Fill="{StaticResource brush}" Opacity="0.2" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="330"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<TextBlock Grid.Column="1" x:Name="txtWaittingInfo" Margin="5,2,0,0" TextWrapping="Wrap"/>
</Grid>
</Border>
</Grid>
</Window></span><span style="color:#ff0000;font-size:14px;">
</span>


二、等待对话框后台处理 - 还是典型的事件加控件。。。。没时间整也没必要分层

<span style="font-size:14px;">using System;

using System.Linq;
using System.Text;
using System.Windows;
using System.Threading;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Runtime.InteropServices;

namespace DialogEx.Controls
{
/// <summary>
/// WaittingDlg.xaml 的交互逻辑
/// </summary>
public partial class WaittingDlg : Window
{
[DllImport("user32.dll")]
static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

//构造函数
public WaittingDlg(string sWaittingInfo = "", string sWindowColor = "", string sDlgBorderColor = "", int nBorderWidth = 5,int nWidth = 0,int nHeight = 0)
{
InitializeComponent();
if (nWidth != 0)
{
this.Width = nWidth;
}
if (nHeight != 0)
{
this.Height = nHeight;
}
this.sWaittingInfo = "请等待。。。";    //提示信息
this.sWindowColor = "White";                                        //窗口颜色
this.sDlgBorderColor = "#FF5B9BD1";                                 //边框颜色
this.nBorderWidth = 5;                                              //边框宽度
if (sWaittingInfo != "")
{
this.sWaittingInfo = sWaittingInfo;
}
if (sWindowColor != "")
{
this.sWindowColor = sWindowColor;
}
if (sDlgBorderColor != "")
{
this.sDlgBorderColor = sDlgBorderColor;
}
if (nBorderWidth > 0)
{
this.nBorderWidth = nBorderWidth;
}
this.Closing += new System.ComponentModel.CancelEventHandler(Window1_Closing);
}
//关闭事件
void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
this.Closing -= new System.ComponentModel.CancelEventHandler(Window1_Closing);
IntPtr handle = (new System.Windows.Interop.WindowInteropHelper(this)).Handle;
IntPtr ownerhandle = (new System.Windows.Interop.WindowInteropHelper(this.Owner)).Handle;
EnableWindow(handle, false);
EnableWindow(ownerhandle, true);
}
//初始化完成
private void Window_Loaded(object sender, RoutedEventArgs e)
{
IntPtr handle = (new System.Windows.Interop.WindowInteropHelper(this)).Handle;
EnableWindow(handle, true);
SetForegroundWindow(handle);
this.AutoChangeSize();
}
//等待提示信息
public string sWaittingInfo
{
set
{
txtWaittingInfo.Text = value;
}
get
{
return txtWaittingInfo.Text.ToString().Trim();
}
}
//窗口背景 Img
public string sWindowBkImg
{
set
{
Uri uri = new Uri(value, UriKind.RelativeOrAbsolute);
BitmapImage bimg = new BitmapImage(uri);
this.Background = new ImageBrush(bimg);
}
}
//窗口背景颜色 String
public string sWindowColor
{
/***********用法*******
* sWindowColor = "Red";
*********************/
set
{
this.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value));
}
}
//窗口背景颜色 Color
public Color cWindowColor
{
/***********用法*******
* cWindowColor = System.Windows.Media.Colors.Red;
*********************/
set
{
bDlgBorder.BorderBrush = new SolidColorBrush(value);
}
}
//边框颜色 String
public string sDlgBorderColor
{
/***********用法*******
* sDlgBorderColor = "Red";
*********************/
set
{
bDlgBorder.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value));
}
}
//边框颜色 Color
public Color cDlgBorderColor
{
/***********用法*******
* cDlgBorderColor = System.Windows.Media.Colors.Red;
*********************/
set
{
bDlgBorder.BorderBrush = new SolidColorBrush(value);
}
}
//边框宽度
public int nBorderWidth
{
set
{
bDlgBorder.BorderThickness = new Thickness(value);
}
}
//自动调整文本上下居中
private void AutoChangeSize()
{
if (this.txtWaittingInfo.ActualHeight + 8 > this.ActualHeight)
{
this.txtWaittingInfo.SetValue(VerticalAlignmentProperty, VerticalAlignment.Top);
this.txtWaittingInfo.Margin = new Thickness(0, 2, 0, 0);
}
else
{
this.txtWaittingInfo.SetValue(VerticalAlignmentProperty,VerticalAlignment.Center);
}
}
}
}
</span>


三、等待对话框 Helper,这是封装好的调用方法而已。怎么调用再第四步

<span style="font-size:14px;color:#333333;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;

namespace DialogEx.Controls.ProcessWindow
{
public class WaittingDlgHelper
{
/// <summary>
/// 等待关闭时的回调
/// </summary>
public delegate void CloseWaitDialogCallBack();

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool bEnable);

private static WaittingDlg _WatitDlg;
private static CloseWaitDialogCallBack _CallBack;

/// <summary>
/// 是否已激活等待对话框
/// - 调用本Helper内部函数时不需要对此判断
/// - 仅对外部显示是否正在等待
/// </summary>
public static bool IsWaitAlive { get { return _WatitDlg != null; } }
/// <summary>
/// 显示等待对话框
/// </summary>
/// <param name="win"></param>
/// <param name="sWaittingInfo"></param>
/// <param name="sWindowColor"></param>
/// <param name="sDlgBorderColor"></param>
/// <param name="nBorderWidth"></param>
/// <param name="nWidth"></param>
/// <param name="nHeight"></param>
public static void ShowWaitDialog(Window win, string sWaittingInfo = "", string sWindowColor = "", string sDlgBorderColor = "", int nBorderWidth = 5, int nWidth = 0, int nHeight = 0)
{
win.Dispatcher.Invoke(new Action(() =>
{
if (_WatitDlg != null)
{
_WatitDlg.Close();
_WatitDlg = null;
}
IntPtr handle = (new System.Windows.Interop.WindowInteropHelper(win)).Handle;
_WatitDlg = new WaittingDlg(sWaittingInfo, sWindowColor, sDlgBorderColor, nBorderWidth, nWidth, nHeight);
_WatitDlg.Owner = win;
_WatitDlg.WindowStartupLocation = WindowStartupLocation.CenterOwner;
_WatitDlg.ShowInTaskbar = false;
WindowInteropHelper helper = new WindowInteropHelper(_WatitDlg);
EnableWindow(handle, false);
_WatitDlg.ShowDialog();
}));
}
/// <summary>
/// 关闭等待对话框
/// </summary>
/// <param name="win"></param>
public static void CloseWaitDialog(Window win)
{
win.Dispatcher.Invoke(new Action(() =>
{
if (_WatitDlg != null)
{
_WatitDlg.Close();
_WatitDlg = null;
}
if (_CallBack != null)
{
_CallBack();
}
}));
}
/// <summary>
/// 设置对话框内容
/// </summary>
/// <param name="win"></param>
/// <param name="strTitle"></param>
public static void SetWaitDialogTitle(Window win, string strTitle = "")
{
win.Dispatcher.Invoke(new Action(() =>
{
if (_WatitDlg != null)
{
if (strTitle != "")
{
_WatitDlg.sWaittingInfo = strTitle;
}
}
}));

}
/// <summary>
/// 设置关闭等待对话框回调 - 收到关闭通知即回调
/// </summary>
public static void SetWaitDialogCloseCallBack(CloseWaitDialogCallBack CallBackMethod)
{
_CallBack += CallBackMethod;
}
}
}</span><span style="color:#ff0000;">
</span>


四、 关于如何使用等待对话框 - 你必须懂得后台线程,或者线程。 本次仅以后台线程为例

<pre name="code" class="csharp">        <span style="font-size:14px;color:#333333;">//启动等待
private void OpenWaittingDialog_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker backWork = new BackgroundWorker()
{
WorkerReportsProgress = false,
WorkerSupportsCancellation = true
};
backWork.DoWork += backWork_DoWork;
backWork.RunWorkerCompleted += backWork_RunWorkerCompleted;
backWork.RunWorkerAsync();
WaittingDlgHelper.ShowWaitDialog(this,"请等待。。。");
}
//关闭等待
private void CloseWaittingDialog_Click(object sender, RoutedEventArgs e)
{
WaittingDlgHelper.CloseWaitDialog(this);
}
//正在执行
void backWork_DoWork(object sender, DoWorkEventArgs e)
{
System.Threading.Thread.Sleep(8000);
}
//执行完
void backWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBoxEx.Show(this, "提示", "等待完成",MessageBoxExButton.Ok,MessageBoxExImage.Information);
WaittingDlgHelper.CloseWaitDialog(this);
}</span>




五、关于等待对话框的回调事件 。 暂时以委托实现。可以用事件。。但是差别不大。。也没什么实际卵用

<span style="white-space:pre">	</span><span style="font-size:14px;color:#333333;">//注册等待对话框关闭通知事件
<span style="white-space:pre">	</span>WaittingDlgHelper.SetWaitDialogCloseCallBack(this.WaittCloseCallBack);

<span style="white-space:pre">	</span>//等待关闭回调
public void WaittCloseCallBack()
{
//你要在等待对话框关闭时执行的操作
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: