Autor Beitrag
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10184
Erhaltene Danke: 1259

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 15.12.06 17:10 
Moin!

Ich habe das Hauptformular meiner Anwendung mit
ausblenden Delphi-Quelltext
1:
Application.ShowMainForm := FALSE; // im FormCreate					

ausgeblendet.

Wenn der Benutzer sich abmeldet, möchte ich auf das WM_QUERYENDSESSION reagieren und habe entsprechenden Code dafür (der auch funktioniert, ist also getestet).

Allerdings wird die Ereignis-Methode für das WM_QUERYENDSESSION nur dann aufgerufen, wenn ich das Formular anzeige (zu Debugzwecken getestet). Im ausgeblendeten Zustand bekomme ich offenbar keine Nachricht... ? :nixweiss:

Also MSDN durchstöbert, und die Info gefunden, in diesem Fall mit SetConsoleCtrlHandler zu arbeiten. Aber auch hier bekomme ich kein CTRL_LOGOFF_EVENT zugestellt. :|

Wie kann ich das ändern, also auch im versteckten Zustand des Formulars die Abmeldungsnachricht erhalten!? (ach ja, ich bekomme natürlich genausowenig ein WM_ENDSESSION, wenn das Formular ausgeblendet ist...)

Danke schonmal für eure Vorschläge. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10184
Erhaltene Danke: 1259

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 16.12.06 21:34 
Moin!

:? Scheint also bisher noch keiner Probleme damit gehabt zu haben oder das ganze anders zu lösen... :gruebel:

OK, alternatives Szenario: ich möchte nicht, dass der Benutzer ein Formular, Taskleisteneintrag oder TNA-Icon sieht (Taskmanager ist egal, darf bzw. soll dort ruhig angezeigt werden). Die Anwendung wird bei der Anmeldung automatisch mitgestartet und soll bei der Abmeldung bzw. beim Runterfahren vor dem Beenden noch Daten in Sicherheit bringen. Dazu muss ich aber irgendwie von diesen Ereignissen in Kenntnis gesetzt werden. Wie kann ich das am Besten lösen?

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
thkerkmann
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 20

Windows 7
Delphi 2010 Professional
BeitragVerfasst: Sa 16.12.06 22:12 
Nabend,

also ich mach das so....

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure HideFromTaskBar;
begin
  ShowWindow(Application.Handle, SW_HIDE);
  SetWindowLong(Application.Handle, GWL_EXSTYLE,
    GetWindowLong(Application.Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
  ShowWindow(Application.Handle, SW_SHOW);
end;


die rufe ich im FormCreate auf - dann gibt es keinen Button in der Taskleiste.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.OnCreate(Sender:tObject);
begin
  HideFromTaskBar;
end;


Wenn Du jetzt noch im OnShow beim ersten mal ein Hide machst, dann ist das Programm weg.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.OnShow (Sender:TObject);
const
  firstTime: boolean = true;
begin
  if firstTime then
  begin
    firstTime := false;
    Hide;
  end;
end;

Es bekommt aber alle QueryEndsession und EndSession Messages. Ich benutze das auf ähnliche Weise wie Du es vor hast.

Gruss

Thomas

Moderiert von user profile iconmatze: Code- durch Delphi-Tags ersetzt
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10184
Erhaltene Danke: 1259

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 18.12.06 12:01 
Moin!

Danke für den Vorschlag. ;)

Ich habe es jetzt so "gelöst" (gleich mehr dazu):
ausblenden Delphi-Quelltext
1:
ShowWindow(GetWindow(Form1.Handle, GW_OWNER), SW_HIDE); // im FormCreate					

um den Taskleisteneintrag auszublenden. @user profile iconthkerkmann: Warum machst du das anders?

Um das Fenster selbst auszublenden, führe ich dann noch genau einmal aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.FormPaint(Sender: TObject);
begin
  Hide; // Fenster ausblenden
  OnPaint := NIL// nur einmal ausführen
end;


Das funktioniert auch auf die gewünschte Weise, ich erhalte jetzt auch die "interessanten" Nachrichten. So gesehen, ist das Problem damit gelöst.

Aaaaber... ;) bei dieser Variante wird natürlich auf sehr schnellen bzw. eher langsamen Maschinen (interessanterweise auf "mittelmäßigen" nicht) kurz der Fensterrahmen gezeichnet. Das ist nicht wirklich schlimm, aber in meinen Augen unnötig. :P

Hat jemand vielleicht doch noch eine andere Lösung bzw. Vorschlag, wie man das lösen könnte?

Ich habe auch noch alternativ mit einer eigenen Fensternachricht und PostMessage gearbeitet, um das Hide auszulösen. Aber offensichtlich kommt die eigene Nachricht noch sehr viel später in der MessageLoop an (bzw. ist diese bereits mit entsprechenden Nachrichten gefüllt), so dass das Fenster sogar einmal komplett gezeichnet wird, bevor das Hide "Wirkung" zeigt. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.


Zuletzt bearbeitet von Narses am Mo 18.12.06 16:02, insgesamt 1-mal bearbeitet
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 18.12.06 15:57 
Du müsstest ein unsichtbares Hintergrundfenster erstellen, dann bekommst du auch alle Messages. Sieh dir mal den Quelltext der TTimer Komponente an! Die macht genau das...

Dann brauchst du dein Hauptfenster nicht für den Empfang der Botschaften, weil du einen eigenen Message Loop für dieses Fenster hast.
// EDIT: ich meine natürlich ein Fenster nicht als visuelles Formular im Sinne von Delphi... (Das schreibe ich weniger für dich als vielmehr für andere, die dies hier später lesen ;-), dir ist das ja wahrscheinlich klar...)

Und dann solltest du natürlich die WndProc nutzen und nicht die Delphi Message Functions. Ich hatte damit schon öfter Probleme (ich weiß nicht, ob es an mir lag ;-)). Abgesehen davon kannst du dort auch ganz leicht etwas abfangen und nicht weiterleiten. Zum Beispiel in einer eigenen Komponente die WM_ERASEBACKGROUND Message, damit die Controls nicht mehr so flackern...
Narses Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10184
Erhaltene Danke: 1259

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 19.12.06 15:49 
Moin!

user profile iconjaenicke hat folgendes geschrieben:
Du müsstest ein unsichtbares Hintergrundfenster erstellen, dann bekommst du auch alle Messages.

Klar, auf die "einfachen" Sachen kommt man immer zuletzt... user defined image

user profile iconjaenicke hat folgendes geschrieben:
Dann brauchst du dein Hauptfenster nicht für den Empfang der Botschaften, weil du einen eigenen Message Loop für dieses Fenster hast.

Gesagt - getan, ein WindowHandle besorgt, MessageCallback-Methode registriert, aber leider... gleiches Ergebnis: ist mit Application.ShowMainForm := FALSE; das Hauptfenster der Applikation ausgeblendet, kriegt auch mein Handle kein WM_QUERYENDSESSION... :? :(

user profile iconjaenicke hat folgendes geschrieben:
Und dann solltest du natürlich die WndProc nutzen und nicht die Delphi Message Functions.

Also, wie vorgeschlagen, Plan B: die WndProc des Hauptformulars überschrieben: leider leider, schon wieder, kein WM_QUERYENDSESSION ohne Hauptformular... :nixweiss:

Ich bin nicht so firm in der VCL, was passiert denn da eigentlich im Detail, wenn man kein Hauptformular anzeigen lässt... :gruebel:

Ich habe also aktuell den "Workaround" laufen, der zwar machmal einen Fensterrahmen aufblitzen lässt, aber dafür die Nachricht kriegt... :|

Noch irgendwelche Vorschläge? ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 19.12.06 16:07 
Warum überhaupt eine Form, wenn man die doch nicht sieht?

Wie schon gesagt wurde, mach eine NonVCL Anwendung mit einem unsichtbaren Hauptfenster.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 20.12.06 21:31 
Poste doch bitte mal ein Projekt, in dem das so drin ist. Dann teste ich das selbst mal. Soweit ich das hier sehe (in einem Überwachungstool so ähnlich wie WinSight) sollte nämlich die Message durchaus auch ankommen, wenn das Hauptfenster ausgeblendet ist. Aber ich hab keine Lust extra ein Programm zu schreiben um zu testen obs auch in der WndProc ankommt bzw. warum nicht. ;-)

Aber ich stöbere mal im MSDN...
Raffo
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 300



BeitragVerfasst: Mi 20.12.06 21:51 
ich habs mal so gelöst da das hauptformular ganz normal sichtbar ist - aber in oncreate die window position auf -4000 gesetzt wird - erst danach die main form ausblenden, dann kriegst du auch wm-qweryendsession
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 20.12.06 22:31 
Ja, an sowas habe ich auch schon gedacht. Aber das lässt sich auch eleganter lösen. Deshalb habe ich zu solchen Notlösungen auch noch nix gesagt, da kann man ja viel in der Richtung machen, damit man gar nix vom Hauptfenster sieht.

BTW: Diese Lösung würde bei mir nix bringen, da ich mehrere Monitore habe und das ganze so eingestellt habe, dass neue Fenster automatisch auf die aktuell aktivierte Anzeigefläche gelegt werden. Deshalb würde das auf den ersten Monitor verschoben und wäre doch kurz zu sehen... Aber das ist natürlich ein Ausnahmefall...

Jedenfalls ists ja auch sehr interessant was da im MSDN zu diesen ganzen Sachen steht. Angesehen hatte ich mir das mal im Hinblick auf die deutlichen Änderungen bei Vista in diesem Zusammenhang.
Jedenfalls gelten manche Sachen nur für Anwendungen mit Top-Level Fenster. Die Frage ist jetzt: Wie sagt man Windows allgemein, dass die Anwendung auch ohne Top-Level Fenster als solche behandelt werden möchte? Unter Vista kein Problem: Man registriert einfach einen String, den man als Grund für ein Blockieren des Herunterfahrens durch die Anwendung dem User zeigen möchte.
Diesen benutzt Vista dann um dem Benutzer zu sagen, dass die Anwendung im Moment noch nicht herunterfahren lassen möchte (was man dann natürlich erzwingen kann). Dann wird die Anwendung so behandelt als hätte sie ein Top-level Fenster.

Das heißt doch aber wohl, dass das erzeugte unsichtbare Fenster für den Nachrichtenempfang ein Top-Level Fenster sein muss, damit es geht. Die Frage ist: Wie macht man daraus eins? Das Hauptfenster ist ja eins, aber ein Fenster muss doch wohl nicht zuerst einmal sichtbar sein, damit es Top-Level sein kann, oder?