WPF 利用子线程弹出子窗体的研究

简介: 原文:WPF 利用子线程弹出子窗体的研究  一般来说子线程都是用来处理数据的,主窗体用来实现展现,但是有些时候我们希望子窗体实现等待效果,遮挡主窗体并使主窗体逻辑正常进行,这个业务需求虽然不多,但是正好我们用到了,于是我打算把研究成果写在这了。
原文: WPF 利用子线程弹出子窗体的研究

  一般来说子线程都是用来处理数据的,主窗体用来实现展现,但是有些时候我们希望子窗体实现等待效果,遮挡主窗体并使主窗体逻辑正常进行,这个业务需求虽然不多,但是正好我们用到了,于是我打算把研究成果写在这了。稍后我会上传我的代码,包含测试程序以及之前两边博文谈到的控件,这里我还实现了一个类似雷达扫描的等待窗体,大家可以稍后查看。

  实际上这里只有两个难点需要处理,一个就是如何让子窗体遮挡主窗体并位于主窗体中间,另一个就是委托及跨线程访问UI界面。为了方便调用,我在这里写了一个静态的子线程窗体管理类DialogWindowsManager。

1.遮挡主窗体

  大家都知道,showDialog方法就是最好的遮挡效果,但是由于它是线程阻塞的,因此每当我们想到这里的时候会有一个误区,认为调用showDialog一定会阻塞前台界面,其实这里的阻塞只是阻塞调用方法所在的线程,并不是一定会阻塞主线程,因此在子线程中调用showDialog方法即可达到效果。实际测试时发现遮挡效果确实有了,可惜每次showDialog的时候窗体会满屏幕乱飞,好吧,最好的方法当然是设置onwer,不过我一直没尝试成功,因为主窗体与子窗体一直处于两个线程中,最后我通过一个算法将位置计算出来之后赋值给了子窗体。代码如下:

 1 /// <summary>
 2         /// 打开等待窗体线程
 3         /// </summary>
 4         public static void ShowWaitingForm(Window onwer) {
 5             double[] d = new double[2];
 6             d[0] = onwer.Top + onwer.Height / 2 - 50;
 7             d[1] = onwer.Left + onwer.Width / 2 - 50;
 8             if (WaitingFormThread == null)
 9             {
10                 WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
11                 WaitingFormThread.SetApartmentState(ApartmentState.STA);
12                 WaitingFormThread.Start(d);
13             }
14             else {
15                 CloseWaitingForm();
16                 ShowWaitingForm(onwer);
17             }
18         }
View Code

2.跨线程访问

  这里不得不说WPF还是很给力的,因为它提供了Dispatcher来获取当前要更新的线程,这里网上资料很多,我就不多做解释了,直接上代码:

 1 /// <summary>
 2         /// 设置进度条百分比
 3         /// </summary>
 4         /// <param name="d">百分比</param>
 5         public static void setProgrssFormPercent(double d) {
 6             if (cf != null) {
 7                 cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
 8                 Thread.Sleep(50);
 9             }
10         }
View Code

3.注意事项

  子线程也是UI线程,因此线程一定要设置为ApartmentState.STA状态。

完成的线程管理代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading;
  6 using System.Windows;
  7 
  8 namespace MyUserControlLibrary
  9 {
 10     public static class DialogWindowsManager
 11     {
 12         #region 属性
 13 
 14         /// <summary>
 15         /// 等待窗体处理线程
 16         /// </summary>
 17         static Thread WaitingFormThread;
 18         /// <summary>
 19         /// 进度条进程
 20         /// </summary>
 21         static Thread CircleProgressFormThread;
 22 
 23         /// <summary>
 24         /// 等待进度条进程
 25         /// </summary>
 26         static Thread WaitingAndProgressFormThread;
 27 
 28         /// <summary>
 29         /// 进度条窗体
 30         /// </summary>
 31         static CircleProgressForm cf;
 32         /// <summary>
 33         /// 等待进度条
 34         /// </summary>
 35         static WaitingAndProgressForm wpf;
 36         #endregion
 37 
 38         #region 私有方法
 39 
 40         /// <summary>
 41         /// 打开等待窗体方法
 42         /// </summary>
 43         private static void showWaitingForm(object o)
 44         {
 45             double[] d = (double[])o;
 46             WaitingForm wf = new WaitingForm();
 47             wf.WindowStartupLocation = WindowStartupLocation.Manual;
 48             wf.Top = d[0];
 49             wf.Left = d[1];
 50             wf.ShowDialog();
 51         }
 52 
 53         /// <summary>
 54         /// 打开进度条窗体方法
 55         /// </summary>
 56         /// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
 57         private static void showCircleProgressForm(object o)
 58         {
 59             double[] d = (double[])o;
 60             cf = new CircleProgressForm();
 61             cf.WindowStartupLocation = WindowStartupLocation.Manual;
 62             cf.Top = d[0];
 63             cf.Left = d[1];
 64             cf.ShowDialog();
 65         }
 66 
 67         /// <summary>
 68         /// 打开进度条窗体方法
 69         /// </summary>
 70         /// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
 71         private static void showWaitingAndProgressForm(object o)
 72         {
 73             object[] m = (object[])o;
 74             double[] d = (double[])m[0];
 75             wpf = new WaitingAndProgressForm();
 76             wpf.MainControl.ShowType = (WaitAndProgressType)m[1];
 77             wpf.WindowStartupLocation = WindowStartupLocation.Manual;
 78             wpf.Top = d[0];
 79             wpf.Left = d[1];
 80             wpf.ShowDialog();
 81         }
 82 
 83         #endregion
 84 
 85         #region 公有方法
 86 
 87         /// <summary>
 88         /// 打开等待窗体线程
 89         /// </summary>
 90         public static void ShowWaitingForm(Window onwer) {
 91             double[] d = new double[2];
 92             d[0] = onwer.Top + onwer.Height / 2 - 50;
 93             d[1] = onwer.Left + onwer.Width / 2 - 50;
 94             if (WaitingFormThread == null)
 95             {
 96                 WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
 97                 WaitingFormThread.SetApartmentState(ApartmentState.STA);
 98                 WaitingFormThread.Start(d);
 99             }
100             else {
101                 CloseWaitingForm();
102                 ShowWaitingForm(onwer);
103             }
104         }
105 
106         /// <summary>
107         /// 关闭等待窗体线程
108         /// </summary>
109         public static void CloseWaitingForm()
110         {
111             WaitingFormThread.Abort();
112             WaitingFormThread.Join();
113             WaitingFormThread.DisableComObjectEagerCleanup();
114             WaitingFormThread = null;
115         }
116 
117         /// <summary>
118         /// 打开进度条窗体线程
119         /// </summary>
120         public static void ShowCircleProgressForm(Window onwer)
121         {
122             double[] d = new double[2];
123             d[0] = onwer.Top + onwer.Height / 2 - 50;
124             d[1] = onwer.Left + onwer.Width / 2 - 50;
125             if (CircleProgressFormThread == null)
126             {
127                 CircleProgressFormThread = new Thread(new ParameterizedThreadStart(showCircleProgressForm));
128                 CircleProgressFormThread.SetApartmentState(ApartmentState.STA);
129                 CircleProgressFormThread.Start(d);
130                 Thread.Sleep(100);
131             }
132             else
133             {
134                 CloseCircleProgressForm();
135                 ShowCircleProgressForm(onwer);
136             }
137         }
138 
139         /// <summary>
140         /// 设置进度条百分比
141         /// </summary>
142         /// <param name="d">百分比</param>
143         public static void setProgrssFormPercent(double d) {
144             if (cf != null) {
145                 cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
146                 Thread.Sleep(50);
147             }
148         }
149 
150         /// <summary>
151         /// 关闭进度条窗体线程
152         /// </summary>
153         public static void CloseCircleProgressForm()
154         {
155             CircleProgressFormThread.Abort();
156             CircleProgressFormThread.Join();
157             CircleProgressFormThread.DisableComObjectEagerCleanup();
158             CircleProgressFormThread = null;
159             cf = null;
160         }
161 
162         /// <summary>
163         /// 打开等待进度条窗体线程
164         /// </summary>
165         public static void ShowWaitingAndProgressForm(Window onwer,WaitAndProgressType t)
166         {
167             object[] o = new object[2];
168             double[] d = new double[2];
169             d[0] = onwer.Top + onwer.Height / 2 - 50;
170             d[1] = onwer.Left + onwer.Width / 2 - 50;
171             o[0] = d;
172             o[1] = t;
173             if (WaitingAndProgressFormThread == null)
174             {
175                 WaitingAndProgressFormThread = new Thread(new ParameterizedThreadStart(showWaitingAndProgressForm));
176                 WaitingAndProgressFormThread.SetApartmentState(ApartmentState.STA);
177                 WaitingAndProgressFormThread.Start(o);
178                 Thread.Sleep(100);
179             }
180             else
181             {
182                 CloseWaitingAndProgressForm();
183                 ShowWaitingAndProgressForm(onwer,t);
184             }
185         }
186 
187         /// <summary>
188         /// 设置进度条百分比
189         /// </summary>
190         /// <param name="d">百分比</param>
191         public static void setWaitingAndProgressFormPercent(double d)
192         {
193             if (wpf != null)
194             {
195                 wpf.Dispatcher.BeginInvoke(new Action(() => { if (wpf != null) { wpf.setPercent(d); } }));
196                 Thread.Sleep(50);
197             }
198         }
199 
200         /// <summary>
201         /// 关闭等待进度条窗体线程
202         /// </summary>
203         public static void CloseWaitingAndProgressForm()
204         {
205             WaitingAndProgressFormThread.Abort();
206             WaitingAndProgressFormThread.Join();
207             WaitingAndProgressFormThread.DisableComObjectEagerCleanup();
208             WaitingAndProgressFormThread = null;
209             wpf = null;
210         }
211 
212         #endregion
213     }
214 }
View Code

整个解决方案我会上传的!!

如果喜欢我的文章可以粉我!!!

 

本文系本人原创,源代码及文章引用转载请注明出处!!谢谢!

源码下载地址:http://files.cnblogs.com/files/lgmbk/UserControlTest.zip

  

目录
相关文章
|
监控 C# C++
VS+C#+WPF多线程视频摄像头播放器监控
VS+C#+WPF多线程视频摄像头播放器监控
322 0
VS+C#+WPF多线程视频摄像头播放器监控
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
242 0
|
C# 容器
WPF框架下,窗体的嵌套显示
WPF框架下,窗体的嵌套显示
226 0
|
C#
WPF异常捕获三种处理 UI线程, 全局异常,Task异常
原文:WPF异常捕获三种处理 UI线程, 全局异常,Task异常 protected override void OnStartup(StartupEventArgs e){base.OnStartup(e);RegisterEvents();} private void RegisterEvents(){//TaskScheduler.
2537 0
|
存储 算法
Emgu-WPF 激光雷达研究-定位实现
原文:Emgu-WPF 激光雷达研究-定位实现 特定位置或障碍物位置定位实现。 读取激光雷达数据并存储于本地作为测试数据。
888 0
|
算法 测试技术
Emgu-WPF 激光雷达研究-移动物体跟踪
原文:Emgu-WPF 激光雷达研究-移动物体跟踪 接前两篇博客: 激光雷达数据解析并绘制雷达图 https://blog.
984 0
|
算法
Emgu-WPF 激光雷达研究-移动物体跟踪2
原文:Emgu-WPF 激光雷达研究-移动物体跟踪2 初步实现了去燥跟踪,并用圆点标注障碍物 https://blog.csdn.net/u013224722/article/details/80780205 测试过程中发现,当存在两个障碍物相对于雷达扫描射线重叠时,距离教远的障碍物信息会丢失。
853 0
|
传感器
Emgu-WPF 激光雷达研究-绘制雷达图
原文:Emgu-WPF 激光雷达研究-绘制雷达图 硬件:Hokuyo URG04LX 环境:VS2017- win10- 64  Emgu_3.
1048 0
Emgu-WPF 激光雷达研究-移动物体检测
原文:Emgu-WPF 激光雷达研究-移动物体检测 接上篇: https://blog.csdn.net/u013224722/article/details/80738619 先pose出效果图,下次撰写思路。
1026 0
|
C#
WPF 透明窗体
原文:WPF 透明窗体 窗体属性中设置:Background="Transparent" AllowsTransparency="True" WindowStyle="None"注:单独设置 Background="Transparent" 窗体默认显示为黑色。
1062 0