Можно ли полностью использовать только один экран из нескольких экранов с .NET на Windows?

С .NET(любой версией), работающей в Windows XP/Vista/7/8, можно зарезервировать один экран для полноэкранного приложения и отобразить данные/графику/что угодно на нем, оставив любые другие экраны доступными для Пользовательское взаимодействие с пользовательским интерфейсом Windows, такое как рабочий стол или другие приложения?

Ниже приведен сценарий/правила использования:

  • ПК должен иметь возможность запускать все программы как есть.

  • Для содержимого .NET не требуется интерактивность (т.е. никаких нажатий клавиш, кликов мыши и т.д.).

  • Никакие другие пользовательские интерфейсы или диалоги других приложений не могут проникнуть в один предопределенный экран, зарезервированный для отображения результата из исполняемого файла .NET.

  • Предопределенный экран с содержимым .NET не должен иметь видимого указателя мыши, а на других экранах должны быть границы курсора, как если бы не было дополнительного экрана (т.е. курсор должен останавливаться по краям один или несколько рабочих столов).

  • Содержимое должно быть видимым, даже если компьютер заблокирован (то есть пользователь зарегистрирован, но рабочая станция заблокирована из проводника).

Я знаю, что могу добиться этого с помощью какого-то внешнего USB-контроллера, который управляет дополнительным монитором или другим устройством отображения, а затем вручную создает содержимое/графику для ввода этого интерфейса, но я прошу, могу ли я сделать это с помощью обычного WDDM драйверы с обычными мониторами?

Изменить. Для дальнейшего уточнения. Я понимаю, что существует несколько подходов к достижению аналогичного результата, но здесь возникает вопрос: можно ли соответствовать всем спецификациям/правилам выше.

Ответ 1

Подход, выбранный, который соответствует нескольким правилам проектирования, был... дождитесь его. Виртуализация. Однако он не соответствует требованию использования только исполняемых файлов .NET(для взлома WDDM).

Оригинальный ПК - это виртуальный хост с двумя гостями. Один для приложения .NET и один для конечного пользователя, которому присвоены соответствующие USB-устройства и т.д. Этот подход, естественно, имеет множество предостережений:

  • WDDM никак не задействован, и возможны проблемы с производительностью. Для случайного офисного приложения это, однако, не проблема.
  • Если вы не используете Hyper-V, программное обеспечение для виртуализации всегда является сторонним.
  • Hyper-V внутри Hyper-V невозможен, поэтому гость не может ничего виртуализировать (по крайней мере, не с какой-либо разумной скоростью, так как он будет работать без гипервизора).
  • В некоторых случаях требуется несколько лицензий для любого программного обеспечения.
  • Нет IPC или другого взаимодействия между исполняемыми и другими приложениями .NET между двумя гостями.

Однако само решение работает отлично - никоим образом пользователь не может переопределять или взаимодействовать с тем, что отображается на дополнительном экране, пока основной хост включен и не разбивается. Блокировка ПК конечного пользователя не влияет на других гостей и т.д.

Ответ 2

Мне кажется, что вы разрабатываете приложение .NET, которое будет использоваться исключительно для вывода (например, для отображения графика/графика, видео и т.д.). Приложение должно иметь выделенный монитор, и никакое другое приложение (или даже курсор не может войти в границы монитора).

У меня такое ощущение, что пока вы можете принудительно применить приложение к определенному монитору (у XBMC есть эта функция), я сомневаюсь, что вы можете помешать всем другим приложениям войти в область отображения монитора.

Когда я прочитал вопрос, что-то в моей голове щелкнул, и я подумал: "Может быть, вам нужно что-то похожее на родство cpu, которое вы можете установить в окнах, и заставить ваше приложение использовать только определенные ядра процессора... может быть, есть что-то подобное для мониторов/областей отображения?"

Конечно, Windows предоставляет следующие функции:

http://msdn.microsoft.com/en-gb/library/windows/desktop/dd375340(v=vs.85).aspx

http://msdn.microsoft.com/en-gb/library/windows/desktop/dd375338(v=vs.85).aspx

Вы должны иметь возможность выталкивать их без особых проблем. Однако это только решит, что вы сможете заставить приложение использовать только определенный монитор. Что касается любого другого приложения в системе, я сомневаюсь, что вы сможете легко контролировать свою близость.

По грубым предположениям, вам нужно будет использовать другой вызов API Win32, чтобы получить ссылки на все дескрипторы окон в системе и проверить их близость отображения, и если они отображаются на вашем выделенном мониторе, переместите их в другое место.

это может помочь получить все дескрипторы окон:

Как получить список или перечислить все ручки неуправляемых окон с тем же классом и именем

http://msdn.microsoft.com/en-us/library/ms633497%28VS.85%29.aspx

Просто подумал, что я брошу это там, это может быть не полезно, но, надеюсь, это должно дать вам еще какое-то направление.

EDIT: Я нашел это тоже... может быть полезным

зарезервировать область экрана в Windows 7

Ответ 3

  • ПК должен иметь возможность запускать все программы как есть.

  • Для содержимого .NET не требуется интерактивность (т.е. никаких нажатий клавиш, кликов мыши и т.д.).

  • Никакие другие пользовательские интерфейсы или диалоги других приложений не могут проникнуть в один предопределенный экран, зарезервированный для отображения результата из исполняемого файла .NET.

Одним из способов достижения этого может быть создание окна стыковки (AppBar). Это будет иметь аналогичные функции, такие как панель задач или настольные доки, такие как Google Desktop и т.д.

Эти две статьи могут помочь:
CodeProject: AppBar с использованием С#
CodeProject: создание приложения, такого как Google Desktop в WPF и С#

Другим способом обращения к # 3 является использование PInvoke (или даже лучше, Managed WinAPI) для сканирования вашего компьютера на открытые окна на регулярной основе интервалы. Если обнаружено, что окно "нарушает", вы просто привязываетесь к нему и перемещаете его. Не лучший подход, но он все равно работает.

4. На предопределенном экране с содержимым .NET не должно быть видимого указателя мыши, а на других экранах должны быть границы курсора, как если бы не было дополнительного экрана вообще (т.е. курсор должен останавливаться на краях одного или нескольких рабочих столов).

Задайте свойство курсора формы пустой. Это эффективно удаляет курсор мыши.
Остановка курсора от доступа к этой части экрана довольно сложна. Лучше всего использовать Global Mouse Hooks для прослушивания движения курсора и переместите курсор в области, занятые вашим окном. Это, очевидно, сделает установку свойства курсора формы бесполезной, поскольку курсор никогда не находится в форме в любом случае.

5. Содержимое должно быть видимым, даже если ПК заблокирован (то есть пользователь зарегистрирован, но рабочая станция заблокирована от проводника)

Я не знаю, как это сделать, чтобы создать приложение блокировки экрана, потому что стандартное поведение Windows - отключить все мониторы, кроме основного.

Edit
Вы можете отобразить окно на экране блокировки с помощью psexec.exe -x. PSEXEC является частью пакета SysInternals, доступным для загрузки из http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx.

Если вы намерены пройти этот путь (показывая свою форму поверх экрана блокировки), вам понадобится способ определить, когда пользовательский сеанс блокируется, поэтому вы изменяете размер своей формы и отключаете ее. В противном случае вам нужно будет найти способ разблокировать сеанс из вашего приложения.

Вы также можете взглянуть на этот вопрос Как отобразить пользовательский интерфейс на экране входа в Windows 7 для других способов реализации приложений блокировки экрана.

Ответ 4

Проект WPF, над которым я работаю, пошел по пути добавления всего внутри "мастер-контейнера", наследующего от System.Windows.Window, который настроен при запуске на основе предпочтений пользователя, чтобы быть либо всеми доступными экранами, либо окном, или один полный экран. Этот контроль затем просто устанавливает себя на основе предпочтения следующим образом:

    private void SpanAllMonitors()
    {
        WindowStyle = WindowStyle.None;
        ResizeMode = ResizeMode.NoResize;
        Width = SystemParameters.VirtualScreenWidth;
        Height = SystemParameters.VirtualScreenHeight;
        Left = SystemParameters.VirtualScreenLeft;
        Top = SystemParameters.VirtualScreenTop;
    }

    private void SingleScreen()
    {
        WindowStyle = WindowStyle.None;
        ResizeMode = ResizeMode.NoResize;
        Width = SystemParameters.PrimaryScreenWidth;
        Height = SystemParameters.PrimaryScreenHeight;
        // this will take over the 'primary' monitor, additional math
        // should allow you to place it on a secondary or other monitor
        Left = 0;
        Top = 0;
    }