Autor Beitrag
ripmav
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 02.03.10 16:09 
Hallo,

ich habe mehrere Fenster in meiner Anwendung offen. Das Event soll nur aufgerufen werden, wenn wirklich alle Fenster meiner Anwendung nicht den Focus haben, d.h. das Fenster einer anderen Anwendung legt sich über die Fenster meiner Anwendung.
LostFocus und Deactivate sind nicht die richtigen Events dafür.
Gibt es dafür ein Event oder muss man die WinAPI benutzen?

MfG
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Di 02.03.10 16:20 
Hallo,

ich glaube, eine solche Möglichkeit ist in .NET nicht enthalten. Aber du kannst es prüfen: Benutze eines der denkbaren Form-Ereignisse; Deactivate dürfte am ehesten passen. Hole Application.OpenForms und frage alle darin enthaltenen Formulare nach ContainsFocus ab.

Gruß Jürgen
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Di 02.03.10 19:23 
Mir fällt da auch spontan kein Event ein...

Dann schreiben wir eben unser eigenes :)

editiert
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
using System;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    static class Program
    {


        /// <summary>
        /// Liefert den Handle des aktiven Fensters
        /// </summary>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern IntPtr GetForegroundWindow();


        /// <summary>
        /// Liefert die PID des Prozesses der das angegeben Fenster-Handle hält
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="lpdwProcessId"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern Int32 GetWindowThreadProcessId(IntPtr hWnd, out Int32 lpdwProcessId);

        //Der Delegate für den Eventaufruf, wenn das Fenster den Focus verliert
        public delegate void AppFocusEvent();

        /// <summary>
        /// Tritt ein, wenn die Application den Focus verliert
        /// </summary>
        public static event AppFocusEvent AppLostFocus;

        /// <summary>
        /// Tritt ein, wenn die Application den Focus bekommt
        /// </summary>
        public static event AppFocusEvent AppGotFocus;

        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Thread ALFThr = new Thread(() =>
                {
                    //Schaltet um, wenn das Fenster den Focus verliert/bekommt
                    //Das verhindert zum einen, dass das Event mehrmals aufgrufen wird
                    bool LostFoc = false;
                    
                    //Endlosschleife zum überprüfen, welches das aktuelle Fordergrundfenster ist
                    while (true)
                    {
                        //ermittelt den Handle des aktuell aktiven Fensters
                        IntPtr hwnd = GetForegroundWindow();
                        
                        //ermittelt die PID des Processes, der das Fenster mit hwnd hält
                        Int32 fgwPID = 0;
                        GetWindowThreadProcessId(hwnd, out fgwPID);
                        
                        //PID des aktuellen Procs
                        int cpPID = Process.GetCurrentProcess().Id;
                        
                        //Wenn die PID des aktuellen Fensters ungleich der des aktuellen Procs
                        // und wir den Focus bisher hatten, dann...
                        if (fgwPID != cpPID && !LostFoc)
                        {
                            //...hat unsere Application den Focus verloren
                            LostFoc = true;
                            
                            //...wenn das Event registriert ist, dann...
                            if (AppLostFocus != null)
                                //...löse es aus
                                AppLostFocus();
                        }
                        //wenn die IDs übereinstimmen und wir den Focus bisher nicht hatten, dann
                        else if (fgwPID == cpPID && LostFoc)
                        {
                            //...hat unsere Application den Focus bekommen
                            LostFoc = false;
                            //...und wenn das Event registriert ist, dann
                            
                            if (AppGotFocus != null)
                                //...löse es aus
                                AppGotFocus();
                        }
                        //...blockiert den Thread eine Weile, um nicht Rechenzeit zu verschwenden
                        Thread.Sleep(100);
                    }
                });
            
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            //Registriert die Events
            AppLostFocus += new AppFocusEvent(Program_AppLostFocus);
            AppGotFocus += new AppFocusEvent(Program_AppGotFocus);
            //Started den Thread, der den Focus prüft
            ALFThr.Start();
            
            Application.Run(new Form1());
        }

        static void Program_AppGotFocus()
        {
            //Code, der ausgeführt werden soll, wenn die Application den Focus zurück bekommt
        }

        static void Program_AppLostFocus()
        {
            //Code, der ausgeführt werden soll, wenn die Application den Focus verliert
        }
    }
}


Hoffe, das hilft dir:)



Moderiert von user profile iconChristian S.: Beiträge zusammengefasst


ich dokumentiere das nachher noch, wenn du das möchtest. muss aber jetzt zum sport... keine zeit

Edit:

Getestet, etwas optimiert, dokumentiert und noch ein "AppGotFocus" hinzugefügt :) na wenn das mal kein Service ist
ripmav Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mi 03.03.10 16:30 
@JüTho:
Leider funktioniert die Methode mit Application.OpenForms nicht :(

@norman2306:
Genau das ist es! Und auch schon alles fertig geschrieben. Vielen Dank!!
Schade das es mit einer Schleife realisiert werden muss, wo doch Windows eigtl ein eventgesteuertes System sein soll.. Aber es gibt wohl keine andere Möglichkeit
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Mi 03.03.10 17:11 
user profile iconripmav hat folgendes geschrieben Zum zitierten Posting springen:
@JüTho:
Leider funktioniert die Methode mit Application.OpenForms nicht :(

Rein interessehalber: was funktioniert daran nicht? Ich habe es nicht selbst geprüft, aber theoretisch sollte es klappen. Jürgen
ripmav Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mi 03.03.10 17:14 
Eine Form hat den Focus (ContainsFocus==true), obwohl das Fenster im Hintergrund ist.. Das ist nur der Fall, wenn man STRG+ALT+ENTF drückt. Kann sein, dass das nur unter Windows 7 auftritt, da ja Windows XP in best. Einstellungen sofort den Taskmanager öffnet.
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: Mi 03.03.10 17:18 
Oops, mit so etwas habe ich bei meinem Vorschlag natürlich nicht gerechnet. Danke für den Hinweis! Jürgen
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Mi 03.03.10 18:13 
user profile iconripmav hat folgendes geschrieben Zum zitierten Posting springen:

Schade das es mit einer Schleife realisiert werden muss, wo doch Windows eigtl ein eventgesteuertes System sein soll.. Aber es gibt wohl keine andere Möglichkeit


Korrigiere mich, aber im Prinzip lassen sich alle internen System-Events (also Events, die nicht auf einem elektrischen Signal beruhen) auf eine Abfrage-Schleife zurückführen. Zum Beispiel erfolgt die Abfrage von Windows-Meldungen auch in einer sog. MessageLoop (so erfährt dein Program das es sich abschiessen muss, wenn du z.B. runterfährst und das Event wird ausgelöst)
ripmav Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mi 03.03.10 18:15 
Ja, das stimmt, aber die MessageLoop basiert auf der Funktion GetMessage und diese wartet ("sleept") solange, bis wirklich eine Message da ist..
norman2306
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 222
Erhaltene Danke: 16

Win XP, Win 7 64-Bit
C# 4.0 (VS2010)
BeitragVerfasst: Mi 03.03.10 18:39 
Joop, aber irgendwo hängt da mal eine Endlosschleife. Entweder ich habe einen physikalischen Schalter, der irgendein Event auslöst (z.B. Tastendruck) oder irgendwas läuft in einer Abfrage-Schleife (Permanente Abfrage, ob was da ist) oder in einer Sende-Schleife (Läuft solang in einer Schleife und blockiert, bis was zum Senden da ist).