Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: Win API


РАССЫЛКИ ПОРТАЛА RUSFAQ.RU

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / WinAPI

Выпуск № 304
от 13.09.2006, 12:35

Администратор:Калашников О.А.
В рассылке:Подписчиков: 364, Экспертов: 36
В номере:Вопросов: 1, Ответов: 3


Вопрос № 54718: Здравствуйте уважаемые знатоки WinAPI! Наверно я не очень понимаю механику окна Win, поэтому заранее прошу простить если сморожу глупость...;-) Вот написал некий визуализатор некоей внешней относительно PC информации. Чистый WinAPI ...

Вопрос № 54.718
Здравствуйте уважаемые знатоки WinAPI!

Наверно я не очень понимаю механику окна Win, поэтому заранее прошу простить если сморожу глупость...;-)

Вот написал некий визуализатор некоей внешней относительно PC информации. Чистый WinAPI (в плане визуализации и самого окна). VSC++7.1. Всё работает: циферки бегают, лампочки мигают, батончики нажимаются... Но(!)...

Технологически необходимо, чтобы окошко было максимизировано (окно - основное, или как там оно называется, НЕ диалоговое, НЕ из ресурсов, создаётся VS-шаблоном в WinMain()).
Так вот, сама проблема: при появлении на экране любого другого окна, которое не перекрывает всю область экрана и убирания оного (всё равно какого: MessageBox'а из этой же программы или другого окошка, или просто при перемешении основного окна в "Восстановленном" виде (кнопочка "восстановить" оставлена в целях отладки)), основное окно продолжает перерисовываться только в том месте, где находилось то окошко. Вся остальная область окна - игнорируется для перерисовывания. Т.е. на той части окна, которая была видна из-под другого окна изображение становится статичным, застывшим. Лечится либо кнопочкой "Восстановить", либо <Ctrl+Tab> на другую задачу, полностью перекрываюшую окном Desktop.
Как заставить окно продолжать перерисовываться _полностью_?

И вот, заодно ещё вопросик: перерисовывать некоторые графические объекты в окне нужно не только при WM_PAINT, но и по другим событиям, например WM_TIMER и при нажатии мышиных кнопок.
Так вот, если делаю отдельную процедуру рисования сразу всего (включающую пару BeginPaint/EndPaint или если упомянутую пару делаю глобальной, в WM_PAINT (со станической ps и hdc) - не важно), оконо перестаёт перерисовываться совсем (рисуется первый кадр статики). Приходится делать так:
в WM_PAINT делаю BeginPaint с глобальными переменными, рисую статику окна, а EndPaint делаю только при WM_DESTROY. В остальных местах вызываю самоперерисовывающиеся объекты с соответствующим hdc.
Почему не рисуется ничего когда (теоритически) код тот же самый, но оформлен в процедуру?

Заранее спасибо за ответы...
Отправлен: 08.09.2006, 12:15
Вопрос задал: Sergijj (статус: 5-ый класс)
Всего ответов: 3
Мини-форум вопроса >>> (сообщений: 3)

Отвечает: dentist
Здравствуйте, Sergijj!
не буду утверждать, что я скажу что-то на 100% приемлимое но...
я бы оставил в обработке сообщения WM_PAINT всё по старому т.е.
BeginPaint/EndPaint
и вызывал бы UpdateWindow().

но боюсь у вас проблема совсем не в этом.
если смотреть на код то мне в данном случае интересно былобы в первую очередь глянуть на цикл обработки сообщений.
у меня он обычно выглядит так:
for(;;)
{
if (GetMessage(...))
{
TranslateMessage(...)
DispatchMessage(...)
}
}
и никогда подобных вашей проблем не возникало.
с другой стороны в функции обработчике сообщений могли касяки выскачить.
жаль что кода вы не привели.
а так, на скорую руку, чтоб не вдаваться в подробности, в том же цикле кидать окну сообщение типа WM_PAINT.
примерно так:
for(;;)
{
if (GetMessage(...))
{
TranslateMessage(...)
DispatchMessage(...)
}
SendMessage(..., WM_PAINT....)
}

---------
"Software is like sex, it's better then it's free" (c) Linus Torvalds
Ответ отправил: dentist (статус: 3-ий класс)
Ответ отправлен: 08.09.2006, 15:37

Отвечает: Mystic
Здравствуйте, Sergijj!
Предлагаю попробовать при каждом событии WM_PAINT в конце добавлять функцию InvalidateRect(hWnd, Rect, true);
Rect - прямоугольник, где находится ваше окно (а можно, наверное, сделать и весь экран, не пробовал).
Не знаю, поможет ли, но, по идее, должно.
Ответ отправил: Mystic (статус: 1-ый класс)
Ответ отправлен: 08.09.2006, 19:42

Отвечает: estiGi
Здравствуйте, Sergijj!
дело в том, что получая контекст для рисования с помощью BeginPaint/EndPaint, вы получаеете только ту часть, которая, как считает система, в данный момент должба быть отрисована. Чтобы получить весь контекст, всего окна, и применить нарисованное ко всему окну, делайте так:

case WM_PAINT:
{
HDC hDc = GetDC (hWnd);
PaintWindow (hDc); // рисуем
ReleaseDC (hDc);
}
break;

Если рисование сложное, объемное etc, лучше рисовать на созданном в памяти контексте, а в WM_PAINT просто копировать - будет намного быстрее. Рисовать можно в отдельном потоке - если объемные работы, а если статическая или малоизменяемая картинка, то вообще один раз просто отрисовать в памяти и просто уже копировать готовый контекст

вызываеть перересовку своего ркна лучше всего посылкой себе же сообщения:
SendMessage (m_hWnd, WM_PAINT, 0, 0);
Ответ отправил: estiGi (статус: Студент)
Ответ отправлен: 09.09.2006, 23:08


Отправить вопрос экспертам этой рассылки

Приложение (если необходимо):

* Код программы, выдержки из закона и т.п. дополнение к вопросу.
Эта информация будет отображена в аналогичном окне как есть.

Обратите внимание!
Вопрос будет отправлен всем экспертам данной рассылки!

Для того, чтобы отправить вопрос выбранным экспертам этой рассылки или
экспертам другой рассылки портала RusFAQ.ru, зайдите непосредственно на RusFAQ.ru.


Форма НЕ работает в почтовых программах The BAT! и MS Outlook (кроме версии 2003+)!
Чтобы отправить вопрос, откройте это письмо в браузере или зайдите на сайт RusFAQ.ru.


© 2001-2006, Портал RusFAQ.ru, Россия, Москва.
Идея, дизайн, программирование: Калашников О.А.
Email: adm@rusfaq.ru, Тел.: +7 (926) 535-23-31
Авторские права | Реклама на портале
Версия системы: 4.36 от 06.09.2006
Яндекс Rambler's Top100

В избранное