Winform ShowDialog如何让先前Show的窗体可以交互
背景描述
最近项目中有一个需求,全局有一个共用的窗体,能够打开不同模块的报告,由于需要兼容不同模块,代码复杂,启动速度慢。优化方案为将窗体启动时就创建好,需要查看报告时,使用此单例弹窗加载不同模块下的报告。
原项目模块是通过在主框架(Form1)下加载不同Tab页实现的,因此查看报告弹窗(Form2)是非模态Show出来。后来业务要求新加入一个模块,模块页面是通过模态方式呈现(Form3),即ShowDialog的方式。
这就有一个问题,如果用户在Form1下先打开Form2,然后又需要在Form3下打开Form2,此时Form2是无法操作的。如下:
解决思路
这个问题和winform设计有关,只能去看看winform源代码是如何区别处理Show和ShowDialog。


1 public void Show(IWin32Window owner)
2 {
3 if (owner == this)
4 {
5 throw new InvalidOperationException(SR.GetString("OwnsSelfOrOwner", "Show"));
6 }
7
8 if (base.Visible)
9 {
10 throw new InvalidOperationException(SR.GetString("ShowDialogOnVisible", "Show"));
11 }
12
13 if (!base.Enabled)
14 {
15 throw new InvalidOperationException(SR.GetString("ShowDialogOnDisabled", "Show"));
16 }
17
18 if (!TopLevel)
19 {
20 throw new InvalidOperationException(SR.GetString("ShowDialogOnNonTopLevel", "Show"));
21 }
22
23 if (!SystemInformation.UserInteractive)
24 {
25 throw new InvalidOperationException(SR.GetString("CantShowModalOnNonInteractive"));
26 }
27
28 if (owner != null && ((int)UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, Control.GetSafeHandle(owner)), -20) & 8) == 0 && owner is Control)
29 {
30 owner = ((Control)owner).TopLevelControlInternal;
31 }
32
33 IntPtr activeWindow = UnsafeNativeMethods.GetActiveWindow();
34 IntPtr intPtr = (owner == null) ? activeWindow : Control.GetSafeHandle(owner);
35 IntPtr zero = IntPtr.Zero;
36 base.Properties.SetObject(PropDialogOwner, owner);
37 Form ownerInternal = OwnerInternal;
38 if (owner is Form && owner != ownerInternal)
39 {
40 Owner = (Form)owner;
41 }
42
43 if (intPtr != IntPtr.Zero && intPtr != base.Handle)
44 {
45 if (UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, intPtr), -8) == base.Handle)
46 {
47 throw new ArgumentException(SR.GetString("OwnsSelfOrOwner", "show"), "owner");
48 }
49
50 zero = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, base.Handle), -8);
51 UnsafeNativeMethods.SetWindowLong(new HandleRef(this, base.Handle), -8, new HandleRef(owner, intPtr));
52 }
53
54 base.Visible = true;
55 }


1 public DialogResult ShowDialog(IWin32Window owner)
2 {
3 if (owner == this)
4 {
5 throw new ArgumentException(SR.GetString("OwnsSelfOrOwner", "showDialog"), "owner");
6 }
7
8 if (base.Visible)
9 {
10 throw new InvalidOperationException(SR.GetString("ShowDialogOnVisible", "showDialog"));
11 }
12
13 if (!base.Enabled)
14 {
15 throw new InvalidOperationException(SR.GetString("ShowDialogOnDisabled", "showDialog"));
16 }
17
18 if (!TopLevel)
19 {
20 throw new InvalidOperationException(SR.GetString("ShowDialogOnNonTopLevel", "showDialog"));
21 }
22
23 if (Modal)
24 {
25 throw new InvalidOperationException(SR.GetString("ShowDialogOnModal", "showDialog"));
26 }
27
28 if (!SystemInformation.UserInteractive)
29 {
30 throw new InvalidOperationException(SR.GetString("CantShowModalOnNonInteractive"));
31 }
32
33 if (owner != null && ((int)UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, Control.GetSafeHandle(owner)), -20) & 8) == 0 && owner is Control)
34 {
35 owner = ((Control)owner).TopLevelControlInternal;
36 }
37
38 CalledOnLoad = false;
39 CalledMakeVisible = false;
40 CloseReason = CloseReason.None;
41 IntPtr capture = UnsafeNativeMethods.GetCapture();
42 if (capture != IntPtr.Zero)
43 {
44 UnsafeNativeMethods.SendMessage(new HandleRef(null, capture), 31, IntPtr.Zero, IntPtr.Zero);
45 SafeNativeMethods.ReleaseCapture();
46 }
47
48 IntPtr intPtr = UnsafeNativeMethods.GetActiveWindow();
49 IntPtr intPtr2 = (owner == null) ? intPtr : Control.GetSafeHandle(owner);
50 IntPtr zero = IntPtr.Zero;
51 base.Properties.SetObject(PropDialogOwner, owner);
52 Form ownerInternal = OwnerInternal;
53 if (owner is Form && owner != ownerInternal)
54 {
55 Owner = (Form)owner;
56 }
57
58 try
59 {
60 SetState(32, value: true);
61 dialogResult = DialogResult.None;
62 CreateControl();
63 if (intPtr2 != IntPtr.Zero && intPtr2 != base.Handle)
64 {
65 if (UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, intPtr2), -8) == base.Handle)
66 {
67 throw new ArgumentException(SR.GetString("OwnsSelfOrOwner", "showDialog"), "owner");
68 }
69
70 zero = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, base.Handle), -8);
71 UnsafeNativeMethods.SetWindowLong(new HandleRef(this, base.Handle), -8, new HandleRef(owner, intPtr2));
72 }
73
74 try
75 {
76 if (dialogResult == DialogResult.None)
77 {
78 Application.RunDialog(this);
79 }
80 }
81 finally
82 {
83 if (!UnsafeNativeMethods.IsWindow(new HandleRef(null, intPtr)))
84 {
85 intPtr = intPtr2;
86 }
87
88 if (UnsafeNativeMethods.IsWindow(new HandleRef(null, intPtr)) && SafeNativeMethods.IsWindowVisible(new HandleRef(null, intPtr)))
89 {
90 UnsafeNativeMethods.SetActiveWindow(new HandleRef(null, intPtr));
91 }
92 else if (UnsafeNativeMethods.IsWindow(new HandleRef(null, intPtr2)) && SafeNativeMethods.IsWindowVisible(new HandleRef(null, intPtr2)))
93 {
94 UnsafeNativeMethods.SetActiveWindow(new HandleRef(null, intPtr2));
95 }
96
97 SetVisibleCore(value: false);
98 if (base.IsHandleCreated)
99 {
100 if (OwnerInternal != null && OwnerInternal.IsMdiContainer)
101 {
102 OwnerInternal.Invalidate(invalidateChildren: true);
103 OwnerInternal.Update();
104 }
105
106 DestroyHandle();
107 }
108
109 SetState(32, value: false);
110 }
111 }
112 finally
113 {
114 Owner = ownerInternal;
115 base.Properties.SetObject(PropDialogOwner, null);
116 }
117
118 return DialogResult;
119 }
1 if (dialogResult == DialogResult.None)
2 {
3 Application.RunDialog(this);
4 }
1 internal static void RunDialog(Form form)
2 {
3 Application.ThreadContext.FromCurrent().RunMessageLoop(4, new Application.ModalApplicationContext(form));
4 }
1 internal void RunMessageLoop(int reason, ApplicationContext context)
2 {
3 IntPtr userCookie = IntPtr.Zero;
4 if (Application.useVisualStyles)
5 {
6 userCookie = UnsafeNativeMethods.ThemingScope.Activate();
7 }
8 try
9 {
10 this.RunMessageLoopInner(reason, context);
11 }
12 finally
13 {
14 UnsafeNativeMethods.ThemingScope.Deactivate(userCookie);
15 }
16 }


1 private void RunMessageLoopInner(int reason, ApplicationContext context)
2 {
3 if (reason == 4 && !SystemInformation.UserInteractive)
4 {
5 throw new InvalidOperationException(SR.GetString("CantShowModalOnNonInteractive"));
6 }
7 if (reason == -1)
8 {
9 this.SetState(8, false);
10 }
11 if (Application.ThreadContext.totalMessageLoopCount++ == 0)
12 {
13 Application.ThreadContext.baseLoopReason = reason;
14 }
15 this.messageLoopCount++;
16 if (reason == -1)
17 {
18 if (this.messageLoopCount != 1)
19 {
20 throw new InvalidOperationException(SR.GetString("CantNestMessageLoops"));
21 }
22 this.applicationContext = context;
23 this.applicationContext.ThreadExit += this.OnAppThreadExit;
24 if (this.applicationContext.MainForm != null)
25 {
26 this.applicationContext.MainForm.Visible = true;
27 }
28 DpiHelper.InitializeDpiHelperForWinforms();
29 AccessibilityImprovements.ValidateLevels();
30 }
31 Form form = this.currentForm;
32 if (context != null)
33 {
34 this.currentForm = context.MainForm;
35 }
36 bool flag = false;
37 bool flag2 = false;
38 HandleRef hWnd = new HandleRef(null, IntPtr.Zero);
39 if (reason == -2)
40 {
41 flag2 = true;
42 }
43 if (reason == 4 || reason == 5)
44 {
45 flag = true;
46 bool flag3 = this.currentForm != null && this.currentForm.Enabled;
47 this.BeginModalMessageLoop(context);
48 hWnd = new HandleRef(null, UnsafeNativeMethods.GetWindowLong(new HandleRef(this.currentForm, this.currentForm.Handle), -8));
49 if (hWnd.Handle != IntPtr.Zero)
50 {
51 if (SafeNativeMethods.IsWindowEnabled(hWnd))
52 {
53 SafeNativeMethods.EnableWindow(hWnd, false);
54 }
55 else
56 {
57 hWnd = new HandleRef(null, IntPtr.Zero);
58 }
59 }
60 if (this.currentForm != null && this.currentForm.IsHandleCreated && SafeNativeMethods.IsWindowEnabled(new HandleRef(this.currentForm, this.currentForm.Handle)) != flag3)
61 {
62 SafeNativeMethods.EnableWindow(new HandleRef(this.currentForm, this.currentForm.Handle), flag3);
63 }
64 }
65 try
66 {
67 if (this.messageLoopCount == 1)
68 {
69 WindowsFormsSynchronizationContext.InstallIfNeeded();
70 }
71 if (flag && this.currentForm != null)
72 {
73 this.currentForm.Visible = true;
74 }
75 if ((!flag && !flag2) || this.ComponentManager is Application.ComponentManager)
76 {
77 bool flag4 = this.ComponentManager.FPushMessageLoop((IntPtr)this.componentID, reason, 0);
78 }
79 else if (reason == 2 || reason == -2)
80 {
81 bool flag4 = this.LocalModalMessageLoop(null);
82 }
83 else
84 {
85 bool flag4 = this.LocalModalMessageLoop(this.currentForm);
86 }
87 }
88 finally
89 {
90 if (flag)
91 {
92 this.EndModalMessageLoop(context);
93 if (hWnd.Handle != IntPtr.Zero)
94 {
95 SafeNativeMethods.EnableWindow(hWnd, true);
96 }
97 }
98 this.currentForm = form;
99 Application.ThreadContext.totalMessageLoopCount--;
100 this.messageLoopCount--;
101 if (this.messageLoopCount == 0)
102 {
103 WindowsFormsSynchronizationContext.Uninstall(false);
104 }
105 if (reason == -1)
106 {
107 this.Dispose(true);
108 }
109 else if (this.messageLoopCount == 0 && this.componentManager != null)
110 {
111 this.RevokeComponent();
112 }
113 }
114 }
1 if (reason == 4 || reason == 5)
2 {
3 flag = true;
4 bool flag3 = this.currentForm != null && this.currentForm.Enabled;
5 this.BeginModalMessageLoop(context);
6 hWnd = new HandleRef(null, UnsafeNativeMethods.GetWindowLong(new HandleRef(this.currentForm, this.currentForm.Handle), -8));
7 if (hWnd.Handle != IntPtr.Zero)
8 {
9 if (SafeNativeMethods.IsWindowEnabled(hWnd))
10 {
11 SafeNativeMethods.EnableWindow(hWnd, false);
12 }
13 else
14 {
15 hWnd = new HandleRef(null, IntPtr.Zero);
16 }
17 }
18 if (this.currentForm != null && this.currentForm.IsHandleCreated && SafeNativeMethods.IsWindowEnabled(new HandleRef(this.currentForm, this.currentForm.Handle)) != flag3)
19 {
20 SafeNativeMethods.EnableWindow(new HandleRef(this.currentForm, this.currentForm.Handle), flag3);
21 }
22 }
1 private void btnOpenOldForm_Click(object sender, EventArgs e)
2 {
3 OldFrom.Hide();
4 OldFrom.Show(this);
5 OldFrom.BringToFront();
6 var formhandle = OldFrom.Handle;
7 NativeMethodHelper.EnableWindow(new HandleRef(null, formhandle), true);
8 }
1 public class NativeMethodHelper
2 {
3 [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
4 public static extern IntPtr SetActiveWindow(HandleRef hWnd);
5
6 [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowLongPtr")]
7 public static extern IntPtr GetWindowLongPtr64(HandleRef hWnd, int nIndex);
8
9 public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLong)
10 {
11 if (IntPtr.Size == 4)
12 {
13 return NativeMethodHelper.SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
14 }
15 return NativeMethodHelper.SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
16 }
17 [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]
18 public static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, HandleRef dwNewLong);
19
20 [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]
21 public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, HandleRef dwNewLong);
22
23 /// <summary>
24 /// 启用窗体
25 /// </summary>
26 /// <param name="hWnd"></param>
27 /// <param name="enable"></param>
28 /// <returns></returns>
29 [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
30 public static extern bool EnableWindow(HandleRef hWnd, bool enable);
31 }
Winform ShowDialog如何让先前Show的窗体可以交互的更多相关文章
- WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)
最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...
- [WinForm] 使用反射将业务对象绑定到窗体或控件容器
在WebForm中,可以使用反射将业务对象绑定到 ASP.NET 窗体控件.最近做Winform项目,也参考WebForm中的代码实现同样的功能. Winform没有提供类似WebForm中的 ...
- WinForm 之 程序启动不显示主窗体
在 WinForm 程序启动时,不显示主窗体的实现方法主要有以下5种,第五种最简单,而且效果也不错,第四种方法也值得推荐. 实例代码如下: //隐藏窗体的方法1/5:不指定任何窗体为主窗体 //注意: ...
- Winform中怎样根据Name获取同窗体的控件
场景 在同一个Winform窗体中,点击一个Button按钮时, 获取同窗体的其他控件的属性. 首先需要对要获取的控件赋予Name属性,然后就可以通过Name进行获取. 实现 在Button的点击事件 ...
- Winform 在高分变率显示器中窗体变模糊配置方式
我们知道 Winform 前身与 XP 系统 同一时代出生 , 那时候显示器还是LCD 和 大头机 ,显示器普遍 96 DPI . 随着显示器质量改善,2K 屏, 4K屏普及,DPI 达 19 ...
- winform下自绘提示框风格窗体
昨天分享了一个环形滚动条控件,今天分享一个提示框风格的窗体.代码如下: /// <summary> /// 继承自Form,但将FormBorderStyle设置为None /// < ...
- win7 C# winForm编程 savefiledialog 不能弹出保存窗体
public void ResMsg() { while (isRecMsg) { //准备一个数组 准备接收 ...
- winform showDialog() 退出问题
今日发现: 当返回值为Dialog.OK时,会自动退出,不需要this.close().别的返回值仍需要.
- 浅谈delphi创建Windows服务程序与窗体实现交互
我想实现的功能是创建一个服务程序,然后在服务Start时动态创建一个窗体Form,然后把Form缩小时变成TrayIcon放在Windows托盘上. 我在服务程序的OnStart事件中写到 Start ...
- LayUI 子父窗体的交互
---恢复内容开始--- 收到的工作是将一个ERP的窗体程序改为网页实现,所以就肯定需要弹框来选择(如:物料编码.部门.业务员等等) 本文采取的前段框架是LayUI. layUI的官网API网址:ht ...
随机推荐
- 某开源ERP最新版SQL与RCE的审计过程
文章首发于 https://forum.butian.net/share/134 前言 代码路径 https://gitee.com/jishenghua/JSH_ERP 软件版本 华夏ERP_v2. ...
- 【Amadeus原创】从域副域控无法同步的解决方法
强制同步指令:repadmin /syncall /force 同步查询:repadmin.exe /replsummary
- COSBrowser文件编辑-随时随地在线编辑
本文介绍如何通过COSBrowser文件在线编辑功能更方便的使用云上存储的数据. 痛点分析 日常工作和生活中,我们需要把记录的文档.编写的文案.音视频文件保存管理好,又担心设备损坏.文件丢失或是更换设 ...
- ng-alain: 配置开发环境
配置 ng-alain 开发环境 安装 1. Yarn 官方文档实际上是基于 Yarn 1 的,请从 Yarn 1 开始.在创建项目之后,可以升级到 Yarn 3. 注意:直接通过 npm 安装 ya ...
- opencv+Linux源码编译安装及引用
(一)下载 opencv下载地址:https://opencv.org/releases/ opencv_contrib下载地址:https://github.com/opencv/opencv_co ...
- MatLab R2023a 安装激活
解压 下载压缩包后解压得到以下内容: Setup文件夹里面存放的是 安装包,用于安装MatLab Crack文件夹里面存放的是 激活文件,包括libmwlmgrimpl.dll,license.lic ...
- Argo CD使用CLI工具修改默认密码
查看默认密码 kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}&q ...
- TB交易开拓者_趋势跟踪策略_多品种对冲_递进优化回测_A0001188020期货量化策略
如果您需要代写技术指标公式, 请联系我. 龙哥QQ:591438821 龙哥微信:Long622889 也可以把您的通达信,文华技术指标改成TB交易开拓者的自动交易量化策略. 众所周知,投资界有基本面 ...
- Qt编写视频监控管理平台(支持海康/大华/宇视/华为/天地伟业/H264/H265等)
一.前言 海康大华等厂家自己的客户端软件,基本上都是支持自家的设备,不支持其他家的摄像机和硬盘录像机,并不是因为技术上做不到,这些大厂要实现支持兼容其他的家的(他们家的服务端或者收费的都是支持其他家的 ...
- Qt数据库应用15-通用数据库同步
一.前言 数据库同步的主要功能是将本地的数据库记录同步到远程的数据库,其中数据库类型不限,比如本地是sqlite数据库,远程可以是mysql数据库,本地是mysql数据库,远程也可以是postgres ...