Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Снимок экрана приложений использующих DirectX  (Прочитано 19273 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
Axenic
Гость
« : 15-02-2010 18:33 » 

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

Fraps делает снимки как надо и так понял он использует для снятие скриншотов технологию DirectX.

Я ничего не понимаю в DirectX и мне не сильно хочется тратить 2-3 месяца на его изучение чтобы узнать написать только одну функцию. Для моего проекта мне вполне хватает GDI+ который я по мере продвижения подучиваю.

Если у кого-нибудь есть функция, которая делает снимок игры в полноэкранном режиме и записывает это все в Bitmap, то выложите пожалусто. И если у Вас её нет, но вы знаете как просто её написать, тоже выложите Улыбаюсь
Записан
zubr
Гость
« Ответ #1 : 16-02-2010 13:35 » 

Задача однозначно не в одну функцию. Тебе надо получить HDC оверлея, а для этого надо получить доступ к интерфейсу IDirectDraw процесса, осуществляющего вывод видеопотока через DirectX. Если это твой процесс то задача решается просто, иначе надо перехватывать API-функцию DirectDrawCreate. Ну и еще вариант - видео-драйвер-фильтр.
Записан
Axenic
Гость
« Ответ #2 : 16-02-2010 18:26 » 

Загрузил Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 09-03-2011 21:11 » 

Задача однозначно не в одну функцию. Тебе надо получить HDC оверлея, а для этого надо получить доступ к интерфейсу IDirectDraw процесса, осуществляющего вывод видеопотока через DirectX. Если это твой процесс то задача решается просто, иначе надо перехватывать API-функцию DirectDrawCreate. Ну и еще вариант - видео-драйвер-фильтр.
о, я так понимаю, это то, что мне сейчас надо ) А как такой перехват функции DirectDrawCreate делается ?
Записан

zubr
Гость
« Ответ #4 : 10-03-2011 07:49 » 

Алексей1153++, есть множество способов перехвата API-функций (подмена адреса перехватываемой функции в библиотеке, подмена адреса функции в адресном пространстве процесса, использование DebugApi), также есть несколько способов внедрения в адресное пространство чужого процесса (хук, CreateRemoteThread). Все это с примерами есть на wasm.ru. Также у Рихтера есть примеры. Правда во всех этих способах есть особенности, связанные с админскими правами, битностью системы (x86, x64).

Добавлено через 6 минут и 46 секунд:
Также надо будет и DirectDrawCreateEx перехватывать. С точки зрения простоты, то проще миррор-видеодрайвер замутить, просто пример из DDK скомпилировать и установить, но тормоза при этом ощутимые, да и полномочия нужны админские при установке + перезагрузка системы.
« Последнее редактирование: 10-03-2011 07:56 от zubr » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 10-03-2011 09:36 » 

zubr, да, я уже понял, что это не то немного ) Вечером поизучаю, как до поверхности (surface) десктопа добраться
Записан

zubr
Гость
« Ответ #6 : 10-03-2011 12:27 » 

Алексей1153++, если там DirectX, то других вариантов нет.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 11-03-2011 17:43 » 

так, что-то я запутался, с чего начинать. Всё-таки перехватить функцию DirectDrawCreateEx надо сначала ? Или же при помощи DX API можно прямо как-то с видеопамяти весь текущий битмап вытащить ?
Записан

zubr
Гость
« Ответ #8 : 11-03-2011 18:44 » 

Насколько я помню, интерфейсы DirectX не предоставляют методов для возможности перехватывать чужой видеопоток.
Поэтому остаются менее документированные способы перехвата. Перехватив DirectDrawCreateEx и DirectDrawCreate мы можем получить указатель на объект IDirectDraw, а у этого интерфейса есть метод получения указателя на объект IDirectDrawSurface. В свою очередь у объекта IDirectDrawSurface есть метод GetDC. Получив контекст видеопотока с ним можно работать как с обычным контекстом монитора.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 11-03-2011 18:53 » 

ок, спасибо. А перехват надо в отдельной DLL делать, я правильно понимаю ? И ещё - как определить, что поверхность принадлежит именно десктопу? Или там у них нет различий - поверхность всегда одна и та же?

Никогда перехваты не делал, никак не могу мозги направить в нужное русло...
Записан

zubr
Гость
« Ответ #10 : 11-03-2011 19:37 » 

Почему только декстоп? А если юзер открыл винамп с фильмом, здесь не декстоп, но на рабочем столе видео присутствует. По логике любое приложение, использующее DirectX, чтобы получить объект IDirectDraw, использует DirectDrawCreateEx или DirectDrawCreate. Определить можно имя процесса в котором произошло обращение к вышеуказанным функциям. Для перехвата надо внедряться в адресное пространство чужого процесса, а для этого можно использовать глобальный хук (dll), также можно делать инжект в внедряемый процесс, тут тоже удобнее всего, чтобы внедряемый код был в виде dll. Можно перехватывать, вообще не внедряясь в чужой процесс, для этого можно использовать DebugApi, тогда твой код перехвата может находиться в потоке основного приложения, причем для каждого перехватываемого процесса надо будет соответственно создавать отладочный поток в основном приложении. У каждого из способов перехвата есть свои преимущества и недостатки, трудно сказать, какой из них лучше.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 11-03-2011 21:01 » 

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

zubr
Гость
« Ответ #12 : 11-03-2011 22:33 » new

Недостатки этого метода:
1. Требуются админские полномочия, про UAC не знаю, не проверял, возможно будет выскакивать.
2. Зачастую разработчики ПО защищают свои проги от отладки, в этом случае будет облом, хотя при определенных извращениях защиту можно обойти (на хитрую ж..пу есть хрен с винтом, а на хр. с винтом есть ж..па с закоулками).
3. Если понадобится отключиться от отлаживаемого процесса, то это надо делать корректно, иначе можно убить отлаживаемый процесс.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines