Необходимо получить снэпшот клиентской области окна и сохранить его в файле. Хэндл окна известен. Задача получения скриншота целого экрана тривиальна -- здесь же надо получить снимок окна и в тех случаях, когда окно или его часть не находятся на переднем плане (перекрыто полностью или частично другими окнами). Пробовал с помощью BitBlt и с помощью SendMessage WM_PRINT -- не получается. Снэпшоты нужны для анализа состояния приложения из другой программы и принятия решения на основе такого анализа.
Не уверен, но по моему если окно закрыто другим окном, то контекст затирается.. В таком случае необходимо перехватить функции, которые перерисовывают изображение, либо подменить хэндл окна/контекста.
Вопрос класса "феникс", => поиск по форумам. Обычно первый совет - PrintWindow. Если "ой, это для XP+, а надо, чтоб и на 98", - тогда советуют WM_PRINT + посылают к статье Фень Юаня. А еще спросят: а так ли уж необходим "для анализа" скриншот ?
ф принципе еси перехватить вм_еразебкгнд, и фуеки выделения дц, посылая свое дц на компатибле битмап, то можно попробовать послать вм_пэйнт. а можно просто врезаться и блитать скрин на клиент и сохраняя параллельно в цепочке картинок. тогда можно просто работать с окном без лишних движений, а потом просмотреть скрины
kero пока шо я занят. и минимум неделю еще буду. а потом, еси проблема не решится, можно будет и попробовать извратиться заради эксперимента
kero Вот только не известно обработает ли приложение это сообщение, видимо в данном случае нет: Кстати если и получится, то в большинстве случаев всё изображение с окна не удастся считать, так как оно частями выводится обычно. Есть мысль заюзоть видимость окна, тоесть сделоть его не видимым посредством NtUserShowWindow(SW_HIDE) послать сообщение для перерисовки и считать контекст. Будет работать ?
Clerk С чего вы взяли ?? Ну, попробуйте Но если еще не читали - почитайте упомянутую выше статью Фень Юаня о WM_PRINT. Похоже, WM_PRINT - единственный способ заснять невидимое окно (во всяком случае на Win<=XP, с Вистой не знаком). [offtop] Clerk, вы упорно пишете "заюзОть", "сделОть", etc. Если это такая манера - ну, бог вам судья. Если же это рефлекторная систематическая описка - стоит поправить: надо через "А". Если прислушаетесь - буду искренне признателен: сам не знаю почему, но страшно раздражает [/offtop]
kero Практический опыт, скока GUI дебажил, не разу не видил построение изображения в памяти и вывод на контекст окна. Смотри, взять любое приложение, проигрователь, текстовый редактор, игру любую - изображение обычно строится участками, через BitBlt() части его выводятся. На счёт указанной статьи всё верно, так как там строится примитив одной операцией. Мошинально, учту.
Благодарю всех за оказанное содействие. Feng Yuan really rulez! В его примере полученный bmp сохр. в буфер обмена. Как, используя Win API, сохр. его в файл? Поделитесь, мож есть у кого ссылки на Windows Graphics Programming: Win32 GDI and DirectDraw. Судя по статье, автор заслуживает всяческого респекта.
Clerk Мое "с чего вы взяли" относится вот к чему: Хотели вы того или нет, но звучит как "в большинстве случаев скриншот окна взять не удастся". Что "в большинстве случаев" попросту неверно. Но давайте все же останемся в рамках задачи ТС, т.е. будем иметь в виду снимок окна, которое partially blocked, но не hidden. Кроме WM_PRINT, требующего внедрения в чужой процесс, есть и способы без внедрения, и это - не только PrintWindow. (Само собой, способы не без ограничений, но об этом не сейчас). На скриншоте - черновая спец.демка PrintLayered, только что - после клика по кнопке "BitBlt /srccopy" - отскриншотившая "всё изображение с окна" калькулятора, которому временно назначен стиль WS_EX_COMPOSITED; окно калькулятора частично сдвинуто за пределы экрана, частично перекрыто окном другой проги, и согласитесь - не примитив:
kero -- волшебник, спору нет. Риспект и благодарность. Полная моя задача состоит в написании почти универсального бота для игры в русские шашки. А эта подзадача возникла вследствие того, что не во всех шашечных программах можно читать ход противника из текстового поля. Сорцы шашечного движка у меня есть и программно кликать мышкой умею. Осталось малое -- собрать всё это воедино.
Сохранить в файл очень просто тебе надо будет две структуры и одна функция. Вот эти структуры (приведу на паскале, так что не пинайте): Код (Text): tagBITMAPINFO = packed record bmiHeader: TBitmapInfoHeader; bmiColors: array[0..0] of TRGBQuad; end; Код (Text): tagBITMAPFILEHEADER = packed record bfType: Word; bfSize: DWORD; bfReserved1: Word; bfReserved2: Word; bfOffBits: DWORD; end; И функция: Код (Text): function GetDIBits(DC: HDC; Bitmap: HBitmap; StartScan, NumScans: UINT; Bits: Pointer; var BitInfo: TBitmapInfo; Usage: UINT): Integer; stdcall; external 'gdi32.dll'; Думаю в МСДНе есть описание этой функции. Потому не буду описывать, что к чему. Структура файла: BmpFileHeader BmpHeader И потом данные. Вот соорудил примерчик (Опять таки на паскале)
Благодарю за участие. Всё расписал как на пальцах. А что на паскале -- так мне без разницы, CPP, Asm, С#, Delphi -- для понимания сути это не критично. А код такой переписать на C -- легко. WriteFile только заменить, остальное -- API-шное, структуры данных -- есть соответствующие.
А если окно со скроллбарами? Можно ли получить все содержимое окна без инициации прокрутки всей области?