Наложение на полноэкранное 3D-приложение - PullRequest
40 голосов
/ 29 мая 2009

Я хочу отобразить пользовательскую графику поверх полноэкранного приложения Windows стороннего производителя.

Вы играли в какие-нибудь игры в Steam? Он имеет исполняемый файл GameOverlayUI.exe, который позволяет вам получить доступ к окнам Steam из игры. (Элементы графического интерфейса выглядят специально, я не знаю, является ли это необходимостью; но внутри игры они выглядят точно так же, как и на рабочем столе.) Даже «затемнение» игровой графики выглядит так фон.

Мне интересно, как можно написать такое приложение.

Мне также интересно, насколько широким будет диапазон решений. Не могли бы вы использовать один метод для всех приложений OpenGL? Для всех Direct3D минус DirectDraw приложений? Для всех полноэкранных приложений Windows?

Я ищу более «современные» и универсальные решения - наложение командной строки или приложения с индексированным цветом 320x240 не представляет проблемы.

Редактировать: Некоторые разъяснения: полноэкранное приложение не мое. Это может быть что угодно. Скорее всего, это будет 3D игра. Я хочу отобразить, скажем, цифровые часы в правом нижнем углу экрана, поверх игровой графики. Я хотел бы избежать трюков, таких как внедрение кода или отладка процесса, если это возможно.

Ответы [ 5 ]

23 голосов
/ 05 ноября 2009

Ну, вот еще один пример. Xfire - это программа чата, которая накладывает свой интерфейс на игры, чтобы вы могли получать сообщения во время игры. Они делают это путем редактирования DLL-библиотеки d3d / opengl на уровне памяти процесса, например, путем внедрения скачков сборки. Я знаю это, потому что их метод вызывал сбой моего мода, и я действительно видел странный ассемблерный код, который они вставляли в d3d9.dll.

Итак, вот как Xfire делает это:

  1. цель процесса игры
  2. искать в памяти процесса d3d.dll / opengl.dll
  3. внедрить в процесс DLL, содержащую пользовательскую логику интерфейса
  4. связывает функции интерфейса с потоком программы, вручную записывая переходы сборки в функции d3d / opengl, найденные в памяти процесса

Нет другого мыслимого способа, поскольку вам нужно захватить графическое устройство, принадлежащее этой игре. Я готов поспорить, что Steam делает это так же, как Xfire. Так что да, нет простого способа сделать это, если кто-то не создал полезную библиотеку, которая сделает все, что вам нужно, на низком уровне.

Вы также спрашивали о затемнении игровой графики под вашим оверлеем. Это простой вызов DrawPrimitive для рисования прозрачного прямоугольника с заливкой поверх экрана.

21 голосов
/ 02 ноября 2009

Создан Gist с полным кодом здесь

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

Все игры Direct3D9 должны вызывать IDirect3DDevice9 :: EndScene после того, как экран отрендерен и готов к рисованию. Таким образом, теоретически мы можем поместить собственный код внутри EndScene, который рисует то, что мы хотим в игре. Мы делаем это, создавая в игре класс, который выглядит как IDirect3DDevice9, но на самом деле это просто оболочка, которая перенаправляет все вызовы функций в реальный класс. Итак, теперь в нашем пользовательском классе наша функция-обёртка для EndScene выглядит следующим образом:

HRESULT IDirect3DDevice9::EndScene()
{
   // draw overlays here

   realDevice.EndScene();
}

Затем мы скомпилируем ее в DLL-библиотеку d3d9.dll и поместим в каталог исполняемого файла игры. Настоящий d3d9.dll должен находиться в папке / system32, но игра сначала просматривает текущий каталог, а вместо этого загружает наш. Как только игра загружается, она использует нашу DLL для создания экземпляра нашего класса-оболочки. И теперь каждый раз, когда вызывается EndScene, наш код выполняется для отрисовки того, что мы хотим на экране.

Я думаю, вы можете попробовать тот же принцип с OpenGL. Но, чтобы предотвратить вмешательство, я думаю, что некоторые современные игры пытаются предотвратить это.

2 голосов
/ 06 мая 2010

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

0 голосов
/ 16 ноября 2009

Я думал об этом. Для OpenGL я бы подключил WGL SwapBuffers к Detours, рисовал свои вещи после игры, а затем сам менял буферы.

0 голосов
/ 29 мая 2009

Я сделал оверлеи для обоих окон просмотра DirectX и WPF (одно и то же), используя оверлей, чтобы нарисовать некоторые приятные 2D GDI + вещи поверх 3D визуализаций.

Мне удалось с помощью панели поверх «фактической» визуализации установить прозрачный цвет, за исключением битов, которые я хотел наложить. Работало довольно хорошо, но было немного трудно передать клик, перетаскивание и другие события через слой «Рисование» в 3D-элемент управления.

...