Aktywacja jednej formy

0

Witajcie :)

Zauważyłem, że gdy mamy jednocześnie wyświetlone więcej niż jedną formę, to gdy zasłonimy je przez okno pochodzące z innej aplikacji, to po próbie aktywowania poprzez kliknięcie (ale nie tylko) jednej formy wszystkie pozostałe formy również wychodzą na wierzch. Chciałbym uzyskać efekt taki, że tylko aktywowana forma ujawnia się spośród reszty okien.

Zakładam, że to będzie coś związanego z CreateParams.

Delphi, środowisko Borland/Embarcadero.

Pozdrawiam i dziękuję za pomoc.

0

może showmodal lub ustawienie właściwości stayonthetop w oknie niemodalnym?

0

ShowModal odpada, gdyż potrzebny jest dostęp do wszystkich form. FsStayOnTop nie pomaga. Gdy chcę aktywować tylko jedną formę to co prawda forma aktywuje się, ale przy okazji wszystkie inne okna należące do aplikacji wypływają na wierzch... Polecam utworzenie nowego projektu z dwoma formami i wywołanie drugiej przez Form2.Show.
Pozdrawiam.

0

Ja bym to rozwiązał tak, o ile dobrze zrozumiałem co autor wątku chce osiągnać.

Kod głównej formatki:

//...
uses
  Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender : TObject);
begin
  Form1.Hide;
  Form2.Show;
end;
//...

Kod pokazywanej formatki w pokazywanej przez kliknięcie na button:

//..
type
  TForm2 = class(TForm)
  private
    procedure WMSysCommand(var Msg : TMessage); message WM_SYSCOMMAND;
  public
  end;

var
  Form2 : TForm2;

implementation

uses
  Unit1;

{$R *.dfm}

procedure TForm2.WMSysCommand(var Msg : TMessage);
begin
  case Msg.WParam of
    SC_MINIMIZE :
      begin
        Application.Minimize;
      end;
    SC_CLOSE :
      begin
        Form2.Hide;
        Form1.Show;
      end;
  else
    begin
      inherited
    end;
  end;
end;
//...
0

Nie do końca się zrozumieliśmy, ale dziękuję za chęci :)

Wytłumaczę to jeszcze raz:

Tworzymy nowy projekt oraz nową formę.
Do formy pierwszej dodajemy Buttona z kodem Form2.Show następnie kompilujemy projekt.

Po uruchomieniu klikamy na button i mamy dwie widoczne formy.
Nie zmieniając nic przechodzimy do innego okna jakieś aplikacji np przeglądarki internetowej, folderu tak, aby dwie nasze formy znajdowały się pod danym oknem, ale niech trochę wystają po bokach np.

Czyli mamy sytuacje: Okno folderu aktywne a pod nim dwie nasze formy gdzie jedna trochę wystaje by można było ją chwycić.

Klikamy na ten wystający fragment i tadam, wraz z klikniętą formą na wierzch idą również pozostałe okna naszej aplikacji :) <- tego efektu chcę właśnie uniknąć, wraz z kliknięciem próbuję zrobić by tylko kliknięta forma się uaktywniła.

Mam nadzieję, że teraz będzie wszystko jasne.
Pozdrawiam.

0

To nic innego, jak sprawdzanie w wątku czy okno o uchwycie naszych formatek nie są na wierzchu, nie przychodzi mi do głowy. Zrob sobie do tego celu klasę lub tablicę swoich formatek, jeżeli masz ich więcej. Na szybko kod sprawdziłem. Działa jak chcesz. I dla pewnosći na Form2 też umiściłem Button, który nic nie robi. Jednak jest to ważne do testów. Ponieważ komunikat WM_KILLFOCUS ma miejsce tylko jak kontrolka traci focus, a kiedy są na niej inne komponenty, to te zdarzenie nie zachodzi. Może jest inny sposób aby to osiągnąc, ale to ktoś inny tutaj Ci to może doradzi. Ewentualnie pokombinuj dalej sam. Wiele da się osiągnąc, trzeba tylko chcieć :)

//...
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm2 = class(TForm)
    Button1 : TButton;
    procedure FormActivate(Sender : TObject);
  public
    procedure WMSysCommand(var Msg : TMessage); message WM_SYSCOMMAND;
  end;

var
  Form2 : TForm2;

implementation

uses
  Unit1;

{$R *.dfm}

var
  ThreadH : Thandle;

procedure TForm2.WMSysCommand(var Msg : TMessage);
begin
  case Msg.WParam of
    SC_MINIMIZE :
      begin
        Application.Minimize;
      end;
    SC_CLOSE :
      begin
        SuspendThread(ThreadH);
        Form2.Hide;
        Form1.Show;
      end;
  else
    begin
      inherited
    end;
  end;
end;

procedure FocusThreadProc;
begin
  while True do
  begin
    if (GetForegroundWindow <> Form2.Handle)
    and (GetForegroundWindow <> Form1.Handle) then
    begin
      Form1.Hide;
    end;
    Sleep(100);
  end;
end;

procedure TForm2.FormActivate(Sender : TObject);
var
  ThrId : Cardinal;
begin
  ThreadH := CreateThread(nil, 0, @FocusThreadProc, nil, 0, ThrId);
end;

end.

W pierwszej formatce pod buttonem jest tylko i wyłącznie kod Form2.Show.

0

Olesio bardzo doceniam Twoją pomoc, za którą bardzo Ci dziękuję, ale niestety chyba się jeszcze nie zrozumieliśmy.

Przedstawię problem za pomocą screenów:

Screen 1:
Dwie formy wyświetlone na ekranie

user image

Screen 2:
Zasłaniamy je oknem pochodzącym z innej aplikacji:

user image

Screen 3:
Po kliknięciu gdziekolwiek na formie 1 bądz drugiej (na ten wystający fragment) dostajemy coś takiego:

user image

Czyli wraz z klikniętą formą uaktywaniają się pozostałe okna aplikacji

Screen 4:
Efekt jaki chcę uzyskać:

user image

Czyli tylko kliknięte okno jest wypychane na wierzch.

Popróbuje coś z Twoim pomysłem, może uda mi się to przerobić.

Pozdrawiam i dziękuję. :)

0

@Szymonss: pokaż jak otwierasz to drugie okno.
Nie podawaj mu parenta.

0

Tworzę nowy projekt, następnie dodaję nową formę, do Unitu 1 w uses pod implementation dodaje unit 2. Formę drugą wywołuję po prostu pod buttonem jako Form2.Show.
Więcej kodu nie wpisuję.

0

@Szymonss: teraz rozumiem jaki efekt chcesz uzyskać. Jednak nie za bardzo mogę wymyśleć, jak to zrealizować. Wiem, że taki efekt z formatkami dzieje się kiedy pracujemy pod IDE Dephi i na przykład przełączamy się tak z okna kodu. Być może @Azarien lub ktoś inny coś więcej Tobie podpowie. Szkoda, że w pierwszym postcie nie chciałeś dać obrazkowej instrukcji, ponieważ tylko ja odpowiadałem na Twoj post, a jego treść rozumiałem inaczej. I teraz jak wszystko jest jasne, to może ktoś jeszcze Tobie podpowie jakieś konkretne rozwiązanie.

0

no nic, niby problem wydaje się banalny a jednak może stwarzać problemy :) bardzo Ci w każdym razie olesio dziękuję za pomoc. Myślałem, że nie będzie problemów ze zrozumieniem, bo tak to bym dał już opis screenowy na samym początku co zaoszczędziłoby Ci pracy.
Próbowałem nawet dodawać osobną belkę na pasku zadań do każdej z form, ale to też nie jest to.
Pozdrawiam.

1
procedure TForm1.CreateParams(var Params:TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := 0;
end;
0

Faktycznie, to najprostsze rozwiązanie. I działa. Także pytający dobrze przewidział, że konieczna będzie operowanie na CreateParams, a @Azarien już post wcześniej podpowiedział, co należy zrobić.

0

hmm a to dziwne...
mam taki kod:

Forma 1:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
end;

end.

Forma 2:

 
unit Unit2;

interface

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

type
  TForm2 = class(TForm)
  private
    { Private declarations }
    procedure CreateParams(var Params: TCreateParams);
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

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

end.

oraz

 
program Project1;

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

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

i nadal jest ten sam problem, bez żadnych zmian. Próbowałem również wrzucać CreateParams do formy pierwszej, drugiej jak również i tu i tu.
Dodam, że projekt jest tworzony na czysto, nic w Object Inspectorze nie zostało zmieniane. Jeżeli u @olesio oraz @Azarien działa dobrze, to co ja robię źle? :P

Pozdrawiam.

1

Sprawdziłem. I pod Delphi 7 zarówno jeżeli damy ten kod dla TFrom1 czy dla TForm2 u mnie działa ok. Testowałem w ten sposób, że przesumąłe, formatki w dól, żeby wystawały pod oknem kodu. i Później kliknąłe na przykład na TForm1. Druga formatka została pod oknem edytora kodu. Co wcześniej przy moich kombinacjach się nie działo. Używasz jakiegoś nowszego Delphi, które w pierwszej chwili sugerowało mi Lazarusa po tej sekcji uses. Jedynie czego brakuje to override po deklaracji procedury. A tak to powinno działać. Jeżeli dobrze pamiętam efekt, jaki oczekiwałeś. Dlatego po sprawdzeniu rozwiązania @Azarien'a postanowiłem je zatwierdzić.

0

dodałem

override

zadziało. Bardzo dziękuję wszystkim biorącym udział w tym temacie.
Problem uważam za zamknięty
Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1