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

  实际上这里只有两个难点需要处理,一个就是如何让子窗体遮挡主窗体并位于主窗体中间,另一个就是委托及跨线程访问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. 缓存一致性(Cache Coherency)入门(转)

    参考原文:http://fgiesen.wordpress.com/2014/07/07/cache-coherency/ 本文是RAD Game Tools程序员Fabian “ryg” Giese ...

  2. Linux下串口编程入门

    简介: Linux操作系统从一开始就对串行口提供了很好的支持,本文就Linux下的串行口通讯编程进行简单的介绍. 串口简介  串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用 ...

  3. Integer to English Words 解答

    Question Convert a non-negative integer to its english words representation. Given input is guarante ...

  4. mysqldump命令详解(转载)

    1.简介 mysqldump为MySQL逻辑备份工具,产生一系列SQL语句,之后重新执行以产生备份的库.表及数据.也可产生CSV.XML等格式的数据.适用于各类引擎的表. 运行mysqldump需一定 ...

  5. 《Java程序员面试笔试宝典》之Java变量命名有哪些规则

    在Java语言中,变量名.函数名.数组名统称为标识符,Java语言规定标识符只能由字母(a~z,A~Z).数字(0~9).下划线(_)和$组成,并且标识符的第一个字符必须是字母.下划线或$.此外,标识 ...

  6. nyoj 234 吃土豆

    描述 Bean-eating * grid. Now you want to eat the beans and collect the qualities, but everyone must ob ...

  7. qt绘制设备

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import  * from Py ...

  8. 第十四个目标(dp + 树状数组 + 线段树)

    Problem 2236 第十四个目标 Accept: 17    Submit: 35 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Probl ...

  9. [转]Laravel 4之控制器

    Laravel 4之控制器 http://dingjiannan.com/2013/laravel-controller/ 控制器 通常Laravel控制器文件放在app/controllers/目录 ...

  10. js控制html5 audio的暂停、播放、停止

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta name ...