Сграбить клиентскую область окна

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

  1. Enterado

    Enterado New Member

    Публикаций:
    0
    Регистрация:
    25 дек 2008
    Сообщения:
    99
    Необходимо получить снэпшот клиентской области окна и сохранить его в файле. Хэндл окна известен. Задача получения скриншота целого экрана тривиальна -- здесь же надо получить снимок окна и в тех случаях, когда окно или его часть не находятся на переднем плане (перекрыто полностью или частично другими окнами). Пробовал с помощью BitBlt и с помощью SendMessage WM_PRINT -- не получается. Снэпшоты нужны для анализа состояния приложения из другой программы и принятия решения на основе такого анализа.
     
  2. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Надо подумать
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    SetForegroundWindow ?
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Не уверен, но по моему если окно закрыто другим окном, то контекст затирается..
    В таком случае необходимо перехватить функции, которые перерисовывают изображение, либо подменить хэндл окна/контекста.
     
  5. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Вопрос класса "феникс", => поиск по форумам.

    Обычно первый совет - PrintWindow.
    Если "ой, это для XP+, а надо, чтоб и на 98", - тогда советуют WM_PRINT + посылают к статье Фень Юаня.
    А еще спросят: а так ли уж необходим "для анализа" скриншот ?
     
  6. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    ф принципе еси перехватить вм_еразебкгнд, и фуеки выделения дц, посылая свое дц на компатибле битмап, то можно попробовать послать вм_пэйнт. а можно просто врезаться и блитать скрин на клиент и сохраняя параллельно в цепочке картинок. тогда можно просто работать с окном без лишних движений, а потом просмотреть скрины
     
  7. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    _basmp_ , а это точно вы писали ? :)

    P.S. как насчет демки, - ваших вариантов в вашем же исполнении ?
     
  8. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    kero
    пока шо я занят. и минимум неделю еще буду. а потом, еси проблема не решится, можно будет и попробовать извратиться заради эксперимента
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    kero
    Вот только не известно обработает ли приложение это сообщение, видимо в данном случае нет:
    Кстати если и получится, то в большинстве случаев всё изображение с окна не удастся считать, так как оно частями выводится обычно.
    Есть мысль заюзоть видимость окна, тоесть сделоть его не видимым посредством NtUserShowWindow(SW_HIDE) послать сообщение для перерисовки и считать контекст. Будет работать ?
     
  10. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Clerk
    С чего вы взяли ??

    Ну, попробуйте :)
    Но если еще не читали - почитайте упомянутую выше статью Фень Юаня о WM_PRINT.
    Похоже, WM_PRINT - единственный способ заснять невидимое окно (во всяком случае на Win<=XP, с Вистой не знаком).

    [offtop]
    Clerk, вы упорно пишете "заюзОть", "сделОть", etc.
    Если это такая манера - ну, бог вам судья.
    Если же это рефлекторная систематическая описка - стоит поправить: надо через "А".
    Если прислушаетесь - буду искренне признателен: сам не знаю почему, но страшно раздражает :)
    [/offtop]
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    kero
    Практический опыт, скока GUI дебажил, не разу не видил построение изображения в памяти и вывод на контекст окна.
    Смотри, взять любое приложение, проигрователь, текстовый редактор, игру любую - изображение обычно строится участками, через BitBlt() части его выводятся. На счёт указанной статьи всё верно, так как там строится примитив одной операцией.
    Мошинально, учту.
     
  12. Enterado

    Enterado New Member

    Публикаций:
    0
    Регистрация:
    25 дек 2008
    Сообщения:
    99
    Благодарю всех за оказанное содействие. Feng Yuan really rulez! В его примере полученный bmp сохр. в буфер обмена. Как, используя Win API, сохр. его в файл? Поделитесь, мож есть у кого ссылки на Windows Graphics Programming: Win32 GDI and DirectDraw. Судя по статье, автор заслуживает всяческого респекта.
     
  13. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Clerk
    Мое "с чего вы взяли" относится вот к чему:
    Хотели вы того или нет, но звучит как "в большинстве случаев скриншот окна взять не удастся".
    Что "в большинстве случаев" попросту неверно.

    Но давайте все же останемся в рамках задачи ТС, т.е. будем иметь в виду снимок окна, которое partially blocked, но не hidden.

    Кроме WM_PRINT, требующего внедрения в чужой процесс, есть и способы без внедрения, и это - не только PrintWindow.
    (Само собой, способы не без ограничений, но об этом не сейчас).
    На скриншоте - черновая спец.демка PrintLayered, только что - после клика по кнопке "BitBlt /srccopy" -
    отскриншотившая "всё изображение с окна" калькулятора, которому временно назначен стиль WS_EX_COMPOSITED;
    окно калькулятора частично сдвинуто за пределы экрана, частично перекрыто окном другой проги, и согласитесь - не примитив:

    [​IMG]
     
  14. Enterado

    Enterado New Member

    Публикаций:
    0
    Регистрация:
    25 дек 2008
    Сообщения:
    99
    kero -- волшебник, спору нет. Риспект и благодарность. Полная моя задача состоит в написании почти универсального бота для игры в русские шашки. А эта подзадача возникла вследствие того, что не во всех шашечных программах можно читать ход противника из текстового поля. Сорцы шашечного движка у меня есть и программно кликать мышкой умею. Осталось малое :) -- собрать всё это воедино.
     
  15. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Сохранить в файл очень просто
    тебе надо будет две структуры и одна функция.
    Вот эти структуры (приведу на паскале, так что не пинайте):
    Код (Text):
    1. tagBITMAPINFO = packed record
    2.     bmiHeader: TBitmapInfoHeader;
    3.     bmiColors: array[0..0] of TRGBQuad;
    4. end;
    Код (Text):
    1. tagBITMAPFILEHEADER = packed record
    2.     bfType: Word;
    3.     bfSize: DWORD;
    4.     bfReserved1: Word;
    5.     bfReserved2: Word;
    6.     bfOffBits: DWORD;
    7. end;
    И функция:
    Код (Text):
    1. function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT;
    2.   Bits: Pointer; var BitInfo: TBitmapInfo; Usage: UINT): Integer; stdcall; external 'gdi32.dll';
    Думаю в МСДНе есть описание этой функции. Потому не буду описывать, что к чему.
    Структура файла:
    BmpFileHeader
    BmpHeader
    И потом данные.

    Вот соорудил примерчик (Опять таки на паскале)
     
  16. Enterado

    Enterado New Member

    Публикаций:
    0
    Регистрация:
    25 дек 2008
    Сообщения:
    99
    Благодарю за участие. Всё расписал как на пальцах. А что на паскале -- так мне без разницы, CPP, Asm, С#, Delphi -- для понимания сути это не критично. А код такой переписать на C -- легко. WriteFile только заменить, остальное -- API-шное, структуры данных -- есть соответствующие.
     
  17. koderr

    koderr New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2006
    Сообщения:
    205
    А если окно со скроллбарами? Можно ли получить все содержимое окна без инициации прокрутки всей области?