Fokus zum letzten Programm schalten

Rudeman

Grünschnabel
Hallo!

Ich muss den Programmfokus auf das zuletzt benutzte Programm schalten. Dafür habe ich eine Klasse geschrieben, die laufend per
Code:
GetForegroundWindow()
die HWND des aktiven Fensters ausliest. Sobald ich dann dorthin schalten will, rufe ich
Code:
SetForegroundWindow()
auf. Doch leider funktioniert das nicht so ganz.
Hoffe Ihr findet einen Denk-/Programmierfehler in diesem Code:

Code:
    public static class cTaskManagement
    {
        #region APIs einbinden
        [DllImport("user32.dll")]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        #endregion

        #region Klassenvariablen
        static IntPtr ActiveProcess = new IntPtr();
        static Timer tmrAutoReco = new Timer();
        #endregion

        #region Eigenschaften
        static private bool bAutoRecognitionOn_ = false;
        static public bool bAutoRecognitionOn
        {
            get { return bAutoRecognitionOn_; }
            set { bAutoRecognitionOn_ = value;
                    //Starten
                    if (value == true)
                    {
                        StartAutoRecognition();
                    }
                }
        }

        static private frm_Main MainForm_ = new frm_Main();
        static public frm_Main MainForm
        {
            get { return MainForm_; }
            set { MainForm_ = value; }
        }
        #endregion

        #region Methoden
        private static void StartAutoRecognition()
        {
            tmrAutoReco = new Timer();
            tmrAutoReco.Interval = 250;
            tmrAutoReco.Tick += new EventHandler(tmrAutoReco_Tick);
            tmrAutoReco.Enabled = true;
        }

        static void tmrAutoReco_Tick(object sender, EventArgs e)
        {
            if (bAutoRecognitionOn)
            {
                IntPtr CurrentWindow = GetForegroundWindow();
                if (CurrentWindow != MainForm.Handle)
                {
                    ActiveProcess = CurrentWindow;
                    Debug.Print(ActiveProcess.ToString());

                }
            }
            else
            {
                tmrAutoReco.Enabled = false;
                tmrAutoReco.Dispose();
            }

        }

        public static void SetFocusToLastApplication()
        {
            SetForegroundWindow(ActiveProcess);
        } 


        #endregion
    }

Danke schonmal & lg,
Rudi
 
Hi nochmal!

Ok, das funktioniert doch so! :-(

Aber das Problem ist, dass der User ein NotifyIcon im Systemtray anklickt, welches utner anderem dann SetFocusToLastApplication() auslöst.
Sobald der User aber den Fokus auf das NotifyIcon setzt, registriert das aber die Autorecognition() und das gespeicherte Handle dürfte entweder die Taskbar selbst, oder aber irgendetwas anderes sein.

Nun habe ich herumüberlegt, wie man das umgehen könnte und mir ist folgende Lösung eingefallen:
Autorecog. sollte nur Handles annehmen wenn dieses auch einen Titel hat. Nun aber meine Frage:

Wie kann ich von der API-Funktion GetForegroundWindow() auf einen Process oder zumindest auf einen Titel kommen

Das mit den Windows Handles ist echt nicht meine Stärke ^^

Danke nochmal & lg
 
Wie kann ich von der API-Funktion GetForegroundWindow() auf einen Process oder zumindest auf einen Titel kommen

Hi. :)

Hier sind 2 weitere Win32 Api Calls mit denen du deine Wünsche erfüllen kannst. ;)

GetWindowText

und

GetWindowThreadProcessId

GetWindowThreadProcessId bietet dir dabei aber mehr Möglichkeiten, da du über die Process-Klasse von .net noch mehr Infos abfragen kannst.

Dies machst du in dem du mit GetWindowThreadProcessId die ProcessID abfragst und mit Process.GetProcessById dann an den Prozess gelangst.
Über dieses Objekt hast du dann auch die Infos wie den Titel des Hauptfensters, den Namen der ausführbaren Datei, und so weiter. :)

Gutes Gelingen.
 
Hi!

Danke für die ausführliche Antwort!! :D

Ich hab das ganze jetzt so geschrieben:
Code:
IntPtr CurrentWindow = GetForegroundWindow();
uint CurrentProcessID = GetWindowThreadProcessId(GetForegroundWindow(), out CurrentProcessID);
Process CurrentProcess = Process.GetProcessById((int)CurrentProcessID);

Nur bekomme ich GetProcessByID immer den Fehler, dass es keinen Process mit der ID ... gibt?!

Hmmm, hoffe Du kannst mir nochmal helfen!

Danke nochmal & lg
 
Hi nochmal. :)

Du hast den Aufruf von GetWindowThreadProcessID falsch.

Der Rückgabewert ist die ThreadID, und der out-Parameter die ProzessID. So wie du das machst, hast am Ende nur die ThreadID.

Ausserdem hast du 2 mal GetForegroundWindow benutzt. Ist ansich jetzt nicht falsch, aber wenn du das Handle schon gespeichert hast, warum nochmal holen? :)

Schau mal hier:

C#:
IntPtr CurrentWindow = GetForegroundWindow();
uint CurrentProcessID;
uint ThreadID = GetWindowThreadProcessId(CurrentWindow, out CurrentProcessID);

Process CurrentProcess = Process.GetProcessById((int)CurrentProcessID);

lg,..
 

Neue Beiträge

Zurück