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

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

1.遮挡主窗体

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

 /// <summary>
/// 打开等待窗体线程
/// </summary>
public static void ShowWaitingForm(Window onwer) {
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (WaitingFormThread == null)
{
WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
WaitingFormThread.SetApartmentState(ApartmentState.STA);
WaitingFormThread.Start(d);
}
else {
CloseWaitingForm();
ShowWaitingForm(onwer);
}
}

2.跨线程访问

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

 /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setProgrssFormPercent(double d) {
if (cf != null) {
cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
Thread.Sleep();
}
}

3.注意事项

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

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

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows; namespace MyUserControlLibrary
{
public static class DialogWindowsManager
{
#region 属性 /// <summary>
/// 等待窗体处理线程
/// </summary>
static Thread WaitingFormThread;
/// <summary>
/// 进度条进程
/// </summary>
static Thread CircleProgressFormThread; /// <summary>
/// 等待进度条进程
/// </summary>
static Thread WaitingAndProgressFormThread; /// <summary>
/// 进度条窗体
/// </summary>
static CircleProgressForm cf;
/// <summary>
/// 等待进度条
/// </summary>
static WaitingAndProgressForm wpf;
#endregion #region 私有方法 /// <summary>
/// 打开等待窗体方法
/// </summary>
private static void showWaitingForm(object o)
{
double[] d = (double[])o;
WaitingForm wf = new WaitingForm();
wf.WindowStartupLocation = WindowStartupLocation.Manual;
wf.Top = d[];
wf.Left = d[];
wf.ShowDialog();
} /// <summary>
/// 打开进度条窗体方法
/// </summary>
/// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
private static void showCircleProgressForm(object o)
{
double[] d = (double[])o;
cf = new CircleProgressForm();
cf.WindowStartupLocation = WindowStartupLocation.Manual;
cf.Top = d[];
cf.Left = d[];
cf.ShowDialog();
} /// <summary>
/// 打开进度条窗体方法
/// </summary>
/// <param name="o">显示位置集合 double[] 0-Top 1-Left</param>
private static void showWaitingAndProgressForm(object o)
{
object[] m = (object[])o;
double[] d = (double[])m[];
wpf = new WaitingAndProgressForm();
wpf.MainControl.ShowType = (WaitAndProgressType)m[];
wpf.WindowStartupLocation = WindowStartupLocation.Manual;
wpf.Top = d[];
wpf.Left = d[];
wpf.ShowDialog();
} #endregion #region 公有方法 /// <summary>
/// 打开等待窗体线程
/// </summary>
public static void ShowWaitingForm(Window onwer) {
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (WaitingFormThread == null)
{
WaitingFormThread = new Thread(new ParameterizedThreadStart(showWaitingForm));
WaitingFormThread.SetApartmentState(ApartmentState.STA);
WaitingFormThread.Start(d);
}
else {
CloseWaitingForm();
ShowWaitingForm(onwer);
}
} /// <summary>
/// 关闭等待窗体线程
/// </summary>
public static void CloseWaitingForm()
{
WaitingFormThread.Abort();
WaitingFormThread.Join();
WaitingFormThread.DisableComObjectEagerCleanup();
WaitingFormThread = null;
} /// <summary>
/// 打开进度条窗体线程
/// </summary>
public static void ShowCircleProgressForm(Window onwer)
{
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
if (CircleProgressFormThread == null)
{
CircleProgressFormThread = new Thread(new ParameterizedThreadStart(showCircleProgressForm));
CircleProgressFormThread.SetApartmentState(ApartmentState.STA);
CircleProgressFormThread.Start(d);
Thread.Sleep();
}
else
{
CloseCircleProgressForm();
ShowCircleProgressForm(onwer);
}
} /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setProgrssFormPercent(double d) {
if (cf != null) {
cf.Dispatcher.BeginInvoke(new Action(() => { if (cf != null) { cf.setPercent(d); } }));
Thread.Sleep();
}
} /// <summary>
/// 关闭进度条窗体线程
/// </summary>
public static void CloseCircleProgressForm()
{
CircleProgressFormThread.Abort();
CircleProgressFormThread.Join();
CircleProgressFormThread.DisableComObjectEagerCleanup();
CircleProgressFormThread = null;
cf = null;
} /// <summary>
/// 打开等待进度条窗体线程
/// </summary>
public static void ShowWaitingAndProgressForm(Window onwer,WaitAndProgressType t)
{
object[] o = new object[];
double[] d = new double[];
d[] = onwer.Top + onwer.Height / - ;
d[] = onwer.Left + onwer.Width / - ;
o[] = d;
o[] = t;
if (WaitingAndProgressFormThread == null)
{
WaitingAndProgressFormThread = new Thread(new ParameterizedThreadStart(showWaitingAndProgressForm));
WaitingAndProgressFormThread.SetApartmentState(ApartmentState.STA);
WaitingAndProgressFormThread.Start(o);
Thread.Sleep();
}
else
{
CloseWaitingAndProgressForm();
ShowWaitingAndProgressForm(onwer,t);
}
} /// <summary>
/// 设置进度条百分比
/// </summary>
/// <param name="d">百分比</param>
public static void setWaitingAndProgressFormPercent(double d)
{
if (wpf != null)
{
wpf.Dispatcher.BeginInvoke(new Action(() => { if (wpf != null) { wpf.setPercent(d); } }));
Thread.Sleep();
}
} /// <summary>
/// 关闭等待进度条窗体线程
/// </summary>
public static void CloseWaitingAndProgressForm()
{
WaitingAndProgressFormThread.Abort();
WaitingAndProgressFormThread.Join();
WaitingAndProgressFormThread.DisableComObjectEagerCleanup();
WaitingAndProgressFormThread = null;
wpf = null;
} #endregion
}
}

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

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

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

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

  

WPF 利用子线程弹出子窗体的研究的更多相关文章

  1. WPF的WebBrowser屏蔽弹出脚本错误窗体

    WPF自带的WebBrowser在訪问一些有问题的网页时常常跳出非常多提示脚本错误的窗体, 可是WPF没有自带屏蔽这些窗体的方法或属性. 所以网上找来一使用反射的方法来屏蔽弹出脚本错误窗体的方法, 非 ...

  2. WPF 介绍一种在MVVM模式下弹出子窗体的方式

    主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...

  3. WPF 在MVVM模式下弹出子窗体的方式

    主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来 ...

  4. DevExpress第三方控件使用实例之ASPxPopupControl弹出子窗体

    弹出页面控件:ASPxPopupControl, <dxpc:ASPxPopupControl ID="popubCtr" runat="server" ...

  5. WPF:设置弹出子菜单的是否可用状态及效果

    需求: 设置弹出子菜单(二级)项仅首项可用,其他项均不可用:不可用是呈灰色效果. 注: 菜单项都是依据层级数据模板.具体格式如下: StackBlock{TextBlock{Image}.TextBl ...

  6. WPF FileFolderDialog 和弹出子窗口的一些问题

    摘要:本文主要是WPF中 FileFolderDialog的相关问题,补充了关于在父窗口弹出子窗口,以及子窗口的相关属性(Data Binding)和命令绑定(Delegate Command)问题, ...

  7. pyqt5对用qt designer设计的窗体实现弹出子窗口的示例

    pyqt5对用qt designer设计的窗体实现弹出子窗口的示例 脚本专栏 python 1. 用qt designer编写主窗体,窗体类型是MainWindow,空白窗口上一个按钮.并转换成mai ...

  8. 2016 系统设计第一期 (档案一)MVC bootstrap model弹出子页面

    通过bootstrap  弹出modal-dialog 子页面 ,例如我要弹出子页面:areaitem_sub_One.html. 具体步骤如下: 第一步:新建 areaitem_sub_One.ht ...

  9. fancybox 关闭弹出窗口 parent.$.fancybox.close(); 无反应 fancybox 关闭弹出窗口父页面自动刷新,弹出子窗口前后事件

    当我们在父页面使用 fancybox 弹出窗口后,如果想自己手动关闭,则可以 function Cancel() { parent.$.fancybox.close(); } 如果关闭没有反应,最好看 ...

随机推荐

  1. 《Programming WPF》翻译 第8章 1.动画基础

    原文:<Programming WPF>翻译 第8章 1.动画基础 动画包括在一段时间内改变用户界面的某些可见的特征,如它的大小.位置或颜色.你可以做到这一点,非常困难的通过创建一个tim ...

  2. 《Programming WPF》翻译 第3章 2.处理输入

    原文:<Programming WPF>翻译 第3章 2.处理输入 在Windows应用程序中,又3种基本的用户输入形式:鼠标.键盘和手写板.同时,还有一种更高级输入方式,其可能来自快捷键 ...

  3. Compound class names are not supported. Consider searching for one class name and filtering the results

    原文地址:http://stackoverflow.com/questions/20361643/compound-class-names-are-not-supported-consider-sea ...

  4. cf448D Multiplication Table

    D. Multiplication Table time limit per test 1 second memory limit per test 256 megabytes input stand ...

  5. WEB打印插件jatoolsPrinter

    为什么选择 jatoolsPrinter 免费版? 支持无预览直接打印 真正免费,不加水印,没有ip或域名限制,不限时间,兼容ie6+ 无须注册,下载即用 提供经过微软数字签名的cab自动安装包,安装 ...

  6. linux mysql密码破解一张图解释

  7. paip.输入法编程---智能动态上屏码儿长调整--.txt

    paip.输入法编程---智能动态上屏码儿长调整--.txt 作者Attilax ,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csd ...

  8. WPF-24:绘制正多边形

    一般来说绘制正N边形,使用Blend直接画出来就好.不过可能是博主受WInform影响比较大,比较喜欢使用画出来的图形.如果要绘制正N边形,前面的绘制五角星的公式可以通用的(http://blog.c ...

  9. C# -- 扩展方法的应用(Extension Methods)

    当你有下面这样一个需求的时候,扩展方法就会起到作用:在项目中,类A需要添加功能,我们想到的就是在类A中添加公共方法,这个显而易见肯定可以,但是由于某种原因,你不能修改类A本身的代码,但是确实又需要增加 ...

  10. Top 15 Tools To Make Animated GIFs From Images & Video

    Creating an animated GIF picture from photos or video with Adobe Photoshop is easy, but not everyone ...