ITPub博客

首页 > Linux操作系统 > Linux操作系统 > delphi模态窗体突然不模态了

delphi模态窗体突然不模态了

原创 Linux操作系统 作者:enweiiew 时间:2015-11-17 22:11:41 0 删除 编辑
我今天在做项目的时候,也遇到这个问题了,问题就出在我调用的代码里,同事写的代码中有    Application.MainForm.Enabled:= true;这样一句,这样就使得我原理模态的窗体不能够模态了。具体的原理,请参照下面的解释,这是摘自另外的博客,感谢原作者。





问题描述

  昨天同事修改一个bug,请我审查代码时我发现这个bug很有意思,值得深入研究一下。

  问题是这样的,弹出一个模态窗口后,在窗口内切换树节点,发现主窗口也可以接受鼠标和键盘消息了——模态窗口不模态了

  跟踪发现,在窗口内切换树节点会间接调用到进度条窗口(我们自己写的一个窗口),ShowProgress时会调用Application.MainForm.Enabled := False,HideProgress是会调用Application.MainForm.Enabled := True,问题就出现在这个地方。

ShowModal实现

复制代码
TCustomForm.ShowModal begin //... 
  WindowList := DisableTaskWindows(0); 
  Show;
  SendMessage(Handle, CM_ACTIVATE, 0, 0); repeat Application.HandleMessage; if Application.Terminated then ModalResult := mrCancel else if ModalResult <> 0 then CloseModal; until ModalResult <> 0; //... end; DisableTaskWindows begin //... EnumThreadWindows(GetCurrentThreadID, @DoDisableWindow, 0); //... end DoDisableWindow begin //... EnableWindow(Window, False);  
  //... end
复制代码

  ShowModal的实际上只让模态接收键盘和鼠标信息,而禁止其他的窗口接收键盘和鼠标消息,这是通过调用EnableWindow这个Windows API实现的。

SetEnabled实现

复制代码
TControl.SetEnabled begin //...
  Perform(CM_ENABLEDCHANGED, 0, 0) //... end TWinControl.CMEnabledChanged begin //... EnableWindow(FHandle, Enabled) //... end
复制代码

  当调用Application.MainForm.Enabled := True时就会使得MainForm的可以接收消息了,之前的模态窗口就不再模态了。

  修改bug的方法:判断Application.ModalLevel > 0是否为真,为真的时候就不在做上述调用。

Windows API

1、EnableWindow:该函数允许/禁止指定的窗口或控件接受鼠标和键盘的输入,当输入被禁止时,窗口不响应鼠标和按键的输入,输入允许时,窗口接受所有的输入。

2、IsWindowEnabled:用于判断指定的窗口是否允许接受键盘或鼠标输入。

3、EnumThreadWindows枚举所有与一个线程相关联的非子窗口,办法是先将句柄传送给每一个窗口,随后传送给应用程序定义的回调函数。EnumThreadWindows函数继续直到所有窗口枚举完为止或回调函数返回FALSE为止。

VCL:DisableTaskWindows:{ EnumThreadWindows(GetCurrentThreadID, @DoDisableWindow, 0); } //DoDisableWindow为回调函数

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25990299/viewspace-1839978/,如需转载,请注明出处,否则将追究法律责任。

下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2011-07-30

  • 博文量
    16
  • 访问量
    366455