Mdi同样的子窗体只出现一次的几种方法(转贴)
看到论坛中有朋友问,如何可以保证在 MDI主窗体中,同一类型的子窗体只能打开一次,再打开只是将原来打开的窗体激活。这个要求我以前写程序的时候也遇到过。我实现的基本思路是:一般每个子窗体都是继承自 Form类型,不同子窗体分别代表不同的功能,因此只需要判断当前 MDI打开的子窗体的类型中有没有当前需要打开的子窗体类型就行了,如果有,则直接激活,如果没有则创建一个并加到主窗体中。具体实现起来有很多种办法,这里只写出一个利用泛型的实现:/// <summary>
/// 打开MDI子窗口并附加到MDI主窗口中,如果MDI主窗口中已经存在相同类型的子窗口,则直接激活
/// </summary>
/// <typeparam name="T">MDI子窗体类型</typeparam>
/// <param name="mdiParent">MDI主窗体引用</param>
/// <returns>当前创建或得到的MDI子窗体类型实例的引用</returns>
private T OpenUniqueMDIChildWindow<T>(Form mdiParent) where T : Form, new()
{
foreach (Form subForm in mdiParent.MdiChildren)
{
if (subForm.GetType().Equals(typeof(T)))
{
subForm.Activate();
return subForm as T;
}
}
T newForm = new T();
newForm.MdiParent = mdiParent;
newForm.Show();
return newForm;
}
(二)用反射实现的MDI子窗体只运行一个实例首先是通过子窗体类型名来判断是否打开新的子窗体,还是把原有的子窗体进行显示。
using System.Reflection;
/// <summary>
/// Open child window
/// </summary>
/// <param name="ChildTypeString"></param>
private void OpenWindow( string ChildTypeString )
{
Form myChild = null;
if( !ContainMDIChild( ChildTypeString ) )
{
// Get current process assembly
Assembly assembly = Assembly.GetExecutingAssembly();
// Create data type using type string
Type typForm = assembly.GetType( ChildTypeString );
// Create object using type's "InvokeMember" method
Object obj = typForm.InvokeMember( null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null );
// Show child form
if( obj != null )
{
myChild = obj as Form;
myChild.MdiParent = this;
myChild.Show();
myChild.Focus();
}
}
}
/// <summary>
/// Search mdi child form by specific type string
/// </summary>
/// <param name="ChildTypeString"></param>
/// <returns></returns>
private bool ContainMDIChild( string ChildTypeString )
{
Form myMDIChild = null;
foreach(Form f in this.MdiChildren)
{
if( f.GetType().ToString() == ChildTypeString )
{
// found it
myMDIChild = f;
break;
}
}
// Show the exist form
if( myMDIChild != null)
{
myMDIChild.TopMost = true;
myMDIChild.Show();
myMDIChild.Focus();
return true;
}
Else
return false;
}
如: //Open a mdi child form which type named "MDIChild" OpenWindow( typeof( MDIChild ).ToString() );
(三)同一个MDI子窗体只打开一个在MDI中运行多个FORM1,FORM2,FORM3,如果在FORM2打开的状态下再次点击打开FORM2的菜单,如何控制不再打开一个新的FORM2,而是激活已经打开的FORM2.如果窗口在Show后不再改变标题(大多数情况如此),可以通过判断窗口标题来实现,建立一个struct,包括一个获取MDI父窗口是否有窗口标题为指定字符串的子窗口的方法ExistWin和至少一个获取窗口标题的方法WinCaption,代码如下:public struct ChildWinManagement
{
/// <summary>/// 获取窗口标题/// </summary>
/// <returns></returns>public static string WinCaption(用于构造窗口的参数){ return 用参数构造窗口标题 }
/// <summary>/// 获取MDI父窗口是否有窗口标题为指定字符串的子窗口(如果已经存在把此子窗口推向前台)
/// </summary>/// <param name=”MDIwin”>MDI父窗口</param>
/// <param name=”caption”>窗口标题</param>
/// <returns></returns>
public static bool ExistWin(Form MDIwin,string caption)
{
bool R = false;
foreach(Form f in MDIwin.MdiChildren)
{
if(f.Text == caption)
{R = true;f.Show();
f.Activate();
break;
}
}
return R;
}
}
(四)在MDI中使子窗体只保留一个实例
public static void OpenForm(Form frmContains,Type formType)
{
bool isNewForm = true;
if (formType == null)
{
throw (new Exception("打开窗体Form不存在"));
}
foreach (Form myMDIChild in frmContains.MdiChildren)
{
if (myMDIChild.GetType() == formType)
{
myMDIChild.WindowState = FormWindowState.Maximized;
myMDIChild.TopMost = true;
myMDIChild.Show();
myMDIChild.Focus();
isNewForm = false;
break;
}
}
if (isNewForm == true)
{
object obj = formType.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
Form form = obj as Form;
form.WindowState = FormWindowState.Maximized;
form.MdiParent = frmContains;
form.Show();
form.Focus();
}
}
调用方法OpenForm(main,//mdi窗体,typeof(child))//子窗体的Type.
(五)来自csdn方法一: Code
/// <summary>/// 检查MDI子窗体是否存在
/// </summary>/// <param name="childFrmName"></param>
/// <returns></returns>
private bool IsChildFormExist(string childFrmName)
{
foreach (Form childFrm in this.MdiChildren)
{
if (childFrm.Name == childFrmName) //用子窗体的Name进行判断,如果存在则将他激活
{
If
(childFrm.WindowState == FormWindowState.Minimized)
{
childFrm.WindowState = FormWindowState.Normal;
}
childFrm.Activate();
return true;
}
}
return false;
}
//调用示例如下
/// <summary>/// 用户管理
/// </summary>///
<param name="sender"></param>/// <param name="e"></param>
private void ToolStripMenuItem_UserManage_Click(object sender, EventArgs e){ if (string.IsNullOrEmpty(currentLoginName))
{ return; }
//通过窗体名称查询该窗体是否已经存在,如存在则显示,否则就新创建一个
if (!this.IsChildFormExist("UserForm"))
{
UserForm frmUser = new UserForm();
frmUser.MdiParent = this;
frmUser.WindowState = FormWindowState.Maximized;
frmUser.Show();
}
}
方法二: Code/// <summary>/// 打开窗体
/// </summary>/// <param name="mdiChildTypeString"></param>
/// <returns></returns>
private void ShowWindow(string mdiChildTypeString)
{
Form currentMdiChild = null;
if (!IsMDIChildFormExist(mdiChildTypeString))
{
Assembly assembly = Assembly.GetExecutingAssembly();
Type typForm = assembly.GetType(mdiChildTypeString);
//关于InvokeMember用法,不明白的可以查看:http://msdn.microsoft.com/zh-cn/library/de3dhzwy(VS.80).aspx
Object mdiChild = typForm.InvokeMember(
null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
if (mdiChild != null)
{
currentMdiChild = mdiChild as Form;
currentMdiChild.MdiParent = this;
currentMdiChild.WindowState = FormWindowState.Maximized;
currentMdiChild.Show();
currentMdiChild.Focus();
}
}
}
/// <summary>/// 检查MDI子窗体是否存在
/// </summary>/// <param name="mdiChildTypeString"></param>
/// <returns></returns>
private bool IsMDIChildFormExist(string mdiChildTypeString){
Form currentMDIChild = null;
foreach (Form mdiChildFrm in this.MdiChildren)
{
if (mdiChildFrm.GetType().ToString() == mdiChildTypeString)
{
currentMDIChild = mdiChildFrm;
break;
}
}
if (currentMDIChild != null)
{
if (currentMDIChild.WindowState == FormWindowState.Minimized)
{
currentMDIChild.WindowState = FormWindowState.Normal;
}
currentMDIChild.TopMost = true;
currentMDIChild.Activate();
currentMDIChild.Focus();
return true;
}
else
{ return false; }}
//调用方法如下/// <summary>/// 用户管理/// </summary>/// <param name="sender"></param>/// <param name="e"></param>
private void ToolStripMenuItem_UserManage_Click(object sender, EventArgs e)
{ if (string.IsNullOrEmpty(currentLoginName))
{
return;
}
ShowWindow(typeof(UserForm).ToString());
}
浙公网安备 33010602011771号