Autor Beitrag
alexpj
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Mo 27.02.23 12:26 
Moin Moin....ich benötige etwas Hilfe für folgenden Problem.
Es läuft ein Programm. Dies muß zwingend im Vordergrund laufen, da hier mittels Ipad einige Tastatur-Shortcuts übertragen werden, was nur funktioniert, wenn dies Programm im Vordergrund läuft. Bisher muss ich immer nach extremer Mausklickerei wieder einmal in dies Programmfenster klicken. Dafür habe ich nun eine App gemacht, die dieses Programm intervallmäßig in den Vordergrund holt bzw. den Fokus wieder in dies Programm setzt.

Dies kleine Tool macht einen Check, ob die das zu überwachende Programm läuft und setzt den Focus hierauf. Das ganze über einen BackgroundWorker.
Das funktioniert jedoch nur auf meinem - Windows 11 - Entwickler Rechner.

Auf fremden PC auch mit W11 oder W7 wird der Focus auf das zu überwachende Programm nur gesetzt, wenn mein Tool selbst (zuvor) im Vordergrund lief. Wenn eine dritte App im Vordergrund läuft, wird das zu überwachende Programm nur in der Taskbar orange blinkend angezeigt, aber nicht mit dem Fokus versehen. Auf meinem W11 Entwicklerrechner geht das aber.

Was mache ich da falsch?
Das zu überwachende Programm läuft im Vollbild auf Bildschirm (2), mein Tool auf Bildschirm (1)
Der Code ist nicht sehr lang....ich poste das mal komplett:

start() aktiviert den BackgroundWorker --> bg2_DoWork(...)
FocusProcess(AppName) macht dann die eigentliche Arbeit. Scheinbar steckt hier das Problem.

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:
119:
120:
121:
122:
123:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Drawing;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.ComponentModel;
using System.Threading;

namespace FocusedControlInOtherProcess
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
            Start();

        }
        private static string AppName;
       
        [DllImport("user32.dll")]
        internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);

        private void Start()
        {
            AppName = tBAppName.Text; //<--get AppName from Textbox
            int fileExtPos = AppName.LastIndexOf(".");
            if (fileExtPos >= 0)
                AppName = AppName.Substring(0, fileExtPos);
            if (tBAppName.Text != "")
            {
                labelAppName.ForeColor = Color.Red;
                labelAppName.Text = AppName;//<--zeige das zu überwachende Programm im Label und in rot
            }
            try
            {
                bg2.RunWorkerAsync();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            buttonStart.Enabled = false;
        }
        private void bg2_DoWork(object sender, DoWorkEventArgs e)
        {           
            BackgroundWorker worker = sender as BackgroundWorker;
           
            int dfinterval = 3000;//<--default interval
            int interval = int.TryParse(tBInterval.Text, out dfinterval) ? dfinterval : 1;//<--get individual interval from textbox
            while (!bg2.CancellationPending)
            {
               
                    try
                    {                       
                        FocusProcess(AppName);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Error:\n\n" + ex.Message, "System", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                    Thread.Sleep(interval);
               
            }
            e.Cancel = true;
        }

        private void FocusProcess(string fileName)//<-- Hier scheint das Problem zu stecken
        {
            AppName = fileName;
            IntPtr hWnd;
            Process[] processRunning = Process.GetProcesses();
            foreach (Process pr in processRunning)
            {
                if (pr.ProcessName == AppName)
                {
                    hWnd = pr.MainWindowHandle; //use it as IntPtr not int
                    SetForegroundWindow(hWnd);
                    labelAppName.BeginInvoke(new Action(() => { labelAppName.ForeColor = System.Drawing.Color.Green; ; }));
                    //<--zeige das zu überwachende Programm im Label grün = Überwachung aktiv
                                      
                }
            }
        }
       
        private void buttonStart_Click(object sender, EventArgs e)
        {
            Start();
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            bg2.CancelAsync();
            bg2.Dispose();
            labelAppName.ForeColor = Color.Red;
            buttonStart.Enabled = true;
        }

        private void buttonZoom_Click(object sender, EventArgs e)
        {
            if (panel1.Visible == true) infozoom(true);
            else infozoom(false);
        }

        private void infozoom(bool zoom)
        {
            if (zoom == false)
            {
                panel1.Visible = true;
                this.Width = 445;
                button3.Text = "<<";
            }
            else
            {
                panel1.Visible = false;
                this.Width = 235;
                button3.Text = ">>";
            }
        }
    }
}


Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 27.02.23 13:18 
Moin!

Ohne mich jetzt mit der Windows-API näher beschäftigt zu haben: das Verhalten, das Windows an den Tag legt (auf den "anderen" PCs, nicht bei dir auf dem Entwickler-PC) klingt für mich absolut sinnvoll und beabsichtigt. Wenn du per API-Call eine andere Anwendung in den Vordergrund einer GUI-Session holen willst, dann hat das nach meinem Verständnis von Sicherheit nicht automatisch zu passieren. Die Anwendung darf signalisieren, dass sie gerne den Focus hätte (tut sie ja auch, wird orange/blinkt in der Taskleiste), aber ob sie den Fokus kriegt oder nicht, das liegt in meinem Ermessen (als "Eigentümer" der GUI-Session). Alles andere wäre ganz klar ein Sicherheitsverstoß und für mich ein Grund nach einer Alternative für diese Anwendung zu suchen.

Nun ist das was du beschreibst sicherlich nachvollziehbar und möglicherweise sogar legitim, aber das gehört nicht in einer GUI-Session umgesetzt. Es ist deshalb mindestens fraglich, ob der Aufwand für einen Workaround ("Lösung" klingt für mich hier nicht sinnvoll, denn das sollte eigentlich nicht passieren dürfen) Sinn macht. Klingt für mich eher nach einer API-Schnittstelle, die hier gefragt wäre.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
alexpj Threadstarter
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Mo 27.02.23 14:00 
Moin Moin..

alles richtig, trotzdem verstehe ich das unterschiedliche Verhalten von Windows nicht.

PC1 Win11:
Ich starte das zu überwachende Program + meinen Code und alles funktioniert wie es soll

PC2 Win11
Ich starte das zu überwachende Program + meinen Code und es erzeugt nur ein Blinken in der tastleiste

PC3 WIN7
wie vor

Das zu überwachende Programm ist eine Golf-Simulatur Software, die mittels Beamer an eine schlagfeste Leinwand visualisiert wird. Dies Programm steuere ich mit einem Ipad mitteld "unified remote" App vom Abschlag aus.
Relativ oft muss ich aber am Bildschirm (1) in der Golfsoft-ApiSchnittstelle den Launchmonitor (Golfballsensor) manuell steuern.
In dem Moment funktioniert das Ipad als Remotesteuerung leider nicht mehr.

Das ist der Hintergrund.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 27.02.23 15:41 
Laufen die Programme auf den Rechnern unter unterschiedlichen Accounts (Admin vs. Non-Admin)?

Beachte besonders die Hinweise unter SetForegroundWindow.
alexpj Threadstarter
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Mo 27.02.23 20:09 
Die Lösung war komisch und hier beschrieben: stackoverflow.com/qu...isual-studio-is-open
scheinbar braucht es einen a key press....warum auch immer. Damit funktioniert es im W7 Sim-Rechner

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
 public static void ActivateWindow(IntPtr mainWindowHandle)
        {
            //check if already has focus
            if (mainWindowHandle == GetForegroundWindow()) return;

            //check if window is minimized
            if (IsIconic(mainWindowHandle))
            {
                ShowWindow(mainWindowHandle, Restore);
            }

            // Simulate a key press
            keybd_event(0000);

            SetForegroundWindow(mainWindowHandle);
        }