胖胖虫关于Delphi中窗口(表单)的自以为是的经验总结

来源:互联网 发布:为什么淘宝充值便宜 编辑:程序博客网 时间:2024/04/30 06:14

不能在模式表单中Release自己

Form1的一个方法中如下:

    var

        x:tform2;

    begin

        x:=tform2.CreateParented(Self.Handle);

        x.ShowModal;

    如果在Form2中的某个事件方法中使用Self.Release释放自己,则Form2消失了,Form1却再也不响应键盘和鼠标。如果改成以下这样也不行:

        x:=tform2.CreateParented(Self.Handle); ( x:=tform2.Create(nil)

        x.ShowModal;

        x.release;                (x.Free)

将第2句改成 x.Show 以后一切正常。

结论:不能在模式表单中Release自己,

    原理:经代码追溯,发现表单是这样实现的:在 ShowModal 方法中重复检查消息和ModalResult属性值,直到符合条件后,再进行关闭自己的一系列动作。所以,如果在模式表单中调用Release或类似方法将引发混乱。要在模式表单中关闭自己,可以调用Close方法,或者将ModalResult属性设置为非零值。

显示模式表单后,该模式表单无法回到屏幕最前面

    还是上个问题的第一段代码,

    var

        x:tform2;

    begin

        x:=tform2.CreateParented(Self.Handle);

        x.ShowModal;

 

Form2显示后(其FormStyle属性=fsNormal时), 切换到操作系统中其它任务画面后

只有以下方法才能回到该程序画面(也就是让Form2回到屏幕最前面):

    1.选择"显示桌面"再点击任务栏上的该程序任务;

    2.点击Form1, 虽然Form1不能接收焦点, 但却导致Form2来到屏幕最前面;

    3.点击Form2的标题栏。

而以下方法无法让Form2回到屏幕最前面

    1.点击Form2的标题栏之外的区域, 这时虽然Form2被激活,却无法回到最前面;

    2.点击操作系统任务栏上的该程序任务

    3.通过任务管理器来切换到该程序

原因:几乎可以肯定是Delphi中的BUG
解决办法

覆盖Form2 WndProc方法,捕捉Wm_Activate消息,获取该消息后  SetWindowPos(Self.Handle,HWND_TOP,

0,0,0,0,SWP_NOSIZE+SWP_NOMOVE);  该语句使得Form2回到前面来。

非模式表单要尽量避免使用 BsDialog 边框

2003.7.28

    还发现在Excel, Delphi建立的非模式边框为 BsDialog 的表单也有同样情况,当切换到操作系统中其它任务后,再切换回来时,Excel很难显示出来,

不过,当显示出来时,其中的表单状态是正常的.

    所以, 非模式表单要尽量避免使用 BsDialog 边框,

消息响应的问题

    我覆盖了WndProc方法试图捕捉用户按下任意组合键中的Shift键,代码如下:

procedure TForm1.wndproc(var message: TMessage);

begin

  if message.Msg =WM_KEYUP then

    if GetKeyState(VK_SHIFT)=1   then

      ShowMessage('shift');

  inherited;

end;

    结果发现,每按两次组合键(例如Shift1),GetKeyState才捕捉到一次,更要命的是,当上一次捕捉到Shift时,现在开始只按 1 不按Shift键,可GetKeyState却又每次都捕捉到Shift键。

结论:

无论是WndProc还是MainWndProc方法,其Message参数都是经过加工的,也就是说,有另外一个过程(这个过程是在运行时生成的,具体参考大富翁中的1267299号文章)响应了Windows消息,将该消息加工成TMessage结构后再传递给MainWndProc方法,这些加工后的消息已经和Windows的原始消息有所不同了。

原创粉丝点击