Активация нескольких окон приложения не работает правильно - PullRequest
3 голосов
/ 29 апреля 2009

У меня есть приложение Delphi, в котором основной формой является браузер документов. Когда пользователь открывает документ, мы открываем окно редактора. Мы хотим, чтобы у каждого редактора была кнопка на панели задач, а также основная форма. Для этого я применил обычный код (ниже), но когда я нажимаю на основную форму после использования окна редактора, редактор остается сверху, а фокус находится на главной форме. Я не могу понять, что вызывает такое поведение.

Настройка сцены: я открываю основную форму и форму документа.

  1. Нажмите на другое приложение, нажмите на основную форму, основная форма остается сфокусированной. (Ведёт себя как положено.)

  2. Нажмите на форму документа, нажмите на основную форму, форма документа приходит задом наперед, но показано неактивным. (Изображение показывает результат)

альтернативный текст http://www.matthew -jones.com / temp_xfer / titlebarfailure.jpg

Первый шаг, это Delphi 2007, и у меня в проекте:

Application.MainFormOnTaskBar := True;

Для основной формы у меня нет дополнительного кода.

Для формы документа у меня есть

procedure TCommonEditForm.CreateParams(var params: TCreateParams);
begin
  inherited;
  params.WndParent := 0; // GetDeskTopWindow; no diff
end;

Я пытался разобраться, есть ли сообщение, которое делает это, но не могу найти что-нибудь подходящее. Я искал код для чего-либо связанного с «активировать». Подсказки приветствуются!

Ответы [ 3 ]

6 голосов
/ 29 апреля 2009

Мое приложение работает так, как вы описываете. Вот подход, который я выбрал. Я хотел бы найти более простой подход, но никогда не делал.

Я начал с чтения этих статей. Это первая отличная статья Питера Белоу:

http://groups -beta.google.com / группа / borland.public.delphi.winapi / сообщ / e9f75ff48ce960eb? Гектолитров = еп

Другая информация также была найдена здесь, однако это не оказалось правильным решением: для моего использования: http://blogs.teamb.com/DeepakShenoy/archive/2005/04/26/4050.aspx

В конце концов вот что я закончил.

Мой экран-заставка используется в качестве основной формы приложения. Основная форма имеет особую привязку к объекту приложения. Использование всех вторичных форм дает мне то поведение, которое я искал.

В каждой форме на панели задач я перезаписываю CreateParams. Я делаю это в моих формах редактирования и в том, что пользователи видят как «основную форму»

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

Моя «Основная» форма, если говорить о Delphi, загружает истинную основную форму в свою функцию Activitate. Я использую переменную-член, чтобы отслеживать первую активацию. Затем в конце функции я скрываю форму всплеска, но не закрываю ее. Это было важно для меня, потому что, если пользователь редактировал документ и закрывал основную форму, я не хотел, чтобы экраны редактирования закрывались одновременно. Таким образом, все видимые формы обрабатываются одинаково.

    if FFirstActivate = false then
      exit;

    FFristActivate := false;

    /* 
       Main Load code here 
       Update Splash label, repaint
       Application.CreateForm
       etc.
    */


    // I can't change visible here but I can change the size of the window
    Self.Height := 0;
    Self.Width := 0;
    Self.Enabled := false;

    //  It is tempting to set Self.Visible := false here but that is not
    // possible because you can't change the Visible status inside this
    // function.  So we need to send a message instead.
    ShowWindow(Self.Handle, SW_HIDE);

  end;

Но есть еще проблема. Вам нужно закрыть главное окно / заставку, когда все остальные формы закрыты. У меня есть дополнительная проверка в моих процедурах закрытия для Parent <> nil, потому что я использую формы как плагины (в моих целях они работают лучше, чем фреймы).

Мне не очень понравилось использовать событие Idle, но я не замечаю, что это перетаскивание процессора.

{
  TApplicationManager.ApplicationEventsIdle
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.ApplicationEventsIdle(Sender: TObject;
  var Done: Boolean);
begin

  if Screen.FormCount < 2 then
    Close;
end;

{
  TApplicationManager.FormCloseQuery
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
var
  i: integer;
begin

  for i := 0 to Screen.FormCount - 1 do
  begin
    if Screen.Forms[i] <> self then
    begin
      // Forms that have a parent will be cleaned up by that parent so
      // ignore them here and only attempt to close the parent forms
      if Screen.Forms[i].Parent = nil then
      begin
        if Screen.Forms[i].CloseQuery = false then
        begin
          CanClose := false;
          break;
        end;
      end;
    end;
  end;

end;

{
  TApplicationManager.FormClose
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.FormClose(Sender: TObject;
  var Action: TCloseAction);
var
  i: integer;
begin

  for i := Screen.FormCount - 1 downto 0 do
  begin
    if Screen.Forms[i] <> self then
    begin
      // Forms that have a parent will be cleaned up by that parent so
      // ignore them here and only attempt to close the parent forms
      if Screen.Forms[i].Parent = nil then
      begin
        Screen.Forms[i].Close;
      end;
    end;
  end;

end;

Это до сих пор хорошо мне служило. Я сделал небольшое изменение для Vista, потому что значок для моего экрана «Main / Splash» все еще показывался. Я не помню, что это было, хотя. Возможно, мне не нужно устанавливать ширину, высоту, включать и отправлять сообщение о скрытии на заставке. Я просто хотел убедиться, что он не появился: -).

Необходимо иметь дело с событиями закрытия. Если я правильно помню, это было необходимо, когда Windows отправил сообщение о выключении. Я думаю, что только основная форма получает это сообщение.

0 голосов
/ 29 апреля 2009

возможно, добавьте это в createparams

Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;

или попробуйте это в любом месте кода. Я предварительно использую его в событиях форм .OnCreate.

SetWindowLong(Wnd, GWL_EXSTYLE, 
  GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ;

Недостатком этого является то, что если основная форма свернута, другие формы тоже прячутся, но восстанавливаются, когда основная форма делает.

0 голосов
/ 29 апреля 2009

Извините, если это действительно глупо, но вы не установили для formstyle значение fsStayOnTop? Это объяснило бы это поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...