|
|
| Посл.отвђт | Сообщен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 |