Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Отображение Application.Icon  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11984
В OnCreate главной формы создаются дочерние формы, которые докаются на TabSheet. Код примерно такой
procedure TMainForm.FormCreate(Sender: TObject);
begin
  ..........
  ChildForm := TChildForm.Create(Self);
  ChildForm.ManualDock(TabSheet1);
  ChildForm.Show;
  .........
end;


Проблема: при создании формы в Vcl.Forms вызывается такой код
+
constructor TCustomForm.Create(AOwner: TComponent);
begin
    ............
    InitializeNewForm;
    ............
end;

procedure TCustomForm.InitializeNewForm;
begin
  ............
  Screen.AddForm(Self);
  ............
end;

procedure TScreen.AddForm(AForm: TCustomForm);
begin
  FCustomForms.Add(AForm);
  if AForm is TForm then
  begin
    FForms.Add(AForm);
    Application.UpdateVisible;
  end;
end;

procedure TApplication.UpdateVisible;

  procedure SetVisible(Value: Boolean);
  const
    ShowFlags: array[Boolean] of Word = (
      SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_HIDEWINDOW,
      SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_SHOWWINDOW);
  begin
    // Dont auto-update visibility if somebody else has hidden app window
    if (IsWindowVisible(Handle) = AppVisible) and (AppVisible <> Value) then
    begin
      if MainFormOnTaskBar and not AppVisible then
        SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_NOACTIVATE);
      SetWindowPos(Handle, 0, 0, 0, 0, 0, ShowFlags[Value]);
      AppVisible := Value;
    end;
  end;

var
  I: Integer;
  Form: TForm;
begin
  if Handle <> 0 then
  begin
    for I := 0 to Screen.FormCount - 1 do
    begin
      Form := Screen.Forms[I];
      if Form.Visible and ((Form.ParentWindow = 0) or not Form.HandleAllocated or
        not IsChild(Form.Handle, Form.ParentWindow)) then
      begin
        SetVisible(True);
        Exit;
      end;
    end;
    SetVisible(False);
  end;
end;
Теперь что получается: при создании очередной формы Application.UpdateVisible обнаруживает созданную раннее форму, у которой уже установлено Visible := True и показывает окно Applacation на таскбаре. Но без иконки.

Проблема решается одним из трех способов

1. Установка в дизайнере MainForm.Visible := True;
2. Установка Application.MainFormOnTaskBar := True;
3. Вызов перед Application.Run
ShowWindow(Application.Handle, SW_HIDE);
ShowWindow(Application.Handle, SW_SHOW);

Delphi 10.3.1, Windows 10 1909

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

Вопрос: куда девается иконка и какие есть цивилизованные способы решения проблемы?

Сейчас решаю передергиванием ShowWindow

С уважением, Vasilisk
20 июл 20, 20:26    [22170680]     Ответить | Цитировать Сообщить модератору
 Re: Отображение Application.Icon  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11984
Вот тестовый пример
procedure TForm1.FormCreate(Sender: TObject);
var
  LForm: TForm;
begin
  LForm := TForm2.Create(Self);
  LForm.ManualDock(PageControl1);
  LForm.Show;
  //
  LForm := TForm2.Create(Self);
  LForm.ManualDock(PageControl1);
  LForm.Show;
  //
  Sleep(1000);
end;

+ dpr
program TestIcon;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
наличие слипа обязательно. В реальной программе слип заменен долгой загрузкой из базы
21 июл 20, 18:05    [22171206]     Ответить | Цитировать Сообщить модератору
 Re: Отображение Application.Icon  [new]
alekcvp
Member

Откуда:
Сообщений: 2263
_Vasilisk_,

А если вынести вызов .Show в событие OnShow или OnActivate? Или вообще на короткий таймер (100мс), запускаемый из OnActivate?
И вообще разве для таких вещей не фреймы были придуманы?

Сообщение было отредактировано: 21 июл 20, 19:39
21 июл 20, 19:41    [22171241]     Ответить | Цитировать Сообщить модератору
 Re: Отображение Application.Icon  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 31323
alekcvp
И вообще разве для таких вещей не фреймы были придуманы?
вот не надо тут про фреймы.
оно задумано было хорошо, но реализовано было как обычно - криво.
а вообще, речь не об этом.
21 июл 20, 21:13    [22171276]     Ответить | Цитировать Сообщить модератору
 Re: Отображение Application.Icon  [new]
alekcvp
Member

Откуда:
Сообщений: 2263
Мимопроходящий
но реализовано было как обычно - криво.

... поэтому будет делать ещё кривее на формах?..
21 июл 20, 21:20    [22171284]     Ответить | Цитировать Сообщить модератору
 Re: Отображение Application.Icon  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11984
alekcvp
А если вынести вызов .Show в событие OnShow или OnActivate?
Да костылей можно много придумать.

Тут хочется понять почему Windows так себя ведет. С точки зрения Delphi вызов Application.UpdateVisible на создание формы конечно лишний. Да и проверка Form.ParentWindow = 0 для докнутых формах неверна. Но на ранних версиях Windows все работало

alekcvp
И вообще разве для таких вещей не фреймы были придуманы?
Вообще-то не совсем. Некоторые формы могут потом андокиться и превращаться в обычные окна.
22 июл 20, 15:18    [22171760]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить