C#的Winform的Form,只锁住父亲窗口的方法。

C#的Winform的Form,只锁住父亲窗口的方法。

C#的Winform的Form用Show和ShowDialog两种不同的显示方法。
ShowDialog会锁住自己以外的所有窗口。如果有多个窗口时,都需等待子窗口关闭后才能用。
研究了一下只锁自己父亲窗口的方法,共参考。

背景

给工厂做的系统,其中有一个流水线的画面,基本功能是扫描产品的条形码,
凑齐个数后按登录按钮时会弹出再次确认窗口,按确认后数据被登录,画面清零。
本来功能很简单,没啥可聊的,但系统上线时问题来了。
现场地方狭小,放不了很多电脑,厂家也想节约成本,
最后硬件配置变成,一台PC供6个流水线使用。
成为:1PC + 6扫描枪 + 6触摸屏
触摸屏从高空悬挂,空间问题得以解决。

PC里启动一个应用,开6个窗口,拖放到各个屏幕,基本的使用没问题。
但是最后的再次确认窗口是ShowDialog显示的,
一个人显示了确认窗口其他五人就啥也干不了了。

有下面2个方案可以解决

  1. 分成6个应用启动,大家互不干扰。
  2. 不用ShowDialog,找方法只锁自己父亲窗口。

方案1立刻被否决了,因为分开应用后扫描枪的COM端口配置要一一配置后期维护繁琐。

于是就方案2了,主要技术点有2个。
Form.Owner // 设置父子关系,是孩子窗口永远在上。
Form.Activated // 父亲窗口被激活时,立刻激活子窗口,以免父亲窗口的按钮被按。

下面是代码。

管理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class NonModalDialog
{
Form owner {get;set;}
Form child { get; set; }
Action closingAction { get; set; }
public NonModalDialog( Form owner ,Form child,Action closingAction=null)
{
this.owner = owner;
this.child = child;
this.closingAction = closingAction;

this.child.Owner = this.owner; // 设置父子关系,是孩子窗口永远在上。

this.owner.Activated += owner_Activated;
this.child.FormClosed += child_FormClosed;

this.child.StartPosition = FormStartPosition.Manual;
this.child.Location = new Point(
this.owner.Location.X + (this.owner.Width - this.child.Width) / 2,
this.owner.Location.Y + (this.owner.Height - this.child.Height) / 2
);
}

void child_FormClosed(object sender, FormClosedEventArgs e)
{
if (null != this.child && null != this.closingAction)
{
this.child.Owner = null;
this.child = null;
this.closingAction();
}
}

void owner_Activated(object sender, EventArgs e)
{
var ls = this.owner.OwnedForms;
foreach (var item in ls)
{
item.Activate();// 父亲窗口被激活时,立刻激活子窗口,以免父亲窗口的按钮被按。
item.Location = new Point(
this.owner.Location.X + (this.owner.Width - item.Width) / 2,
this.owner.Location.Y + (this.owner.Height - item.Height) / 2
);
}
}
}

使用时

1
2
3
4
5
6
7
8
9
10
11
private void btnOpen_Click(object sender, EventArgs e)
{
Form fmA = new fmA();
new NonModalDialog(this/*親*/, fmA/*子*/,
() =>
{
//After ClosedAction
//子窗口关闭后想做的事可以写在这里
});
fmA.Show(); // 用Show 取代 ShowDialog
}