Не удается восстановить свернутую программу с панели задач Windows

Моя программа написана на Delphi 10. Она показывает диалоговое окно входа в систему до того, как запустится, и все работает нормально.

Но если я сверну программу, щелкнув панель задач Windows (при активном диалоговом окне входа в систему), она останется свернутой навсегда.

Кто-нибудь знает решение?

Unit1.pas

class function TForm1.Execute: Boolean;
var
 Dlg:TForm1;
begin
 Dlg:=TForm1.Create(nil);
 try
   Result:=Dlg.ShowModal=mrOk;
 finally
  Dlg.Free;
 end;
end;

Project1.dpr

begin
  if not TForm1.Execute then //if i press on task bar, window will remain minimized forever.
   Exit;
  Application.Initialize;
  Application.MainFormOnTaskbar := True; 
  //Moving TForm1.Execute here has no effect
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end

person Community    schedule 01.04.2021    source источник
comment
Почему вы используете один и тот же класс как для модального диалога, так и для основной формы? Этот код не имеет смысла.   -  person Remy Lebeau    schedule 01.04.2021
comment
Это просто пример воспроизведения ошибки. Переименование класса не решит эту проблему.   -  person    schedule 01.04.2021
comment
Вы должны позволить приложению инициализировать и запустить Application.CreateForm до, когда у вас будет if not TForm1.Execute..., также было бы лучше использовать экземпляр, созданный приложением, поэтому используйте Execute как метод объекта, а не метод класса.   -  person Rob Lambden    schedule 01.04.2021
comment
Привет, можешь написать краткий пример? Я не совсем понимаю, как создать форму с помощью Application.CreateForm и выйти из программы, если модальный результат этой формы - mrCancel   -  person    schedule 01.04.2021
comment
Что произойдет, если вы создадите основную форму перед формой входа?   -  person David Heffernan    schedule 01.04.2021
comment
Он покажет окно с ошибкой, так как учетные данные пользователя не введены.   -  person    schedule 01.04.2021
comment
Правильно ли, что TForm1 используется как для диалога входа, так и для основной формы? На первый взгляд, я бы создал разные формы для входа и в качестве основной формы.   -  person fpiette    schedule 01.04.2021
comment
Нет, он не показывает окно с ошибкой, потому что ваш код не проверяет учетные данные пользователя.   -  person David Heffernan    schedule 02.04.2021


Ответы (1)


Я сделал пример кода, показывающий, как отображать форму входа ПЕРЕД основной формой. Я проверил (Win10), что, свернув окно с помощью щелчка на панели задач, его можно повторно активировать с помощью щелчка на панели задач.

В форме входа я просто сделал это с двумя кнопками, одна для входа в систему и одна для неудачного входа в систему, без фактической проверки какого-либо кода пользователя/пароля. Я предполагал, что ты сможешь сделать эту часть.

Файл проекта:

program LoginDemo;
uses
  Vcl.Forms, Vcl.Dialogs, Vcl.Controls,
  LoginDemoMain in 'LoginDemoMain.pas' {DemoMainForm},
  LoginDemoDialog in 'LoginDemoDialog.pas' {DemoLoginForm};
{$R *.res}
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TDemoLoginForm, DemoLoginForm);
  try
      if DemoLoginForm.ShowModal <> mrOK then begin
          ShowMessage('Invalid login, sorry...');
          Exit;
      end;
  finally
      DemoLoginForm.Free;
  end;
  Application.CreateForm(TDemoMainForm, DemoMainForm);
  Application.Run;
end.

Диалоговое окно входа:

unit LoginDemoDialog;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TDemoLoginForm = class(TForm)
    LoginOKButton: TButton;
    LoginFailedButton: TButton;
    Label1: TLabel;
    procedure LoginFailedButtonClick(Sender: TObject);
    procedure LoginOKButtonClick(Sender: TObject);
  end;

var
  DemoLoginForm: TDemoLoginForm;

implementation

{$R *.dfm}

procedure TDemoLoginForm.LoginFailedButtonClick(Sender: TObject);
begin
    Close;
    ModalResult := mrCancel;
end;

procedure TDemoLoginForm.LoginOKButtonClick(Sender: TObject);
begin
    Close;
    ModalResult := mrOK;
end;

end.

Основная форма:

unit LoginDemoMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TDemoMainForm = class(TForm)
    Label1: TLabel;
    ExitButton: TButton;
    procedure ExitButtonClick(Sender: TObject);
  end;

var
  DemoMainForm: TDemoMainForm;

implementation

{$R *.dfm}

procedure TDemoMainForm.ExitButtonClick(Sender: TObject);
begin
    Close;
end;

end.
person fpiette    schedule 01.04.2021
comment
Здравствуйте, похоже, ваш ответ работает только частично, поскольку первая форма, созданная с помощью Application.CreateForm, назначается свойству Application.MainForm только для чтения. Это не может быть изменено позже. Вы можете просмотреть исходный код формы Application.Create или docwiki.embarcadero.com/Libraries/Sydney/en/› Я не совсем понимаю значение этого - person ; 01.04.2021
comment
Первый вызов Application.CreateForm() устанавливает Application.MainForm, и когда эта форма закрывается, приложение завершает работу. Для заставок/форм входа в систему, созданных до желаемого MainForm, вы должны вместо этого Create создать их вручную, например: DemoLoginForm := TDemoLoginForm.Create(nil); В противном случае сначала создайте MainForm, но установите Application.ShowMainForm := False перед вызовом Application.Run(), а затем вызовите Application.MainForm.Show() при необходимости. . - person Remy Lebeau; 01.04.2021
comment
Я сделал то же самое в своей функции класса TForm1.Execute, Dlg:=TForm1.Create(nil); Это работало нормально, но форма входа не может быть восстановлена, если она свернута. - person ; 01.04.2021
comment
@Valeriy.B Извините, вы не правы. После освобождения формы входа и создания экземпляра TDemoMainForm эта форма становится основной. Это легко увидеть с помощью отладчика: поставьте точку останова на строку Application.Run и нажмите CTRL-F7, чтобы показать Application.Mainform.Name, и вы увидите, что основная форма теперь называется DemoMainForm. - person fpiette; 01.04.2021
comment
@fpiette Да, ты прав. Спасибо за помощь. Что ж, я изменил способ создания экземпляра диалога входа в систему в моей функции класса Execute на Application.CreateForm и переместил его в правильное место в файле .dpr. - person ; 01.04.2021
comment
Я уверен, что @Remy находится здесь, и этот код просто делает форму входа основной формой. Что не может быть желаемым результатом. Не похоже, чтобы на этот вопрос был дан удовлетворительный ответ. - person David Heffernan; 02.04.2021
comment
@DavidHeffernan Форма входа становится основной на время процесса входа. Сразу после входа в систему форма входа освобождается, и либо программа завершает работу (неверный вход), либо (действительный вход) создается TDemoMainForm, который становится основной формой, как и ожидалось. Несмотря на то, что форма входа в систему является основной формой, приложение не закрывается при освобождении, потому что это поведение находится в Application.Run, который еще не запущен (поэтому первое предложение Реми неверно). В любое время панель задач можно использовать для минимизации видимого окна, и именно об этом просила ОП. - person fpiette; 02.04.2021