打赏

源起:

近期所介入的几个项目中,最后视频生成窗体,为一模态对话框。因生成时间可能较长,所以其窗体可以最小化,它最小化时同时最小化主程序,唤醒时主程序再复原。

代码亦是8年前本人所写,一直那样用了,也没什么不妥,但总感觉显示效果有优化空间,回头看看当初代码少了些简练。于是用些时间做些验证,寻得相对好点的优化方案。

 

1、最初实现:

方式是接管模态窗体WM_SYSCOMMAND消息,拦截SC_MINIMIZE窗体最小化消息值进行处理,代码如下:

type
  TfrmModal = class(TForm)
    Edit1: TEdit;
  private
    { Private declarations }
    procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;

...

procedure TfrmModal.WMSysCommand(var Msg: TWMSysCommand);
begin
  if Msg.CmdType = SC_MINIMIZE then
    Application.Minimize
  else 
inherited; end;

此代码工作效果,如下动画:

它有两个问题:

i. 任务栏唤起时,对话框直接显示出来,然后才是主窗体从任务栏上动画出来。

ii. 显示出来后,焦点没有落在它身上,需要点击下主窗体触发,焦点才会移到它上面。

这就是它的瑕疵。可是如何优化呢?

反复调整消息处理次序,并抓取在此过程中它的系统消息,终于找到一个相对好点的方案,如方案2.

 

2、方案优化

与1大同小异,调整WM_SYSCOMMAND消息处理函数处理机制,并加入WM_SHOWWINDOW消息处理,代码如下:

type
  TfrmModal = class(TForm)
    Edit1: TEdit;
  private
    { Private declarations }
    procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
    procedure WMShowWindow(var Msg: TWMShowWindow); message WM_SHOWWINDOW;

...

procedure TfrmModal.WMShowWindow(var Msg: TWMShowWindow);
begin
  inherited;
  if Self.WindowState = wsMinimized then
  begin
    Self.WindowState := wsNormal;
    Application.BringToFront;
  end;
end;

procedure TfrmModal.WMSysCommand(var Msg: TWMSysCommand);
begin
  inherited;
  if Msg.CmdType = SC_MINIMIZE then
    Application.Minimize;
end;

因为没有忽略SC_MINIMIZE消息,此窗体亦被最小化,那么在WM_SHOWWINDOW消息中,对它重唤起。

效果如下图:

 

两图对比可见,方案1之两点问题,完美解决。

posted on 2018-07-17 20:13  楚人无衣  阅读(429)  评论(1编辑  收藏  举报