Delphi Изменение основной формы во время работы приложения


2 принят

Как уже сказал Дэвид Хеффернан, изменение основной формы уже запущенного приложения невозможно. Это ограничение самих окон.

То, что вы можете сделать, это обмануть и никогда не изменять основную форму, но только заставляйте ее выглядеть так, как вы.
Как вы это достигаете?

Шаг 1: добавьте код ко второй форме, чтобы создать собственную кнопку панели задач

procedure TWorkForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

Шаг 2. Динамически создайте вторую форму непосредственно перед ее переключением. После его создания ранее добавленный код создаст новую кнопку панели задач для вашей второй формы.

Шаг 3: Теперь скройте вас фактическую основную форму. Скрытие также скроет принадлежащую ему кнопку панели задач. Таким образом, вы все еще показываете одну кнопку панели задач, и она принадлежит вашей второй форме.

Шаг 4: Чтобы ваша вторая форма завершила ваше приложение при его закрытии, вызовите метод Close вашей реальной основной формы из вашего второго события Forms OnClose или OnFormCloseQuery.
Если вы хотите вернуться к истинному вызову основной формы, выберите метод «Моя основная форма» вместо метода «Закрыть».

Этот подход позволяет нам быстро менять формы, поэтому только самые острые пользователи заметят короткую анимацию кнопки «Панель задач».
ПРИМЕЧАНИЕ. Если ваш второй вариант является сложным, и из-за этого требуется некоторое время для создания, вы можете создать его скрытым, а затем, как только его процесс создания завершится, покажите его и выполните обмен. В противном случае вы можете в итоге показать две кнопки панели задач, которые, как я полагаю, вы хотите избежать.

Вот краткий пример:
- LoginForm - это настоящая основная форма, созданная при запуске приложения. WorkForm - это форма, по которой пользователь будет проводить большую часть времени после входа в систему, и этот файл создается в процессе входа в систему

Форма входа в систему:

unit ULoginForm;

interface

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

type
  TLoginForm = class(TForm)
    BLogIn: TButton;
    procedure BLogInClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  LoginForm: TLoginForm;

  //Global variable to tell us if we are only logging out or closing our program
  LoggingOut: Boolean;

implementation

uses Unit2;

{$R *.dfm}

procedure TLoginForm.BLogInClick(Sender: TObject);
begin
  //Create second Form
  Application.CreateForm(TWorkForm, WorkForm);
  //Hide Main Form
  Self.Hide;
  //Don't forget to clear login fields
end;

end.

Код формы работы:

unit UWorkForm;

interface

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

type
  TWorkForm = class(TForm)
    BLogOut: TButton;
    //Used in overriding forms creating parameters so we can add its own Taskbar button
    procedure CreateParams(var Params: TCreateParams); override;
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure BLogOutClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  WorkForm: TWorkForm;

implementation

uses Unit1;

{$R *.dfm}

procedure TWorkForm.BLogOutClick(Sender: TObject);
begin
  //Set to true so we know we are in the process of simply logging out
  LoggingOut := True;
  //Call close method to begin closing the current Form
  Close;
end;

procedure TWorkForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

procedure TWorkForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  //Check to see if we are in the process of simply logging out
  if not LoggingOut then
  begin
    //If we are not in the process of logging out close the Main Form
    LoginForm.Close;
    //and then allow closing of current form
    CanClose := True;
  end
  else
  begin
    //But if we are in the process of simply logging out show the Main Form
    LoginForm.Show;
    //Reset the LoggingOut to false
    LoggingOut := False;
    //and then alow closing of current form
    CanClose := True;
  end;
end;

end.

4

Можно ли изменить основную форму, пока приложение уже запущено?

Невозможно изменить основную форму VCL во время работы программы. Это свойство определяется раз и навсегда, когда программа запускается.

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

Обновить

Ну, вы можете изменить Application.MainForm, но для этого требуется уничтожить текущую основную форму, а затем создать новую.


3

Невозможно изменить Application.MainFormодин раз, когда он был назначен. Однако вам тоже этого не нужно. Самое простое решение этой проблемы - создать пустую скрытую, TFormчтобы действовать как реальная, Application.MainForm и позволить ей нормально управлять панелью задач, а затем при необходимости вы можете отображать / скрывать любые вторичные TFormобъекты, где ваш желаемый «MainForm» является вторичной формой, а не реальный MainForm.


2

Если Application.MainFormOnTaskbarв вашей программе запуска (в .dprфайле) установлено значение false , то VCL создаст скрытую форму, единственной целью которой является предоставить значок панели задач. Это более старый подход и обычно не рекомендуется, но пока видны другие окна, он позволит вам скрыть основную форму без исчезновения приложения с панели задач.

Вы также можете предоставить Application.OnGetMainFormHandleобработчик события, чтобы изменить его Application.MainFormHandleво время выполнения (но не Application.MainForm ). MainFormHandleзатрагивает такие вещи, как владелец модальных всплывающих диалогов.

Дополнительная информация Application.MainFormOnTaskbarи недостатки ее отключения: это становится сложным в спешке. Краткая версия находится в документах VCL , в которых объясняется, что некоторые новые функции Windows (например, миниатюры на панели задач), которые были введены в Vista, требуют MainFormOnTaskbar := True. В этом обсуждении SO есть намного больше фоновых чтений .


2

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

Код выглядел примерно так:

procedure TfrmLogin.btnLoginClick(Sender: TObject);
begin
    frmMainWork := TfrmMain.Create(Application);
    try
        Pointer((@Application.MainForm)^) := frmMainWork;
        frmLogin.Hide;
        frmMainWork.ShowModal;
    finally
        Pointer((@Application.MainForm)^) := frmLogin;
        frmLogin.Show;
        FreeAndNil(frmMainWork);
    end;

end;

надеюсь это поможет :-)

формы, Дельфы, VCL, панель задач, Дельфы-XE6,

forms,delphi,vcl,taskbar,delphi-xe6,

5

Ответов: 8


2 принят

Как уже сказал Дэвид Хеффернан, изменение основной формы уже запущенного приложения невозможно. Это ограничение самих окон.

То, что вы можете сделать, это обмануть и никогда не изменять основную форму, но только заставляйте ее выглядеть так, как вы.
Как вы это достигаете?

Шаг 1: добавьте код ко второй форме, чтобы создать собственную кнопку панели задач

procedure TWorkForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

Шаг 2. Динамически создайте вторую форму непосредственно перед ее переключением. После его создания ранее добавленный код создаст новую кнопку панели задач для вашей второй формы.

Шаг 3: Теперь скройте вас фактическую основную форму. Скрытие также скроет принадлежащую ему кнопку панели задач. Таким образом, вы все еще показываете одну кнопку панели задач, и она принадлежит вашей второй форме.

Шаг 4: Чтобы ваша вторая форма завершила ваше приложение при его закрытии, вызовите метод Close вашей реальной основной формы из вашего второго события Forms OnClose или OnFormCloseQuery.
Если вы хотите вернуться к истинному вызову основной формы, выберите метод «Моя основная форма» вместо метода «Закрыть».

Этот подход позволяет нам быстро менять формы, поэтому только самые острые пользователи заметят короткую анимацию кнопки «Панель задач».
ПРИМЕЧАНИЕ. Если ваш второй вариант является сложным, и из-за этого требуется некоторое время для создания, вы можете создать его скрытым, а затем, как только его процесс создания завершится, покажите его и выполните обмен. В противном случае вы можете в итоге показать две кнопки панели задач, которые, как я полагаю, вы хотите избежать.

Вот краткий пример:
- LoginForm - это настоящая основная форма, созданная при запуске приложения. WorkForm - это форма, по которой пользователь будет проводить большую часть времени после входа в систему, и этот файл создается в процессе входа в систему

Форма входа в систему:

unit ULoginForm;

interface

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

type
  TLoginForm = class(TForm)
    BLogIn: TButton;
    procedure BLogInClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  LoginForm: TLoginForm;

  //Global variable to tell us if we are only logging out or closing our program
  LoggingOut: Boolean;

implementation

uses Unit2;

{$R *.dfm}

procedure TLoginForm.BLogInClick(Sender: TObject);
begin
  //Create second Form
  Application.CreateForm(TWorkForm, WorkForm);
  //Hide Main Form
  Self.Hide;
  //Don't forget to clear login fields
end;

end.

Код формы работы:

unit UWorkForm;

interface

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

type
  TWorkForm = class(TForm)
    BLogOut: TButton;
    //Used in overriding forms creating parameters so we can add its own Taskbar button
    procedure CreateParams(var Params: TCreateParams); override;
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure BLogOutClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  WorkForm: TWorkForm;

implementation

uses Unit1;

{$R *.dfm}

procedure TWorkForm.BLogOutClick(Sender: TObject);
begin
  //Set to true so we know we are in the process of simply logging out
  LoggingOut := True;
  //Call close method to begin closing the current Form
  Close;
end;

procedure TWorkForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

procedure TWorkForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  //Check to see if we are in the process of simply logging out
  if not LoggingOut then
  begin
    //If we are not in the process of logging out close the Main Form
    LoginForm.Close;
    //and then allow closing of current form
    CanClose := True;
  end
  else
  begin
    //But if we are in the process of simply logging out show the Main Form
    LoginForm.Show;
    //Reset the LoggingOut to false
    LoggingOut := False;
    //and then alow closing of current form
    CanClose := True;
  end;
end;

end.

4

Можно ли изменить основную форму, пока приложение уже запущено?

Невозможно изменить основную форму VCL во время работы программы. Это свойство определяется раз и навсегда, когда программа запускается.

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

Обновить

Ну, вы можете изменить Application.MainForm, но для этого требуется уничтожить текущую основную форму, а затем создать новую.


3

Невозможно изменить Application.MainFormодин раз, когда он был назначен. Однако вам тоже этого не нужно. Самое простое решение этой проблемы - создать пустую скрытую, TFormчтобы действовать как реальная, Application.MainForm и позволить ей нормально управлять панелью задач, а затем при необходимости вы можете отображать / скрывать любые вторичные TFormобъекты, где ваш желаемый «MainForm» является вторичной формой, а не реальный MainForm.


2

Если Application.MainFormOnTaskbarв вашей программе запуска (в .dprфайле) установлено значение false , то VCL создаст скрытую форму, единственной целью которой является предоставить значок панели задач. Это более старый подход и обычно не рекомендуется, но пока видны другие окна, он позволит вам скрыть основную форму без исчезновения приложения с панели задач.

Вы также можете предоставить Application.OnGetMainFormHandleобработчик события, чтобы изменить его Application.MainFormHandleво время выполнения (но не Application.MainForm ). MainFormHandleзатрагивает такие вещи, как владелец модальных всплывающих диалогов.

Дополнительная информация Application.MainFormOnTaskbarи недостатки ее отключения: это становится сложным в спешке. Краткая версия находится в документах VCL , в которых объясняется, что некоторые новые функции Windows (например, миниатюры на панели задач), которые были введены в Vista, требуют MainFormOnTaskbar := True. В этом обсуждении SO есть намного больше фоновых чтений .


2

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

Код выглядел примерно так:

procedure TfrmLogin.btnLoginClick(Sender: TObject);
begin
    frmMainWork := TfrmMain.Create(Application);
    try
        Pointer((@Application.MainForm)^) := frmMainWork;
        frmLogin.Hide;
        frmMainWork.ShowModal;
    finally
        Pointer((@Application.MainForm)^) := frmLogin;
        frmLogin.Show;
        FreeAndNil(frmMainWork);
    end;

end;

надеюсь это поможет :-)

формы, Дельфы, VCL, панель задач, Дельфы-XE6,
Похожие вопросы