Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.06.2009, 18:01   #1
butterflight
 
Регистрация: 07.06.2009
Сообщений: 5
По умолчанию CreateCompatibleDC(NULL) - для какого HDC создаётся compatible DC

Когда я вызываю CreateCompatibleDC(NULL), то данный вызов, как я понимаю, эквивалентен вызову CreateCompatibleDC(hdc) для некоторого ненулевого hdc. Как узнать, для какого именно?

Вот, что сказано в MSDN по поводу данного вызова "If this parameter is NULL, the function creates a memory DC compatible with the application's current screen". Если это так, то как получить HDC для "application's current screen"?

Дело вот в чём. Некоторые словари, напрмер, Lingvo >=12, используют технику API hooking для перевода текста, над которым находится указатель мыши. В моём случае, нужно обрабатывать текст, который принадлежит определённым окнам. Первоначально, моей идеей было - перехватывать функции типа DrawText, TextOut и др., получать передаваемый в них hdc и при помощи WindowFromDC определять в каком окне происходит отображение текста. Однако выяснилось, что некоторые приложения перед тем как отобразить текст создают контекст в памяти при помощи CreateCompatibleDC(NULL), в котором происходит весь текстовый вывод. Я просто думал перехватить вызов CreateCompatibleDC(NULL), определить реальный hdc, а по реальному hdc при помощи WindowFromDC определить дескриптор окна. Возможно, данный способ не очень красивый (а возможно и принципиально неправильный из-за моего непонимания). Но другого пока я не придумал.

Последний раз редактировалось butterflight; 14.06.2009 в 21:32. Причина: уточнение вопроса
butterflight вне форума Ответить с цитированием
Старый 14.06.2009, 21:02   #2
Д'якон
Форумчанин
 
Регистрация: 05.12.2007
Сообщений: 236
По умолчанию

Что-то я вопроса не понял, но посоветую GetDC, если имелось в виду именно это.
Д'якон вне форума Ответить с цитированием
Старый 14.06.2009, 21:35   #3
butterflight
 
Регистрация: 07.06.2009
Сообщений: 5
По умолчанию

GetDC требует дескриптор окна, который мне не известен. В действительности меня интересует именно дескриптор окна, который я собирался определить при помощи WindowFromDC(hdc).
butterflight вне форума Ответить с цитированием
Старый 15.06.2009, 00:13   #4
Д'якон
Форумчанин
 
Регистрация: 05.12.2007
Сообщений: 236
По умолчанию

Можно по фокусу определить дескриптор окна, можно по имени окна, смотря что вам известно? Если собираешься перехватывать в определенных окнах, значит должно быть известно имя окна. Либо просмотреть все окна, определить процесс, а потом имя исполняемого файла, если отбор идет по имени запущенных программ
Д'якон вне форума Ответить с цитированием
Старый 15.06.2009, 14:31   #5
butterflight
 
Регистрация: 07.06.2009
Сообщений: 5
По умолчанию

Попытаюсь объяснить. Есть анализируемая программа, допустим, Internet Explorer 5.0 (исходников к ней, понятно, нет), которая имеет несколько окон (в случае IE, в каждом окне отображается соответствующая страница). Необходимо написать программу-анализатор, которая анализирует текстовое содержимое каждого из окон. Скажем, если в тексте, отображаемом в окне IE, присутствует слово sex, то необходимо закрыть данное окно (лишь одно окно, где есть sex, но ни в коем случае не все окна процесса).

Спрашивается, на каких идеях строить подобный анализатор. Первое, что пришло в голову перехватывать вызовы DrawText, TextOut, etc. при помощи техники API hooking и, исходя из передаваемого данным функциям в качестве параметра текста, делать дальнейший анализ. В этом случае код программы будет состоять из 2 частей: 1) - перехватчик функций DrawText, TextOut и т.д.; 2) - парсер, который получает текст от перехватчика и принимает решение о закрытии окна приложения.

При этом возникает проблема: как определить, в каком из окон IE будет отображён перехваченный текст с ключевым словом? Ведь в функциях DrawText, TextOut, etc. дескриптор окна (HWND) не передаётся, передаётся лишь декскриптор контекста устройства (HDC). Как связать HDC и HWND? Я знаю только один способ - WindowFromDC. Оказалось, однако, что очень часто создаётся контекст в памяти при помощи CreateCompatibleDC(NULL), который и передаётся в DrawText, TextOut, etc. Вызов WindowFromDC для контекста в памяти даёт NULL информации об окне, то бишь ничего не даёт. В любом случае связывание контекста в памяти с контекстом окна рано или поздно должно произойти (иначе текст просто не будет отображён).

Это может произойти или при создании контекста в памяти при помощи CreateCompatibleDC(NULL) - с каким контекстом связывает система создаваемый контекст (если вообще с каким-то связывает)? (Это и был мой первоначальный вопрос. Мне казалось, что функция CreateCompatibleDC(NULL) внутри себя определяет действительный hdc нужного окна и создаёт совместимый контекст именно для действительного hdc.)

Либо это может произойти на более позднем этапе, когда контекст в памяти уже содержит полностью подготовленное изображение. В этом случае, как я понимаю, должны вызываться BitBlt или StretchBlt? Данные функции копируют изображение из одного контекста hdcSrc в другой - hdcDest. К сожалению, по непонятным для меня причинам перехват BitBlt и StretchBlt ничего не дал - вызовы BitBlt, StretchBlt, в которых контекст, созданный при помощи createCompatibleDC(NULL), передавался бы в качестве hdcSrc попросту отсутствуют. Если у кого-то есть соображения почему они могут отсутствовать - с удовольствием выслушаю.

В конечном итоге, задача состоит в определении связи между контекстом в памяти и окном в которое этот контекст в конечном итоге будет отображён. Любые идеи приветствуются.

По поводу определения активного окна. Страница с ключевым словом может загружаться и не будучи активной, текст в ней будет перехвачен, передан парсеру, а парсер закроет другое окно. Это не совсем то, как мне кажется. По крайней мере, я пытался это делать при помощи функции GetGUIThreadInfo. Определялось другое окно.

Последний раз редактировалось butterflight; 15.06.2009 в 14:38.
butterflight вне форума Ответить с цитированием
Старый 15.06.2009, 14:41   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Уй-юй-юй... А чего бы просто не написать проксисервер и не анализировать им?
Или в крайнем слечае подсоединиться к IE как к СОМ серверу?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 15.06.2009, 15:49   #7
butterflight
 
Регистрация: 07.06.2009
Сообщений: 5
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Уй-юй-юй... А чего бы просто не написать проксисервер и не анализировать им?
Или в крайнем слечае подсоединиться к IE как к СОМ серверу?
Вы считаете написать прокси проще? Мне казалось, что перехват API как раз-таки проще. Я сразу получаю весь текст безразлично к тому как он передаётся (зашифрован или закодирован - не имеет значения). Перехват API довольно универсальная техника. Приложение так или иначе должно обратиться к функциям вывода текста будь-то браузер или какая-либо другая программа типа Skype, ICQ или почтового клиента, вне зависимости от того поддерживает ли оно интерфейс COM-сервера или нет.

Тем более, что определённая часть кода по внедрению DLL и перехвату API у меня уже написана. Неужели связывание контекстов с окнами операционной системой настолько сложный и малопонятный механизм, что в него нельзя внедриться, перехватив пару-тройку API?

По поводу подсоединения как к COM-серверу - я не очень силён в деталях реализации этого метода. Насколько это универсально? Все ли браузеры обязаны поддерживать его?

Например, здесь: http://nibuthomas.com/2008/08/15/cap...-mouse-cursor/ приведён пример прграммы определения текста, находящегося в "чужом" приложении под курсором мыши. Могу сказать, что у меня данная программа работает не со всеми приложениями, с которыми работает API hooking.
butterflight вне форума Ответить с цитированием
Старый 15.06.2009, 16:23   #8
barand
Пользователь Подтвердите свой е-майл
 
Регистрация: 21.06.2008
Сообщений: 12
По умолчанию

butterflight!
У меня проблема, как у тебя, кажется, один к одному. Вот только исследуемые проги разные. И опыта у меня поменьше.

Ты пишешь:
"В любом случае связывание контекста в памяти с контекстом окна рано или поздно должно произойти"
Вот именно. Это предполагает исследование программы. Тяжело это.

Ещё смотри. У тебя, видать, существует какой-нибудь аналог BitBlt. Но!
Если ты думаешь, что перехватишь этот аналог и почерпнёшь информацию о соответствии контекста памяти контексту окна, то ошибаешься. (Рад буду, если это не так)

Я, например, могу перехватывать BitBlt в тех и только тех случаях, когда дескриптор целевого DC есть дескриптор некоторого определённого нужного мне окна
(Я к чему это? Просто рано или поздно ты найдёшь аналог BitBlt, но много ли он даст?)

Вот такой код выполняется у меня вместо BitBlt

Код:
push [esp+4]
;положил в стек значение "дескриптор целевого DC"

call WindowFromDC
;вызвал WindowFromDC

cmp eax, <некоторое значение>
;сравниваю значение, которое возвратило WindowFromDC с хэндлом
;нужного мне окна (подробнее ниже)

jne метка
;если значения разные, то прыгаю на метку

nop
nop
;...если значения одинаковые, то выполняю некотрые действия. Я 
;записываю в текстовый файл значение [esp+18], которое есть (по твоей ;терминологии) DC контекста в памяти

метка:
mov edi, edi
push ebp
mov ebp, esp
jmp <адрес BitBlt+5>
Теперь смотри. Я и BitBlt перехватил и есть у меня текстовый файл с разными hdc. (Но все они объединены одним- в них в разное время "рисовали текст" функции (в моём случае DrawTextw и TextOutW) и контексты памяти с такими hdc соответствовали определённому окну)

Но правильно ты говоришь- в какой момент было такое соответствие определено? Просто из перехвата не понять. Тут исследовать программу надо.

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

Потом ещё поразмышляю.
А вот к тебе вопрос- я перехватываю CreateCompatibleDC, но параметр, переданный в неё почему-то не ноль.

То есть я понимаю, что это какое-то заданное устройство и CreateCompatibleDC вернёт дескриптор контекста устройства, котрое с этим устройством совместимо.
В общем, наговорил-наговорил, аж сам не понял. Если речь идёт об окне- передаём в CreateCompatibleDC хэндл окна, что ли?

Последний раз редактировалось rpy3uH; 15.06.2009 в 17:41.
barand вне форума Ответить с цитированием
Старый 15.06.2009, 22:22   #9
butterflight
 
Регистрация: 07.06.2009
Сообщений: 5
По умолчанию

Цитата:
Сообщение от barand Посмотреть сообщение
А вот к тебе вопрос- я перехватываю CreateCompatibleDC, но параметр, переданный в неё почему-то не ноль.
Не вижу вопроса. То что параметр не NULL ничему не противоречит. Если WindowFromDC от него не NULL, то можно определить окно, на котором, скорее всего, будет отображена информация, которую ты перехватываешь через DrawText, TextOut.

Почему BitBlt не принимает в качестве параметра hdcSrc созданный в памяти контекст, я не знаю. Графическая информация, подготовленная через контекст в памяти, отображается в окне при помощи BitBlt. Другой вопрос, что дескриптор контекста, передаваемый BitBlt, не совпадает с дескриптором, созданным CreateCompatibleDC.
butterflight вне форума Ответить с цитированием
Старый 16.06.2009, 21:19   #10
barand
Пользователь Подтвердите свой е-майл
 
Регистрация: 21.06.2008
Сообщений: 12
По умолчанию

Цитата:
Сообщение от butterflight Посмотреть сообщение
Другой вопрос, что дескриптор контекста, передаваемый BitBlt, не совпадает с дескриптором, созданным CreateCompatibleDC.
А не в том ли дело, что CreateCompatibleDC создаёт некоторый промежуточный дескриптор? Сперва в него всё "прописывается" или "рисуется", не знаю, как правильно сказать.
А потом из этого промежуточного дескриптора с помощью BitBlt прописывается в контекст устройства, который соответствует окну.
(Предпоследний найден, предполагаю с помощью GetDC)
Вот, посмотри эту тему, в частности сообщение N 4. Как раз об этом
http://www.wasm.ru/forum/viewtopic.php?id=33082

Ну и от себя. Я читал где-то в инете, что промежуточные усройства вот для чего используются: если, допустим с помощью TextOut рислвать текст не в промежуточном устройстве, а сразу в окне, то после прорисовки каждой стоки будет происходить мигание окна.
Надеюсь, помог в прояснении.
barand вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
operator= для NULL Selebro Общие вопросы C/C++ 2 14.12.2008 16:29
Обработка значения Null в sql запросе KeyDok БД в Delphi 6 13.07.2008 12:03
delete where fields=null??? Geddar SQL, базы данных 1 02.06.2008 16:57
Delphi 2007 и NULL nemaster21 Общие вопросы Delphi 14 23.04.2008 16:59
вопрос time(NULL) Ceprey Общие вопросы C/C++ 5 07.03.2008 11:30