· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Содержимое экрана под окном-как?

Посл.отвђт Сообщенiе


Дата: Май 12, 2003 13:22:04

Вот какая проблема имеет место быть. Создаю в своей программе окно и вывожу его на экран. При этом
ПЕРЕД ТЕМ как мое экно покажется на экране мне нужно скопировать содержимое той части экрана
которую оно закроет. Непонятно? Хорошо, тогда по буквам :)
1)Вызываем CreateWindowEx и говорим ей создать что-нибудь в стиле WS_VISIBLE+WS_POPUP.
2)Эта функция сама посылает нам сообщение WM_CREATE в котором мы копируем
интересную нам часть экрана(т.е. делаем "снимок" части экрана).
3)Затем посылается сообщение WM_PAINT где можно делать что хочешь - часть экрана уже
скопирована и никуда от нас не денется.
Здесь все проходит на отлично, вопросов нет. Но вот допустим юзер поработал с нашим окном,
открыл 2-3 новых окна других прог(а наше, соотвественно, ушло в бэкграунд) и захотел
опять вернуться к нашему окну. Что он делает - а он, к примеру, 2-3 раза давит Alt+Tab
что б вернуть наше окно на передний план. И вот тут-то проблема. Считанный в процессе
обработки WM_CREATEа буфер дисплея уже никому не нужен - дисплей-то изменился!
Значит интересующую нас часть надо считать заново. Но WM_CREATE уже больше
не вызывается, а все прочие мессаги в которых эту процедуру потенциально можно было бы
провернуть(такие как WM_ACTIVATE,WM_ACTIVATEAPP,WM_SETFOCUS,WM_SHOWWINDOW да
и в самом WM_PAINTе это можно было бы сделать), так вот все они вызываются ПОСЛЕ
того как наше окно появилось на дисплее и мы успешно делаем снимок нашего же окна,
а совсем не той части дисплея которое оно закрыло. Не помогают и ухищрения с временным
помещением нашего окна опять в бэкграунд(а потом вытаскиванием его на поверхность) или
игры с ShowWindow,...,SW_HIDE/ShowWindow,...,SW_SHOW. Тут уже в дело вступает тот механизм,
что система сначала ждет пока мы обработаем избранное нами сообщение(к примеру тот же WM_SHOWWINDOW),
потом смотрит не нужно ли ей самой его обработать(она ж не знает, может мы его в этот раз вообще обрабатывать
не будем) а уж потом(и только если это будет надо) пошлет WM_PAINT низлежащим окну/окнам
что бы они себя перерисовали и создали ту самую картинку за которой мы охотимся.
Таким образом требуется мессаг кторый бы вызывался ДО отображения нашего окна на экране
(WM_CREATE подходит идеально, но вызывается лишь однажды :( ) либо совершенно
иной механизм без привлечения системных сообщений. Никому в голову ничего не приходит?


Дата: Май 12, 2003 16:56:06

Хорошая хитрость :)
Но постойте.
Давайтека ещё раз. Собственно говоря за счёт чего вы копируете поверхность экрана?
За счёт того, что она оказывается в контексте вашего окна? Или нет? Кажется так.
То есть когда вызывается WM_PAINT разве вы не копируете ту часть экрана, которая образовалась под окном?
Я не раз наблюдал такую картину во многих прилоджениях, когда машина что-то подкачивала с свопа. Именно, на таких заторможеных окнах (то есть приложение не успевало перерисовать окно), показывалась та, часть экрана, которая уже как бы была под окном.
Судя по вашим словам при поступлении сообщения WM_PAINT ( а кстати там ещё есть NCPAINT) вы будете копировать уже не копию нужной вам части экрана а ваше окно.

Гм...

Позвольте спросить, а что собственно копируется? Если ваше окно ещё не перериосвалось? По моему вы должны как раз поймать изображение экрана.
То есть например варианты ответа:
1. Копируется фон окна?
2. ???

Например я когда-то делал простой эксперемент.
Ставил нулевую кисть и не перерисовывал окно.
Что происходило: в область окна попадало всё, то, что было сверху. То есть те окна, которые находились до этого на верхнем уровне.


Дата: Май 12, 2003 16:56:43

Интересный вопрос :)
А это одингаково работает во всех ОС?


Дата: Май 15, 2003 02:37:36

2 Smarty:
Попробуй поставить хук на клавиатуру, тогда при нажатии на Alt+Tab, ты сможешь сделать снимок экрана, а после этого передать управление системе. Т.е. твоя программа сможет обработать нажатие комбинации еще до того, как оно будет обработано системой.


Дата: Май 16, 2003 13:48:15

to Sk. Inc.: Ну вариант с захучиванием покатит наверняка. Но! Это же только для примера я сказал что
пользователь нажмет Alt+Tab. Он может еще и мышой кликнуть в таскбаре и еще чего-нибудь придумать. :)
Значит надо ставить хук фильтрующий мессаги типа активации окна и т.п. Причем такой хук должен
быть глобальным(общесистемным). А это значит отдельная DLL которая будет приаттачиваться к КАЖДОМУ
процессу в системе и фильтровать ВСЕ оконные сообщения отлавливая нужные. Думается мне, что
это не слабо подсадит производительность системы в целом. Поэтому пока мучаюсь в поисках
иного решения но, на крайняк, придется такую DLL с хуком действительно соорудить.
===
to Edmond: по поводу того где это "одинаково работает" - я могу поручиться только за XP. Там это
100% работает так, как я описал - лично ставил эксперименты. На других ОС не проверял,
могу лишь подозревать, что и там та же петрушка.
По поводу остального:

***
Позвольте спросить, а что собственно копируется?
***

Если имеется в виду что я хочу скопировать - то я хочу получить битмап(BMP-файл) участка экрана.
Вот есть такие специальные проги для снятия снимков с экрана что бы потом эти картинки в статьи
вставлять - примерно то же самое, только не весь экран, не содержимое конкретного окна, а все
что попадает в нужный мне прямоугольник. Там, к примеру, могут оказаться кусочки 5-и различных окон+
участок десктопа. И все это мне нужно как единая картинка. Да и еще - сделать такой снимок
совсем не проблема, проблема как я ее описываю - сделать его в НУЖНЫЙ момент. :)

***
Собственно говоря за счёт чего вы копируете поверхность экрана?
За счёт того, что она оказывается в контексте вашего окна?
***

А копирую я его за счет того что узнаю контекст дисплея, узнаю хэдл битмапа в этом контексте,
создаю контекст(временный) в памяти, создаю совместимый битмап в нем, копирую первый битмап во
второй, и со второго сдираю значение каждого бита. Вот так все просто. :) Контекст моего окна
здесь совершенно не причем, я могу делать эту процедуру вообще не создавая ни одного окна, а, к примеру,
просто дампить считанные значения в файл(и этот вариант, кстати, был бы проще в реализации). Но тем
не менее главное окно в моей программе есть и оно должно появляться на экране когда к нему обратится юзер.

***
То есть когда вызывается WM_PAINT разве вы не копируете ту часть экрана, которая образовалась под окном?
***

То есть Вы считаете, что WM_PAINT "автоматом" делает снимок той части экрана которую соотв. окно готовиться
закрыть? :)) :)) В примере со свопом окно сначала отрисовало не-клиентскую часть(бордюр, тайтлбар, системные
кнопки и т.п.), потом своп тормознул процесс отрисовки(в это время действительно можно смотреть "сквозь"
окно) и потом дорисовалась клиентская часть. Но общей картины это не меняет - сначала показывается
окно со своим "старым" содержимым а ПОТОМ вызывается WM_PAINT. Поэтому то когда я делаю снимок экрана в
WM_PAINTе я получаю не экран а старое содержимое своего же окна. :(

***
Судя по вашим словам при поступлении сообщения WM_PAINT ( а кстати там ещё есть NCPAINT)
вы будете копировать уже не копию нужной вам части экрана а ваше окно.
***

Именно так и происходит(см. выше), хотя за намек на NCPAINT спасибо - вот это стоит попробовать!
Если выяснится, что сначала отрисовывается бордюр(NCPAINT), потом некоторое время окно стоит
"прозрачное" и лишь потом запускается WM_PAINT то проблема будет решена а мне останется
признать, что в предыдущем абзаце я был не совсем прав. :)


Дата: Май 16, 2003 14:14:54

Smarty
to Edmond: по поводу того где это "одинаково работает" - я могу поручиться только за XP. Там это
100% работает так, как я описал - лично ставил эксперименты. На других ОС не проверял,
могу лишь подозревать, что и там та же петрушка.
По поводу остального:

=-=-=-=
ага, тогда я могу предположить, что будут проблемы с 9x
Советую проверить.

совсем не проблема, проблема как я ее описываю - сделать его в НУЖНЫЙ момент. :)

Очень интересное решение.
По моему другие програмы используют иные подходы (хуки кстати + перехват сообщений)

А копирую я его за счет того что узнаю контекст дисплея
Я так и думал...
Но тем
не менее главное окно в моей программе есть и оно должно появляться на экране когда к нему обратится юзер.

Тогда я не понял, что делает ваша программа и в чём специфика?То есть Вы считаете, что WM_PAINT "автоматом" делает снимок той части экрана которую соотв. окно готовиться

Не совсем так :)))
И это зависит от Windows версии.
Вот почему я спрашивал про версию.

Поэтому то когда я делаю снимок экрана в
WM_PAINTе я получаю не экран а старое содержимое своего же окна. :(


Да, я же сказал, это зависит от Винды..хотя за намек на NCPAINT спасибо - вот это стоит попробовать!

Не за что. Попробуйте. мне интересен результат.потом некоторое время окно стоит
"прозрачное" и лишь потом запускается WM_PAINT то проблема будет решена а


Ну вот это мне и интересно!!!


Дата: Май 16, 2003 18:05:55

Честно говоря, я не понимаю а почему надо сохранять свои собственные отрисовки? - Разве Windows не посылает WМ_PАINТ когда нужно и Ваш код должен перерисовать все как надо?


Дата: Май 16, 2003 19:21:37

Рискну дать радикальный совет:
Создайте окно неправильной формы (через регионы), которое может быть прямоугольным но с дыркой в том месте где нужно захватывать содержимое экрана. При получении WM_PAINT и WM_MOVE, конвертируйте координаты этой самой дырки из клиентских в экранные и захватывайте участок экрана через полноэкранный DC.
Результат:
Ваше окно станет плавающей рамкой (В 9x - XP должно работать).


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.060