Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Fenster sichtbar machen (https://www.delphipraxis.net/192237-fenster-sichtbar-machen.html)

idefix2 1. Apr 2017 18:44

Fenster sichtbar machen
 
Ein Programm soll periodisch eine Webcam überwachen, und damit das funktioniert, muss das entsprechende Fenster im Vordergrund sichtbar sein (Das Programm läuft auf einem File Server, auf dem normalerweise nicht gearbeitet wird, also stört das nicht wirklich).

Solange man das Programm laufen lässt und nichts anrührt, funktioniert alles wunderbar, aber wenn jemand das Programmfenster (irrtümlich) minimiert, geht nichts mehr. Deshalb wollte ich zu Beginn jedes Zyklus vor dem Auslesen der Kamera per
Delphi-Quellcode:
windowstate:=wsnormal;
sicherstellen, dass das Fenster nicht minimiert ist. Bloß kümmert sich das Fenster nicht im geringsten um diese Anweisung. Wenn es minimiert war, dann bleibt das so. Was muss man noch machen, um zu erreichen, dass ein minimiertes Programmfenster (das Hauptformular der Anwendung) wieder im Zustand wsnormal angezeigt wird?

a.def 1. Apr 2017 18:50

AW: Fenster sichtbar machen
 
Guck mal hier. Ich mache das immer hiermit. Funktioniert von Windows XP bis Windows 10.

http://www.swissdelphicenter.com/de/showcode.php?id=261

idefix2 1. Apr 2017 19:15

AW: Fenster sichtbar machen
 
Danke, gleich ausprobiert, leider hilft mir das auch nicht weiter. Diese Funktionen bringen das Fenster in den Vordergrund, wenn es vorher nicht minimiert im Hintergrund war. Aber wenn das Fenster minimiert ist, bleibt es minimiert.

EWeiss 1. Apr 2017 19:41

AW: Fenster sichtbar machen
 
Zitat:

Aber wenn das Fenster minimiert ist, bleibt es minimiert.
Verhindere doch einfach das man es minimieren kann.
Also sobald jemand das Fenster minimieren will setze es auf Hide.

und auf visible wenn du es in den Vordergrund bringen willst.

gruss

Aviator 1. Apr 2017 19:42

AW: Fenster sichtbar machen
 
Ich vermute mal, dass du die ganzen Überwachungsaktionen im Main Thread machst. Dadurch ist deine Anwendung wahrscheinlich so ausgelastet, dass keine Zeit mehr für das Zeichnen der Form bzw. zum Verarbeiten von Messages bleibt. Unschöne Abhilfe könnte ein
Delphi-Quellcode:
Application.ProcessMessages;
nach einer bestimmten Anzahl von Zeichendurchläufen bringen.

Besser wäre es aber, wenn du die Webcam in einem anderen Thread abfrägst und die Daten dort verarbeitest. Dann bleibt auch dein Programm bedienbar.

Aviator 1. Apr 2017 19:45

AW: Fenster sichtbar machen
 
Zitat:

Zitat von EWeiss (Beitrag 1366149)
Zitat:

Aber wenn das Fenster minimiert ist, bleibt es minimiert.
Verhindere doch einfach das man es minimieren kann.
Also sobald jemand das Fenster minimieren will setze es auf Hide.

und auf visible wenn du es in den Vordergrund bringen willst.

gruss

Das wäre dann aber nur eine Maßnahme gegen die Symptome. Aber die Ursache davon wäre noch nicht behoben. Also nicht wirklich sauber.

Beim Ändern der Größe würde wahrscheinlich das Gleiche passieren. Bei Systemen vor Vista (mit DWM) würde das Fenster vermutlich weiß bleiben und sich gar nicht mehr neuzeichnen wenn ein anderes Fenster drübergelegt wird.

EWeiss 1. Apr 2017 20:11

AW: Fenster sichtbar machen
 
Davon ab ist es unmöglich ein Fenster in den Vordergrund zu bringen wenn es minimiert ist.
Deshalb habe ich gesagt er soll dafür sorge tragen das es nicht minimiert wird.
Wie oder in welcher weise er sein Fenster zeichnet ist erst mal nebensächlich.

Zitat:

gar nicht mehr neuzeichnen
Sind Vermutungen da du nicht definitiv sagen kannst was er macht daher kann man nur raten.

Zitat:

Deshalb wollte ich zu Beginn jedes Zyklus vor dem Auslesen der Kamera per windowstate:=wsnormal; sicherstellen
Er schreibt aber auch "Vor dem Auslesen" es findet zu der zeit also kein zeichnen statt was den zugriff auf Messages verhindern würde\könnte.

Bin mir jetzt nicht sicher wie oder wo du
windowstate:=wsnormal; setzt.

EDIT:
Glaube aber das deine Anwendung wenn sie keinen Focus hat damit nichts erreichen wird.
Versuche es einfach mal auf die alt bewährte weise mit ShowWindow und sorge dafür das sie einen Focus hat
was im minimierten zustand schwerlich zu erreichen ist wenn du keine Callback oder ähnliches dafür eigerichtet hast.


gruss

a.def 1. Apr 2017 20:36

AW: Fenster sichtbar machen
 
Zitat:

Deshalb habe ich gesagt er soll dafür sorge tragen das es nicht minimiert wird.
Ist aber auch nur eine 0815-Lösung.
Wenn er das Fenster nicht erneut aus der Taskleiste bekommt nachdem es minimiert wurde, ist doch wohl eindeutig der Hauptthread total mit Müll blockiert.

EWeiss 1. Apr 2017 20:46

AW: Fenster sichtbar machen
 
Zitat:

Zitat von a.def (Beitrag 1366153)
Zitat:

Deshalb habe ich gesagt er soll dafür sorge tragen das es nicht minimiert wird.
Ist aber auch nur eine 0815-Lösung.
Wenn er das Fenster nicht erneut aus der Taskleiste bekommt nachdem es minimiert wurde, ist doch wohl eindeutig der Hauptthread total mit Müll blockiert.

Wenn dieser nichts tut und auch keine Webcam abgefragt wird.. wie er sagt.
Möchte ich das bezweifeln.

Aber egal ohne Antwort von ihm werden wir das wohl nicht erfahren.
Daher ist es nur reine Spekulation.

Zitat:

Ist aber auch nur eine 0815-Lösung.
Ist die einzig richtige denn wie schon erwähnt man kann ein minimiertes Fenster nicht in den Vordergrund bringen.
Es scheint mir so als wenn ihr nicht lest was hier geschrieben wird.

gruss

idefix2 1. Apr 2017 23:43

AW: Fenster sichtbar machen
 
Zitat:

Zitat von EWeiss (Beitrag 1366149)
Zitat:

Aber wenn das Fenster minimiert ist, bleibt es minimiert.
Verhindere doch einfach das man es minimieren kann.
Also sobald jemand das Fenster minimieren will setze es auf Hide.

und auf visible wenn du es in den Vordergrund bringen willst.

gruss

Das wäre eine (Not)lösung. Allerdings ist mir auch nicht klar wie ich verhindern kann, dass ein Fenster minimiert wird - Irgendwas auf die Art von OnMinimize oder OnCanMinimize habe ich bei den Formular-Events nicht gefunden.

Zitat:

Zitat von Aviator (Beitrag 1366150)
Ich vermute mal, dass du die ganzen Überwachungsaktionen im Main Thread machst. Dadurch ist deine Anwendung wahrscheinlich so ausgelastet, dass keine Zeit mehr für das Zeichnen der Form bzw. zum Verarbeiten von Messages bleibt. Unschöne Abhilfe könnte ein
Delphi-Quellcode:
Application.ProcessMessages;
nach einer bestimmten Anzahl von Zeichendurchläufen bringen.

Besser wäre es aber, wenn du die Webcam in einem anderen Thread abfrägst und die Daten dort verarbeitest. Dann bleibt auch dein Programm bedienbar.

Nein, Ausgelastet ist gar nichts. Alle Minuten wird ein neues Bild geholt und untersucht. Das wird über einen Timer aktiviert, in der Wartezeit, bis der Timer ausgelöst wird, passiert nichts. In der Timer Routine wollte ich als erstes das Formular aus der Taskleiste herauf holen, falls es minimiert worden ist. Und das geht nicht. Wenn das Programmicon in der Taskleiste von Hand angeklickt wird, wird das Formular sofort angezeigt, und dann funktioniert auch wieder alles andere. Bloß aus dem Programm heraus gelingt es mir nicht, das Fenster aus der Taskleiste wieder sichtbar zu machen. Genau das müsste aber doch eigentlich durch
Delphi-Quellcode:
windowstate:=wsnormal;
erreicht werden, oder?

Luckie 2. Apr 2017 00:24

AW: Fenster sichtbar machen
 
Zitat:

Zitat von idefix2 (Beitrag 1366146)
Ein Programm soll periodisch eine Webcam überwachen, und damit das funktioniert, muss das entsprechende Fenster im Vordergrund sichtbar sein (Das Programm läuft auf einem File Server, auf dem normalerweise nicht gearbeitet wird, also stört das nicht wirklich).

Machst du etwas Screenshots von der Kamera Software oder wie?

idefix2 2. Apr 2017 02:16

AW: Fenster sichtbar machen
 
Ich kann über eine URL direkt ein JPG von der Kamera abrufen. Das jpg wird dann in einer TWebBrowser Komponente angezeigt. Damit das funktioniert, muss das Formular mit dem TWebbrowser im Vordergrund sichtbar sein.

Luckie 2. Apr 2017 03:09

AW: Fenster sichtbar machen
 
Und warum holst du es dir nicht über eine HTTP-Komponente und einem Download direkt in dein Programm?

EWeiss 2. Apr 2017 06:50

AW: Fenster sichtbar machen
 
Zitat:

Wenn das Programmicon in der Taskleiste von Hand angeklickt wird, wird das Formular sofort angezeigt, und dann funktioniert auch wieder alles andere
Wie ich auch schon sagte. Du brauchst den Focus.

Zitat:

Genau das müsste aber doch eigentlich durch windowstate:=wsnormal; erreicht werden, oder?
Ja wenn du den Focus hast.

Frage?
Wenn du eine Taste für deine Anwendung registrierst und dann versuchst mit dieser deine Anwendung wieder zu maximieren was passiert wenn diese keinen Focus hat? Gar nichts!
Lösung!
Das bedeutet du benötigst eine Callback (oder einen Hook) von einer externen Anwendung DLL oder was auch immer die den Status deiner Anwendung überprüft.

Diese sendet dann ein ShowWindow wenn diese Minimiert wurde und das war's dann schon.
Deine Anwendung selbst kann das nicht.

Zitat:

Das wäre eine (Not)lösung. Allerdings ist mir auch nicht klar wie ich verhindern kann, dass ein Fenster minimiert wird
Ein Dialog Window erstellen?
Das kannst du dann weder resizen noch Minimieren.
Aber letztendlich wirst du über einen Hook nicht drum rum kommen da du ja auch den Vordergrund Status prüfen musst.

gruss

idefix2 2. Apr 2017 09:37

AW: Fenster sichtbar machen
 
Zitat:

Zitat von Luckie (Beitrag 1366162)
Und warum holst du es dir nicht über eine HTTP-Komponente und einem Download direkt in dein Programm?

Das ganze sollte eine einfache, schnelle (und billige) Lösung für einen Kunden sein. Das ganze Programm hat gerade mal 250 Zeilen, inkl. Kommentaren und Kontrollausgaben. Und nachdem das Programm am Server läuft, stört es nicht, wenn es im Vordergrund bleibt. Ich habe mir nicht angeschaut, wie ich aus dem HTTP Stream der Seite das jpg herausfiltern könnte, aber ich bin davon ausgegangen, dass das herausfinden, wie das geht, mich deutlich mehr Zeit kosten würde als diese simple Lösung. Wenn ich mit den absurden Komplikationen gerechnet hätte, wäre ich wahrscheinlich so vorgegangen, wie du hier vorschlägst. Schon dass das Fenster im Vordergrund sein muss, damit ich den Canvas kopieren kann, war eine üble Überraschung. Bei anderen visuellen Komponenten gibt es die Einschränkung nicht.


Zitat:

Zitat von EWeiss (Beitrag 1366164)
Ein Dialog Window erstellen?
Das kannst du dann weder resizen noch Minimieren.
Aber letztendlich wirst du über einen Hook nicht drum rum kommen da du ja auch den Vordergrund Status prüfen musst.

Das Programm in den Vordergrund zu bringen funktioniert mit dem Codeschnipsel von a.def http://www.swissdelphicenter.com/de/showcode.php?id=261
Wie mache ich aus einer normalen Form ein nicht minimierbares Fenster?

Luckie 2. Apr 2017 09:45

AW: Fenster sichtbar machen
 
Tja, und mittlerweile ist es durch das hausgemachte Problem mit der Screenshotkrücke wohl erheblich teurer geworden und funktioniert nicht zuverlässig. Und der Download mit einer HTTP-Komponente ist auch nicht viel komplexer. Eher wahrscheinlich das Gegenteil und zudem dürfte es zuverlässiger funktionieren.

Link: https://www.delphi-treff.de/tipps-tr...herunterladen/

Copy and paste und schon fast fertig. Inklusive Anpassung für den Kunden 2 oder 3 Stunden.

a.def 2. Apr 2017 09:57

AW: Fenster sichtbar machen
 
Du schreibst du holst alle paar Minuten ein Bild und dann wird ein Timer aktiviert.
Aber dieses "alle paar Minuten"... ist das nicht auch ein Timer? Oder noch schlimmer. Ein Sleep?

Mit "Ausgelastet" meinte ich keine 100% Auslastung sondern einfach nur, dass der Hauptthread blockiert wird.

t.roller 2. Apr 2017 10:01

AW: Fenster sichtbar machen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Mit XE7, WIN8.1 geht folgender Test-Code:
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Button1: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure SetCursorToControl(Control: TControl);
var P: TPoint;
begin
  P.X := Control.Width div 2;
  P.Y := Control.Height div 2;
  P := Control.ClientToScreen(P);
  SetCursorPos(P.X, P.Y);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Timer1.Enabled:= TRUE;
  Button1.Enabled:= FALSE;
  Self.WindowState:= wsMinimized;
end;

procedure TForm1.Timer1Timer(Sender: TObject); // interval:= 10000;
begin
  Timer1.Enabled:= FALSE;
  Button1.Enabled:= TRUE;

  Application.BringToFront; //Setzt das zuletzt aktive Fenster auf dem Desktop in den Vordergrund
  Self.WindowState:= wsNormal; // besser als: Application.Restore;

  SetCursorToControl(self);
  mouse_event(MOUSEEVENTF_LEFTDOWN, 50, 50, 0, 0);
  mouse_event(MOUSEEVENTF_LEFTUP, 50, 50, 0, 0);
end;

end.
Source + EXE hinzugefügt

idefix2 2. Apr 2017 10:37

AW: Fenster sichtbar machen
 
Zitat:

Zitat von Luckie (Beitrag 1366171)
Tja, und mittlerweile ist es durch das hausgemachte Problem mit der Screenshotkrücke wohl erheblich teurer geworden und funktioniert nicht zuverlässig. Und der Download mit einer HTTP-Komponente ist auch nicht viel komplexer. Eher wahrscheinlich das Gegenteil und zudem dürfte es zuverlässiger funktionieren.

Link: https://www.delphi-treff.de/tipps-tr...herunterladen/

Copy and paste und schon fast fertig. Inklusive Anpassung für den Kunden 2 oder 3 Stunden.

Das Problem ist, dass ich keine "Datei" herunterladen kann. Wenn es eine Download-URL für das Bild selbst geben würde, hätte ich das natürlich so gemacht. Aber die gibt es nicht. Der Webserver der Kamera lädt in meinen Browser ein Javaskript, das einen Video-Stream (oder eben alternativ statt des bewegten Live-Streams nur ein Frame des Streams) am Bildschirm anzeigt.

Und das "hausgemachte" Problem war zu Beginn überhaupt nicht absehbar. Von einer normalen Form kann ich jederzeit eine Kopie eines Teils des Canvas machen, auch wenn die Form gerade nicht am Bildschirm sichtbar ist. Alle Schwierigkeiten haben damit begonnen, dass das in diesem Fall nicht funktioniert. Das konnte ich im voraus nicht wissen.

EWeiss 2. Apr 2017 10:56

AW: Fenster sichtbar machen
 
Zitat:

Wie mache ich aus einer normalen Form ein nicht minimierbares Fenster?
BorderStyle? bsDialog

gruss

idefix2 2. Apr 2017 12:01

AW: Fenster sichtbar machen
 
Zitat:

Zitat von a.def (Beitrag 1366173)
Du schreibst du holst alle paar Minuten ein Bild und dann wird ein Timer aktiviert.
Aber dieses "alle paar Minuten"... ist das nicht auch ein Timer? Oder noch schlimmer. Ein Sleep?

Mit "Ausgelastet" meinte ich keine 100% Auslastung sondern einfach nur, dass der Hauptthread blockiert wird.

Nein, ich habe geschrieben:
Zitat:

Alle Minuten wird ein neues Bild geholt und untersucht. Das wird über einen Timer aktiviert, in der Wartezeit, bis der Timer ausgelöst wird, passiert nichts.
Dass es nicht an einem blockierten Hauptthread liegt (was schon deshalb nicht sein kann, weil der in der Zeit NICHTS tut), ist auch daran zu erkennen, dass über einen Klick auf das Programmicon in der Taskleiste das Formular sofort sichtbar wird.

Zitat:

Zitat von EWeiss (Beitrag 1366179)
Zitat:

Wie mache ich aus einer normalen Form ein nicht minimierbares Fenster?
BorderStyle? bsDialog

Danke, ich denke, damit ist das Problem gelöst.

Zitat:

Zitat von t.roller (Beitrag 1366175)
Mit XE7, WIN8.1 geht folgender Test-Code:
...

Seltsam: Das EXE funktioniert, aber wenn ich den Code in mein Programm einbaue, funktioniert es nicht. Ich kann es mir zwar nicht so recht vorstellen, aber könnte es einen Unterschied ausmachen, ob das Programm sich selbst minimiert hat, wie in deinem Beispiel, ober ob das Programm manuell per Klick auf den Minimieren-Button durch den Programmbenutzer minimiert wurde?

Leider lässt sich dein Projekt mit meinem Delphi 2009 nicht kompilieren, ich bekomme die Fehlermeldung
Code:
[MSBuild Fehler] 0 ist ein ungültiger Wert für den DebugInformation-Parameter der DCC-Aufgabe. Der DebugInformation-Parameter gehört zum System.Boolean-Typ.
Funktioniert das Restore des Fensters in denem Beispielprogramm immer noch, wenn du in der Button1Click Routine die Zeile
Delphi-Quellcode:
Self.WindowState:= wsMinimized;
herausnimmst und statt dessen nach dem Klick auf den Button das Fenster manuell minimierst?

t.roller 2. Apr 2017 13:51

AW: Fenster sichtbar machen
 
Zitat:

Zitat von idefix2 (Beitrag 1366183)
Funktioniert das Restore des Fensters in denem Beispielprogramm immer noch, wenn du in der Button1Click Routine die Zeile
Delphi-Quellcode:
Self.WindowState:= wsMinimized;
herausnimmst und statt dessen nach dem Klick auf den Button das Fenster manuell minimierst?

Wenn ich manuell minimiere mit dem Anklicken des BorderIcons biMinimize funktioniert es auch.

Hinweis: Der mouse_event darf NICHT über dem Element erfolgen (im Beispiel Button1), das den Test ausgelöst hat, weil sonst gleich ein neuer Test ausgelöst wird (Kettenreaktion).
Evtl. mouse_event-Parameter ändern oder Button1 verschieben.

Wegen Debugger: Starte die Compilation versuchsweise mal mit
Umsch+Strg+F9.

idefix2 2. Apr 2017 23:05

AW: Fenster sichtbar machen
 
Zitat:

Zitat von t.roller (Beitrag 1366191)
Wenn ich manuell minimiere mit dem Anklicken des BorderIcons biMinimize funktioniert es auch.

Wirklich seltsam. Es wären doch etliche Anpassungen in deinem Beispielprogramm zu machen, damit es kompiliert, die ganzen Unitnamen passen ja auch nicht. Wenn ich mehr Zeit habe, spiele ich mich damit noch (und werde hier zurückmelden, was ich gefunden habe), weil ich verstehe überhaupt nicht, was bei meinem Programm schuld daran sein könnte, dass genau der gleiche Code, der im Beispielprogramm funktioniert, bei mir nicht geht. Aber jetzt kann ich verhindern, dass das Formular überhaupt minimiert wird, deshalb kommt das fürs erste in die Lade "möchte aber doch gerne wissen warum" und nicht mehr in die Lade "brauche ich unbedingt" :)

Zitat:

Hinweis: Der mouse_event darf NICHT über dem Element erfolgen (im Beispiel Button1), das den Test ausgelöst hat, weil sonst gleich ein neuer Test ausgelöst wird (Kettenreaktion).
Evtl. mouse_event-Parameter ändern oder Button1 verschieben.
Schon klar, in meinem Programm gibt es ja gar keinen entsprechenden Button. Minimiert wurde nur manuell, und in der Timerroutine sollte das Fenster vor dem nächsten Durchlauf wiederhergestellt werden. Und das macht er hartnäckig nicht.

Luckie 3. Apr 2017 00:34

AW: Fenster sichtbar machen
 
Ich würde es immer noch direkt über HTTP probierten. Jetzt hast du so viel Zeit vergagelt... ;)

Luckie 3. Apr 2017 00:39

AW: Fenster sichtbar machen
 
Es wird ja wohl ein Image im Browser angezeigt. Man müsste also die Seite mach dem img-Tag scuhen können. Oder im JS-Script sehen, wo die Images abgelegt werden. FTP wäre noch eine Idee.

Luckie 3. Apr 2017 00:42

AW: Fenster sichtbar machen
 
Oder gibt es für die Kamera keine API?

idefix2 3. Apr 2017 08:36

AW: Fenster sichtbar machen
 
Es gibt für die Kamera keine dokumentierte API, zumindest habe ich im Internet nichts gefunden, und auch keinen dokumentierten FTP-Zugang. Es läuft ein Javascript, das habe ich mir angeschaut, aber bin daraus nicht schlau geworden. Deshalb diese Lösung, mit der ich auch nicht besonders viel "Zeit vergagelt" habe, jedenfalls nicht mehr als mit einer anderen Lösung, bei der ich möglicherweise die Hindernisse auch erst unterwegs bemerkt hätte.
Das Programm ist längst fertig und läuft seit gut einem halben Jahr einwandfrei, von "funktioniert nicht zuverlässig" kann keine Rede sein. Es ist aber jetzt zum zweiten Mal passiert, dass ein Mitarbeiter das Programm irrtümlich minimiert hat. Die Möglichkeit habe ich jetzt mit Forumsunterstützung abgestellt (schöner wärs andersrum, wenn das Programm selbstständig wieder hervorkommen würde, aber das ist nicht wirklich wichtig), und dazu habe ich dem Fenster während des Auslesens des Bildes noch die Eigenschaft stayontop verpasst. An dem Server wird normalerweise nicht gearbeitet, aber es laufen darauf ein paar "Hintergrundprogramme", die ganz sporadisch einen kurzen Bedienereingriff erfordern.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz