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

  实际上这里只有两个难点需要处理,一个就是如何让子窗体遮挡主窗体并位于主窗体中间,另一个就是委托及跨线程访问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. 使用ownCloud搭建你的个人云服务(ubuntu 14.04 server)(ownCloud对文件不切片,Seafile对文件切片),owncloud没有存储的功能 只能同步 本地删除了服务器也会删除

    ownCloud是什么 ownCloud是一个自由且开源的个人云存储解决方案(类似百度网盘或者Dropbox),包括两个部分:服务器和客户端. ownCloud在客户端可通过网页界面,或者安装专用的客 ...

  2. 【转】gcc warning: braces around scalar initializer (标量初始化的括号)

    原文网址:http://stackoverflow.com/questions/3462513/gcc-warning-braces-around-scalar-initializer I have ...

  3. Spring MVC Controller 单元测试

    简介 Controller层的单元测试可以使得应用的可靠性得到提升,虽然这使得开发的时间有所增加,有得必失,这里我认为得到的比失去的多很多. Sping MVC3.2版本之后的单元测试方法有所变化,随 ...

  4. voijs1883 月光的魔法

    背景 影几欺哄了众生了天以外——月儿何曾圆缺 描述 有些东西就如同月光的魔法一般. Luke是爱着vijos的.他想为自己心爱的东西画些什么. 就画N个圆吧.把它们的圆心都固定在x轴上. 圆与圆.为了 ...

  5. c++ 04

    一.this指针 1. 2.应用场景 1) 2)将this指针作为函数的参数.一个对象可以通知另一个对象有关自身的地址.    教师 提问|^     V|答案    学生 交叉类问题: class ...

  6. 【shell】构造并遍历二位数组的一种用法

    参考shell数组的部分操作用法,实现了构造和遍历二维数组的一种方式,具体如下: #数组元素以空格分割 sites=("www.a.com www.b.com www.c.com www.d ...

  7. windows media player 中播放pls的方法

    windows media player目前只能播放 wpl 和 asm格式的列表文件.而linux下mplayer和vlc支持的pls,很遗憾没法支持. 不过,老外写了个“open pls in w ...

  8. xmind教程

    xmind是什么东西我不多说.作为一个程序员,我通常用来编写一个文档.比如某个模块的设计或者流程图. 一开始我是以word画图的方式来用xmind的,即想要什么图形,就去插入里面找.结果碰了一鼻子灰, ...

  9. [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍

    阅读<Java并发编程实践>一书后整理的思维导图.

  10. Mysql 分别按月, 日为组group,进行统计排序order

    在数据库中我们经经常使用sql语句对表进行简单的统计排序,对于日期字段.我们能够简单的对其进行order. 对于复杂一点的能够按日期中的年.月,日分别进行group,order. 按年份进行group ...