Est-il possible de démarrer/de lancer un programme via Process dans un autre écran?
Quelqu'un a demandé que ici mais il n'y avait pas de réponse.
Remarque: ce n'est pas un formulaire dans mon application, je demande à exécuter un programme externe dans un autre écran!
Comme la fenêtre ne vous appartient pas, vous ne pouvez la déplacer qu'en appelant l'API Windows. Vous devrez faire ceci:
Lancer le processus.
Utilisez FindWindow
pour récupérer le descripteur dans la fenêtre. Si la fenêtre n’existe pas encore, le processus ne l’a pas encore créée; Dormez pendant 500 ms puis réessayez. (Mais n'entrez pas dans une boucle infinie; arrêtez-vous si vous ne trouvez pas la fenêtre après un délai raisonnable.)
Utilisez SetWindowPos
pour changer la position de la fenêtre.
Si vous ne connaissez pas le titre de la fenêtre, vous ne pouvez pas utiliser FindWindow
. Dans ce cas,
Lancez le processus et obtenez le descripteur de processus en récupérant Process.Handle
.
Utilisez EnumWindows
pour récupérer toutes les fenêtres. Pour chaque fenêtre, utilisez GetWindowThreadProcessId
pour vérifier si elle appartient à votre processus. Si aucune fenêtre n'appartient à votre processus, attendez et continuez d'essayer.
Utilisez SetWindowPos
pour changer la position de la fenêtre.
Bien sûr, vous pouvez utiliser Screen.AllScreens[n].WorkingArea
pour récupérer la position et la taille de l'écran souhaité, puis positionner la fenêtre par rapport à celle-ci.
D'abord, sortez de la zone du second moniteur en utilisant quelque chose comme:
Rectangle area = Screen.AllScreens[1].WorkingArea;
Utilisez l’API Windows SetWindowPos pour le déplacer, à l’aide du Process.MainWindowHandle obtenu à partir du début de l’autre processus en tant que descripteur.
Timwi a fourni une astuce très utile. J'ai donc décidé de créer un script PowerShell appelant une bibliothèque avec ces fonctions pour une utilisation plus simple et de partager la solution.
J'avais besoin d'exécuter plusieurs fenêtres Chrome au démarrage et la solution sur GitHub cible exactement ce problème (question connexe: https://superuser.com/a/901790/111424 ).
Mais la logique sous-jacente est la même:
Trouver le handle Windows à utiliser. Vous pouvez utiliser FindWindow ou EnumWindows dans des cas génériques en tant que Timwi . Mais si votre processus est simple et ne comporte qu'une seule fenêtre principale, c'est simplement:
var hndl = proc.MainWindowHandle
Ayant la poignée, vous pouvez utiliser la fonction suivante. Il vous suffit de fournir le numéro d'affichage (à partir de 1) et le descripteur:
public static bool MoveToMonitor(IntPtr windowHandle, int monitor)
{
monitor = monitor - 1;
return WinApi.SetWindowPos(windowHandle, IntPtr.Zero, Screen.AllScreens[monitor].WorkingArea.Left,
Screen.AllScreens[monitor].WorkingArea.Top, 1000, 800, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOREDRAW);
}
Vous pouvez trouver toutes les énumérations et importations de fonctions sur http://www.pinvoke.net/ ou simplement copier mon code sur GitHub: https://github.com/alex-tomin/Tomin.Tools.KioskMode .
Vous devez démarrer le processus, afficher la fenêtre principale du processus et utiliser un appel d'API, tel que SetWindowPos (), pour déplacer la fenêtre vers l'écran de votre choix.
Essayez de mettre ce code dans la méthode form_load
:
this.setdesktoplocation(int x, int y);
this.windowstate = formwindowstate.maximized;
La valeur de x doit être supérieure à la largeur de votre écran principal. Par exemple, si votre écran principal a une résolution de 1366 x 786 pixels, vous devez attribuer à x une valeur d'au moins 1368 ou supérieure.
Cela a fonctionné pour moi. Mais c'est juste à des fins de débogage seulement. Après tout, vous devrez l'exécuter sur le moniteur principal lorsque l'application est terminée.