Некорректная активация нескольких приложений Windows

StackOverflow https://stackoverflow.com/questions/802279

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть приложение на 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;

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

Это было полезно?

Решение

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

Я начал с чтения этих статей.Это первое из них - отличная статья Питера, приведенная ниже:

http://groups-beta.google.com/group/borland.public.delphi.winapi/msg/e9f75ff48ce960eb?hl=en

Здесь также была найдена другая информация, однако это не оказалось правильным решением:для моего использования: 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;

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

Мне не очень понравилось использовать событие 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 отправила сообщение о завершении работы.Я думаю, что только основная форма получает это сообщение.

Другие советы

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

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

Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top