Перехват функций Gdi32

Тема в разделе "WASM.WIN32", создана пользователем gloomyraven, 19 янв 2009.

  1. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    Добрый день!
    Такая проблема:
    Есть многопоточное приложение.
    Для каждого потока создается окно.
    В 1-м потоке создается hdc1=CompatibleDC c параметром 0, т.е. для всего экрана процесса (поправьте, если не прав).
    В остальных окнах(потоках) выводится графика НА ЭКРАН из файла в ЭТОТ самый контекст устройсва (hdc1), причем разные окна выводят в одни и те же координаты... Как это возможно?

    Графика выводится функцией AlphaBlend.
    Нужно определить "какое именно окно вызвало эту функцию" или "в какое окно выводится графика"

    Перехват функций делаю методом сплайсинга (хотя это наверно не важно).

    Помогите плиз, уже мозг взрывается (гуглил, курил "Программирование графики" Фень Юаня)
     
  2. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    Сделаю небольшую поправку: я не уверен, что окна создаются в разных потоках (хотя это было бы логично).
    Когда я попадаю в функцию-обработчик OnAlphaBlend я вызываю GetCurrentThread. Возвращаемое значение одинаково для разных окон (может это потому, что GetCurrentThread вызывается в контексте перехватчика?).
     
  3. umka60

    umka60 New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2009
    Сообщения:
    7
    GetCurrentThread возвращает всегда в контексте того, кем вызванна перехваченная функция.
    если с тредами не катит, попробуй узнать с какого адресса вызвали процедуру. для этого смотри в стеке, что находиться сразу за параметрами, оно как раз и будет адресс куда будет возвращаться после ret из процедуры.
     
  4. umka60

    umka60 New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2009
    Сообщения:
    7
    ой, все таки я слепой. но тот метод тоже можно юзать :) GetCurrentThread возвращает не хендл текущего треда, а его псевдо значение, как и у процессов такое есть. у процессов хендл своего процесса -1. у тредов -2.
    юзай GetCurrentThreadId !!!!! они точно разные должны быть
     
  5. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    umka60
    щас вкурну и попробую...
     
  6. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    umka60
    ThreadId тоже один и тот же...
     
  7. umka60

    umka60 New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2009
    Сообщения:
    7
    значит это реально один и тот же тред.
    смотри по стёку как я писал выше. но тут тоже может быть прикол, что эта функция вызвается из другой одной и тойже функции. но опять же по стеку можно выследить :) правда занятие не очень веселое :dntknw:
     
  8. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    думаю, что все банально сводится к функции окна (допустим, событие WM_PAINT). Они же (ф-ии окон) могут находится в одном потоке? Тогда как узнать к какому чертовому окну они относятся?
     
  9. umka60

    umka60 New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2009
    Сообщения:
    7
    функции обработчику окна, как раз куда пичкается WM_PAINT передается хендл окна hWin. Если твоя AlphaBlend вызывается из WndProc, то опять же в стеке можно найти параметр передаваемый WndProc - hWin.
     
  10. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    umka60
    вариант конечно хороший... но не универсально

    пока остановился на следующем способе:
    Есть глобальная переменная curhWnd которая содержит хэндл окна, которое в данный момент обновляется
    1. Перехватываю создание окон в процессе-жертве (получаю их hWnd и заношу в список)
    2. перехватываю функцию hdc = BeginPaint(hwnd) в процессе-жертве, заношу hwnd в curhWnd
    3. при выводе графики по curhWnd определяю какое окно ее выводит

    Способ мне не нравится, хотелось бы услышать проф. мнение. Откуда программа должна знать в какое из ее окон нужно выводить содержимое контекста устройства?
     
  11. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    Все, вроде разобрался я с этой ерундой, если кому интересно - напишу
     
  12. Explode Sense

    Explode Sense New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2006
    Сообщения:
    130
    Адрес:
    Russia
    Интересно, напиши
     
  13. Explode Sense

    Explode Sense New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2006
    Сообщения:
    130
    Адрес:
    Russia
  14. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    Explode Sense
    Чуть позже, сформулирую мысли
     
  15. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    Explode Sense
    Как я понял, есть два типа контекстов устройств: просто контекст (в памяти) и контекст, связанный с окном.
    Если необходимо перехватывать вывод графических объектов в окно программы, то необходимо решить следующие задачи:
    1. Перехватить функции открытия/закрытия файлов, считывания изображений из файлов (например libjpeg.dll), создания DIB секций/битмапов, копирования изображений (BitBlt, StretchBlt и т.д.)

    2. Определить за какими граф. объектами необходимо следить (картинки из файлов, ресурсы)

    3. При открытии изображения заносить из в список. В итоге мы должны знать по какому адресу в памяти находится изображения или в какой DIB секции (битмапе) оно находится.

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

    5. Определить какой объект в данный момент копируется: GetCurrentObject(hdc источника/назначения)
    По хэндлу объекта мы можем его идентифицированть по имени (пунтк 2)
    Теперь мы знаем что именно копируется и в какой объект, если нет, то область копирования может быть как неизвестным объектом, так и совокупностью известных объектов.
    Вот здесь самое интересное, если используется двойная (н-ая) буферизация для быстрого вывода графики, то нам нужно определить какие объекты находятся в hdc источника ПО КООРДИНАТАМ.
    Когда определили, необходимо перенести объекты из hdc источника в hdc назначения с УЧЕТОМ масштабирования.
    Тем самым мы сможем проследить всю цепочку перемещений нашего граф. объекта по различным контестам устройств.
    Потом (я надеюсь) мы попадаем в 4-й пункт, а там мы уже имеем весь список объектов на холсте.

    Если что не понятно (а я думаю, что ничо не понятно) пиши, попытаюсь разъяснить.
     
  16. Explode Sense

    Explode Sense New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2006
    Сообщения:
    130
    Адрес:
    Russia
    Всё более чем понятно, спасибо. Интересный подход, попробую сегодня же.
     
  17. gloomyraven

    gloomyraven Руслан

    Публикаций:
    0
    Регистрация:
    16 апр 2006
    Сообщения:
    288
    Адрес:
    Москва
    Explode Sense
    Слушай, раз ты с gdi работаешь, помоги решить проблему с масштабированием.
    Пытаюсь сделать с помощью деления, умножения, но при таком подходе масштабированные точки не корректны (на пару пикселей)