none
执行 CreateHandle() 时无法调用值 Close()。 RRS feed

  • 问题

  • 我的主窗口是MdiForm,
    当我打开新窗口,
    form1 frm=new form1();   
    frm.    frm.MdiParent = this;       
     frm.Show();   
    在form1_Load()做权限检测, 如果不通过就调用Close();  这时就会出现:"执行 CreateHandle() 时无法调用值 Close()。"错误. 
    但是如果将 frm.MdiParent = this;   删掉又没有问题. 究竟是什么原因呢,有没有办法不删除frm.MdiParent = this;  又能close();
    2010年3月17日 3:31

答案

  • 以前我也和你一样面临这个尴尬的问题,问题的根源就是必要要进入到窗体后才能获取权限判断用户是否有权利打开窗体。这在技术上没有任何问题,界面会闪,用户体验不好。于是改为在实例化窗体前判断是否有权限打开窗体来解决这个问题。

    我建议你也这样做,原因有二:

    1 当没有权限进入时避免窗体闪的情况,提高用户体验。
    2 当没有权限的时候减少开销(因为根本不需要打开窗口,更不需要初始数据)。

    知识改变命运,奋斗成就人生!
    • 已标记为答案 Castrandom 2010年3月18日 2:27
    2010年3月17日 4:50
    版主

全部回复

  • 你好!

    你这里判断的位置不合适,最好在将这个判断放到实例化窗体前。比如:

    bool show = "你的判断结果";

    if (show)
    {
        form1 frm=new form1();   
        frm.frm.MdiParent = this;       
        frm.Show(); 
    }

    知识改变命运,奋斗成就人生!
    2010年3月17日 4:12
    版主
  • 因为权限包括了对窗口里面的按钮的Enable的设置,所以才放到Load()里面
    2010年3月17日 4:32
  • 以前我也和你一样面临这个尴尬的问题,问题的根源就是必要要进入到窗体后才能获取权限判断用户是否有权利打开窗体。这在技术上没有任何问题,界面会闪,用户体验不好。于是改为在实例化窗体前判断是否有权限打开窗体来解决这个问题。

    我建议你也这样做,原因有二:

    1 当没有权限进入时避免窗体闪的情况,提高用户体验。
    2 当没有权限的时候减少开销(因为根本不需要打开窗口,更不需要初始数据)。

    知识改变命运,奋斗成就人生!
    • 已标记为答案 Castrandom 2010年3月18日 2:27
    2010年3月17日 4:50
    版主
  • 你好!
         不好意思,你的描述我不是很清楚,请问可以提供给我你的相关代码吗?我帮你测试一下!
    周雪峰
    2010年3月17日 5:55
    版主
  •     form1 frm=new form1();   
        frm.frm.MdiParent = this;       

    到了这里其实frm已经实体化,可以干他该干的事情了(控件可能还没起来,不过在load中判断的东西应该是不需要控件的吧),可以给一个函数或者属性来进行外部判断,如

        if(frm.IsOk)
        {
          frm.Show(); 
        }
    否则就直接返回好了,frm就让系统自动销毁。

    霸王
    2010年3月17日 9:08
  • 我也是这么想的。 在调用frm.Show();之前,首先调用frm的一个接口函数进行各类验证工作,用来判断是否可以打开frm。
    不过通常情况下,这类验证逻辑不应该写在form1 中。因为它是显示层的问题。最好把验证函数交给逻辑层的某些函数来执行。
    这样做可以有效地将显示控制逻辑和应用逻辑分开,增加系统的可扩展性。今后即使改成B/S了,验证逻辑也照样可重用!
    2010年3月17日 14:59
  • 多少论坛积分才可以做五星上将啊:)
    2010年3月17日 15:01
  • 谢谢各位的建议,最后还是按X.X.Y版主的做法,把权限分两次来做,打开窗口前先判断一次,打开后再做一次.
    把权限名写在窗口的一个字段里面,不是一个好做法...

    2010年3月18日 2:27
  • 额,少打一对括号而已,最近有人告诉我,属性和函数没什么区别,所以……

    只是把你原来在load里的判断方法拿出来而已,没什么坏处,也如楼上某位所说,实际的判断最好放在BLL里面。

    霸王
    2010年3月18日 4:42
  • 多少论坛积分才可以做五星上将啊:)
    > 15000 就可以了

    知识改变命运,奋斗成就人生!
    2010年3月18日 4:43
    版主
  • 我来从技术层面讲一讲这里面为什么会出问题。

    在 Windows Form 进行构造时,首先是调用构造函数,然后 InitializeComponent,然后就要开始 CreateHandle。CreateHandle 用来向 Windows 申请一个新的句柄给创建的窗体,然后窗体调用 CreateWindowEx 创建自己和所有子窗体。

    您写在 Form_Load 中的程序代码,会在 CreateWindowEx 后在 ShowWindow 前执行,如果在这里把窗体 Close 了,就会 Close 这个句柄,接着执行下去到 ShowWindow 的时候 Windows 发现句柄没了,就会有内部错误发生 (窗口句柄无效)。因此为了避免这个问题,Windows Forms 不允许在 Load 事件处理程序中关闭窗体。


    Mark Zhou
    2010年3月18日 10:05
  • 那么延伸一下,在form_load 中如何退出或者取消这个form?记得form-load没有eventarg,不能e.Cancel()的吧
    霸王
    2010年3月18日 12:36
  • 无法取消。Form_Load 是一个中间的生命周期,取消的话可能只能用 Application.Exit(),就像 ASP.NET 中,Page_Load 要终止的话只能 Response.End()。
    Mark Zhou
    2010年3月19日 9:00
  • 所谓的“生出来就得对他负责”么 = =

    那么form_loaded 能不能干这个事情?


    霸王
    2010年3月19日 10:31