Frage

Ich habe eine Delphi -Anwendung mit einem Dokumentbrowser als Hauptformular. Wenn der Benutzer ein Dokument öffnet, öffnen wir ein Editorfenster. Wir möchten jeden Editor mit einer Schaltfläche in der Taskleiste sowie in der Hauptform haben. Ich habe den normalen Code dazu angewendet (unten), aber wenn ich nach der Verwendung des Editor -Fensters auf das Hauptformular klicke, bleibt der Editor oben, während der Fokus auf dem Hauptformular liegt. Ich kann nicht herausfinden, was dieses Verhalten verursacht.

Bühneneinstellung: Ich öffne das Hauptformular und ein Dokumentformular.

  1. Klicken Sie auf eine andere App. Klicken Sie auf das Hauptformular, das Hauptformular bleibt fokussiert. (Wie erwartet sich verhalten.)

  2. Klicken Sie auf das Dokumentformular, klicken Sie auf das Hauptformular, das Dokumentformular kommt wieder nach vorne, ist jedoch inaktiv. (Bild zeigt Ergebnis)

ALT-Text http://www.matthew-jones.com/temp_xfer/titlebarfailure.jpg

Erster Schritt, das ist Delphi 2007, und ich habe im Projekt:

Application.MainFormOnTaskBar := True;

Für das Hauptformular habe ich keinen zusätzlichen Code.

Für das Dokumentformular habe ich

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

Ich habe versucht herauszufinden, ob es eine Nachricht gibt, die dies geschieht, aber nichts angemessenes finden kann. Ich habe den Code nach irgendetwas mit "aktivieren" durchsucht. Hinweise willkommen!

War es hilfreich?

Lösung

Meine Anwendung funktioniert in der Art und Weise, wie Sie beschreiben. Hier ist der Ansatz, den ich gewählt habe. Ich hätte gerne einen einfacheren Ansatz gefunden, aber nie.

Ich habe mit diesen Artikeln angefangen. Dieser erste ist ein großartiger Bericht von Peter unten:

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

Weitere Informationen wurden auch hier gefunden, dies war jedoch keine gültige Lösung: Für meine Verwendung: http://blogs.teamb.com/deepakshenoy/archive/2005/04/26/4050.aspx

Schließlich ist hier, was ich am Ende habe.

Mein Begründungsbildschirm ist gleichzeitig das Hauptformular für Anwendungen. Die Hauptform hat eine spezielle Bindung an das Anwendungsobjekt. Wenn ich alle sekundären Formen benutze, habe ich das Verhalten, nach dem ich gesucht habe.

In jeder Form, die ich in der Taskleiste möchte, überschreibe ich CreateParams. Ich mache dies in meinen Bearbeitungsformularen und was die Benutzer als "Hauptform" ansehen,

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

Meine "Haupt" -Form, soweit Delphi sich betrifft, lädt die wahre Hauptform in seiner Aktivitenfunktion. Ich verwende eine Mitgliedsvariable, um die erste Aktivierung im Auge zu behalten. Dann verstecke ich am Ende der Funktion die Spritzform, aber nicht schließen Sie sie. Dies war für mich wichtig, denn wenn der Benutzer ein Dokument bearbeitete und das Hauptformular schloss, wollte ich nicht, dass die Bearbeitungsbildschirme gleichzeitig geschlossen werden. Auf diese Weise werden alle sichtbaren Formen gleich behandelt.

    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;

Aber es gibt immer noch ein Problem. Sie benötigen das Haupt-/Floßenfenster, um zu schließen, wenn alle anderen Formulare geschlossen sind. Ich habe eine zusätzliche Überprüfung in meinen engen Routinen für Eltern <> nil, da ich Formulare als Plugins verwende (form meine Zwecke, die sie besser funktionieren als Frames).

Ich habe das Leerlaufereignis nicht wirklich gern verwendet, aber ich bemerke nicht, dass dies ein Zug der CPU ist.

{
  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;

Das hat mir bisher gut gedient. Ich habe eine kleine Veränderung für Vista vorgenommen, weil das Symbol für meinen "Main/Splash" -Screen immer noch angezeigt wurde. Ich erinnere mich nicht, was das war. Ich muss wahrscheinlich keine Breite, Höhe, aktiviert einstellen und die Meldung ausblenden auf dem Begrüßungsbildschirm senden. Ich wollte nur sicherstellen, dass es nicht auftaucht :-).

Der Umgang mit den engen Ereignissen war notwendig. Wenn ich mich richtig erinnere, war dies erforderlich, als Windows eine Shutdown -Nachricht gesendet hat. Ich denke, nur die Hauptform erhält diese Nachricht.

Andere Tipps

Tut mir leid, wenn das wirklich dumm ist, aber Sie haben nicht den Formsindyle auf fSstayontop, oder? Dies würde dieses Verhalten erklären.

Fügen Sie dies vielleicht in die CreateParams hinzu

Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;

Oder versuchen Sie es überall im Code. Ich benutze es präsent auf den Formularen .oncreate Event.

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

Der Nachteil ist, dass, wenn die Hauptform minimiert wird, dass sich die anderen Formen auch verstecken, aber wiederherstellen, wenn die Hauptform es tut.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top