一个报警窗体(不能手动关闭),当满足关闭条件时候在FormCloseQuery事件里设置canclose:=true;
现在当报警时候,主窗体缩小到任务拦的话,过段时间,报警消除,把主窗体放大,报警窗体不回消失。
模拟代码如下:
//单元1 ,模拟主线程
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    i:integer;
    { Public declarations }
  end;var
  Form1: TForm1;
implementationuses Unit2;{$R *.dfm}procedure TForm1.Timer1Timer(Sender: TObject);
begin
  i:=i-1;
  if i<0 then
  begin
    i:=0;
    form2.Close;
  end;
end;procedure TForm1.FormShow(Sender: TObject);
begin
  form2.show;
  i:=10;
end;end.

解决方案 »

  1.   

    //单元2,模拟报警窗体
    unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;type
      TForm2 = class(TForm)
        procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form2: TForm2;implementationuses Unit1;{$R *.dfm}procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    begin
      if form1.i<=0 then
         CanClose:=true
      else
        CanClose:=false;
    end;end.
      

  2.   

    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      i:=i-1;
      if i<0 then
      begin
        i:=0;
        if Assigned(form2) then FreeAndNil(form2); //form2.Close;直接把他给KILL掉
      end;
    end;procedure TForm1.FormShow(Sender: TObject);
    begin
     if Not Assigned(form2) then  form2 := TForm2.Create(self);   //不存在时就创建!
      form2.show;
      i:=10;
    end;
      

  3.   

    to 楼上
    最小化恢复到原来状态你的FormShow事件根本不会被触发,另外我只是想找到这个引发问题的原理,解决的话途径很多,你的动态创建释放只是其中之一,谢谢你的热心.
      

  4.   

    分析了原代码之后,有这么点思路,可能不正确!
    首先你最小化的时候,系统处理了WMSysCommand消息,处理代码如下:
    procedure TCustomForm.WMSysCommand(var Message: TWMSysCommand);begin
      with Message do
      begin
        if (CmdType and $FFF0 = SC_MINIMIZE) and (Application.MainForm = Self) then
          Application.WndProc(TMessage(Message))
        ......
    end;
    这句可以看出,如果你最小化的是主窗体,系统就把消息传给Application.WndProc处理
    再来看看Application.WndProc
    procedure TApplication.WndProc(var Message: TMessage);
        with Message do
          case Msg of
            WM_SYSCOMMAND:
              case WParam and $FFF0 of
                SC_MINIMIZE: Minimize;
                SC_RESTORE: Restore;
              else
    end;
    他是调用了Minimize;
    procedure TApplication.Minimize;里又调用了NormalizeTopMosts;
    NormalizeTopMosts再调用DoNormalizeTopMosts(False);

    procedure TApplication.DoNormalizeTopMosts(IncludeMain: Boolean);
    var
      I: Integer;
      Info: TTopMostEnumInfo;
    begin
      if Application.Handle <> 0 then
      begin
        if FTopMostLevel = 0 then
        begin
          Info.TopWindow := Handle;
          Info.IncludeMain := IncludeMain;
          EnumWindows(@GetTopMostWindows, Longint(@Info));
    //这里枚举了窗体,
    我们再来看看GetTopMostWindowsfunction GetTopMostWindows(Handle: HWND; Info: Pointer): BOOL; stdcall;
    begin
      Result := True;
      if GetWindow(Handle, GW_OWNER) = Application.Handle then
        if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0) and
          ((Application.MainForm = nil) or PTopMostEnumInfo(Info)^.IncludeMain or
          (Handle <> Application.MainForm.Handle)) then
          Application.FTopMostList.Add(Pointer(Handle))
        else
        begin
          PTopMostEnumInfo(Info)^.TopWindow := Handle;
          Result := False;
        end;
    end;  if GetWindow(Handle, GW_OWNER) = Application.Handle then
        if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0) and
          ((Application.MainForm = nil) or PTopMostEnumInfo(Info)^.IncludeMain or
          (Handle <> Application.MainForm.Handle)) then
          Application.FTopMostList.Add(Pointer(Handle))
    这里应该是把应用程序中所有真显示的窗体的Handle保存在FTopMostList里面
    做一下记录,好让Restore的时候可以根据这个列表来恢复显示而从Restore中调用的RestoreTopMosts中可以看出,确实是利用了FTopMostList进行了恢复!
          for I := FTopMostList.Count - 1 downto 0 do
            SetWindowPos(HWND(FTopMostList[I]), HWND_TOPMOST, 0, 0, 0, 0,
              SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);所以这里,虽然你已经在TIMER里Close了窗体,但是只是把它给Hide了,FTopMostList
    还是记录窗提要被恢复的信息,所以当你Restore的时候它又再度把他显示出来~~~
    一点看法,应该很多不正确的地方,多多指教~
      

  5.   

    TCloseAction = (caNone, caHide, caFree, caMinimize);
    procedure TCustomForm.DoClose(var Action: TCloseAction);
    begin
      if Assigned(FOnClose) then FOnClose(Self, Action);
    end;
    procedure TCustomForm.Close;
    var
      CloseAction: TCloseAction;
    begin
      if fsModal in FFormState then
        ModalResult := mrCancel
      else
        if CloseQuery then
        begin
          if FormStyle = fsMDIChild then
            if biMinimize in BorderIcons then
              CloseAction := caMinimize else
              CloseAction := caNone
          else
            CloseAction := caHide;
          DoClose(CloseAction);
          if CloseAction <> caNone then
            if Application.MainForm = Self then Application.Terminate
            else if CloseAction = caHide then Hide
            else if CloseAction = caMinimize then WindowState := wsMinimized
            else Release;
        end;
    end;
    通过上述代码可以看出它对非子窗体的关闭确实执行了hide处理,方便以后的调用,delphi版越来越冷,既然找到问题原因了,就结了吧