Есть ли способ запустить/обедать программой через Process на другом экране?
Кто-то спросил, что здесь, но ответа не было.
Примечание: это не форма в моем приложении, я прошу запустить внешнюю программу на другом экране!
Есть ли способ запустить/обедать программой через Process на другом экране?
Кто-то спросил, что здесь, но ответа не было.
Примечание: это не форма в моем приложении, я прошу запустить внешнюю программу на другом экране!
Поскольку окно не принадлежит вам, вы можете перемещать его только с помощью Windows API. Вам нужно будет сделать это:
Запустите процесс.
Используйте FindWindow
для извлечения дескриптора в окно. Если окно еще не существует, процесс еще не создал его; спать на 500 мс, а затем повторить попытку. (Но не входите в бесконечный цикл, остановитесь, если не сможете найти окно после разумного тайм-аута.)
Используйте SetWindowPos
, чтобы изменить положение окна.
Если вы не знаете название окна, вы не можете использовать FindWindow
. В этом случае
Запустите процесс и получите дескриптор процесса, извлекая Process.Handle
.
Используйте EnumWindows
для извлечения всех окон. Для каждого окна используйте GetWindowThreadProcessId
, чтобы проверить, принадлежит ли он вашему процессу. Если ни одно окно не принадлежит вашему процессу, подождите и продолжайте попытки.
Используйте SetWindowPos
, чтобы изменить положение окна.
Конечно, вы можете использовать Screen.AllScreens[n].WorkingArea
для получения позиции и размера требуемого экрана, а затем вы можете поместить окно относительно этого.
Сначала выйдите из области второго монитора, используя что-то вроде:
Rectangle area = Screen.AllScreens[1].WorkingArea;
Используйте Windows API SetWindowPos, чтобы переместить его, используя Process.MainWindowHandle, вы получили от запуска другого процесса как дескриптор.
Timwi предоставил очень полезный совет, поэтому я решил создать powershell script для вызова библиотеки с этими функциями для более удобного использования и совместного использования решения.
Мне нужно было запустить несколько окон Chrome при запуске, и решение на GitHub предназначено именно для этой проблемы (связанный с этим вопрос: https://superuser.com/a/901790/111424).
Но основная логика одна и та же:
Найдите Windows Handle для работы. Вы можете использовать FindWindow или EnumWindows в общем случае в качестве Timwi. Но если ваш процесс прост и имеет одно главное окно, это просто:
var hndl = proc.MainWindowHandle
С помощью дескриптора вы можете использовать следующую функцию. Вам просто нужно указать номер дисплея (начиная с 1) и дескриптор:
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);
}
Все перечисления и функции импорта вы можете найти на http://www.pinvoke.net/ или просто скопировать мой код в GitHub: https://github.com/alex-tomin/Tomin.Tools.KioskMode.
Вам нужно будет запустить процесс, получить главное окно процессов и использовать вызов API, например SetWindowPos(), чтобы переместить окно на требуемый экран.
Попробуйте поместить этот код в метод form_load
:
this.setdesktoplocation(int x, int y);
this.windowstate = formwindowstate.maximized;
Значение x должно быть больше ширины вашего основного экрана. Например, если ваш основной экран имеет разрешение 1366 на 786 пикселей, вы должны указать x значение не менее 1368 или выше.
Это сработало для меня. Но это только для целей отладки. В конце концов, вам нужно будет запустить его на главном мониторе, когда приложение будет завершено.
Если вы не максимизируете окно, но не закрываете его при закрытии, при следующем открытии приложения оно будет отображаться на мониторе, в котором оно было в прошлый раз.
Если приложение/окно развернуто при закрытии, и если вы откроете его снова в следующий раз, оно появится на вашем основном мониторе.