Entwickler-Ecke
WinForms - andere App wieder mit Fokus versehen
alexpj - Mo 27.02.23 12:26
Titel: andere App wieder mit Fokus versehen
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.
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; int fileExtPos = AppName.LastIndexOf("."); if (fileExtPos >= 0) AppName = AppName.Substring(0, fileExtPos); if (tBAppName.Text != "") { labelAppName.ForeColor = Color.Red; labelAppName.Text = AppName; } 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; int interval = int.TryParse(tBInterval.Text, out dfinterval) ? dfinterval : 1; 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) { AppName = fileName; IntPtr hWnd; Process[] processRunning = Process.GetProcesses(); foreach (Process pr in processRunning) { if (pr.ProcessName == AppName) { hWnd = pr.MainWindowHandle; SetForegroundWindow(hWnd); labelAppName.BeginInvoke(new Action(() => { labelAppName.ForeColor = System.Drawing.Color.Green; ; })); } } } 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 Th69: C#-Tags hinzugefügt
Narses - 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
alexpj - 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.
alexpj - Mo 27.02.23 20:09
Die Lösung war komisch und hier beschrieben:
https://stackoverflow.com/questions/10740346/setforegroundwindow-only-working-while-visual-studio-is-open
scheinbar braucht es einen a key press....warum auch immer. Damit funktioniert es im W7 Sim-Rechner
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| public static void ActivateWindow(IntPtr mainWindowHandle) { if (mainWindowHandle == GetForegroundWindow()) return;
if (IsIconic(mainWindowHandle)) { ShowWindow(mainWindowHandle, Restore); }
keybd_event(0, 0, 0, 0);
SetForegroundWindow(mainWindowHandle); } |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!