| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Visual C++/MFC/WTL > Перерисовка в OnSize |
| Автор: maq 28.5.2006, 10:53 |
| Ребята, у меня такой вопрос: нужно чтобы при OnSize в CView не происходила перерисовка клиентской части окна или же его части. В MSDN-не покопался, но не помогло. Кто знает, как это сделать? |
| Автор: vvpC 28.5.2006, 20:20 |
| блокировать(игнорировать) WM_PAINT, када оно не нужно |
| Автор: DeadSoul 28.5.2006, 20:45 |
| Ключевое слово - Erasebackground |
| Автор: maq 28.5.2006, 23:48 | ||||
| 1. В чем разница между OnPaint и OnDraw? Так понимаю, что OnPaint вызывается при сообщении WM_PAINT, а для чего тогда OnDraw? 2.
В смысле использовать PreTranslateMessage? 3.
А можно с примерчиком? |
| Автор: Earnest 29.5.2006, 12:42 |
| OnPaint - это обработчик стандартного сообщения Windows WM_PAINT. OnDraw - в некоторых MFC-классах есть виртуальная ф-я OnDraw, которая вызывается из OnPaint. Глупости. Кто это будет определять, когда нужно и когда не нужно. 1) Чтобы на OnSize не было лишних подергиваний, нужно убрать CS_HREDRAW ии CS_VREDRAW из стиля класса окна. Т.е. зарегистрировать свой класса, а не пользоваться стандартным. CS_VREDRAW и CS_HREDRAW нужны только тогда, когда при изменении размеров окна изменяется масштаб изображения, а когда просто окрываются невидимые части - лучше убрать. 2) Иногда имеет смысл регистрировать класс без кисти (чтобы не было зарисовки на ERASEBKGND) или, что почти то же самое, перехватывать WM_ERASEBKGND и ничего не делать. Но это возможно не всегда. 3) Поищи по форуму, вопрос неоднократно обсуждался. |
| Автор: vvpC 30.5.2006, 09:39 | ||
Неужели? Я бы не был столь котегоричен. Блокировка перерисовки вовремя ресайзинга имеет смысл только при изменении размеров окна мышью, поэтому начало ресайзинга и его завершение определяются элементарно. Вот рабочий пример:
|
| Автор: Earnest 30.5.2006, 11:34 |
| Ну ладно, хорошо, не глупости, а некорректное (в данном случае) решение. Флаги, конечно, можно поставить. Но ведь того же эффекта (т.е. отказ от вывода содержимого окна в процессе растяжения) можно достичь просто отключив соответствующую опцию в Виндовс. И будет растягиваться только рамка. А уже по завершению процесса отрисуется окно. Причем так будут вести себя все приложения в системе. А уж если опция включена (показывать содержимое окна во время ресайза), то задача программы - обеспечить ее нормальную работу - т.е. без дерганий. Которые возникают в результате стирания той части окна, которая в перерисовке вовсе не нуждается. Чтобы с этим бороться, нужно иметь класс окна без CS_[V\H]REDRAW. В этом случае при ресайзе перерисоваются только новые части. |
| Автор: Earnest 30.5.2006, 11:50 |
| vvpC, вдогонку: Кстати, в твоем коде есть еще одна ошибка. Если ты уж ставишь свой обработчик WM_PAINT, то обязан поставить скобки BeginPaint()\EndPaint() (ну или создать объект CPaintDC). А ты, если стоит флаг, просто выходишь. Чем это может грозить? Ну, скажем, во время резайза таймер не будет срабатывать. В нормальном приложении возможны и другие проблемы, в этом маленьком примере не проявляющиеся. Конечно, можно поставить CDialog::OnPaint перед проверкой (все равно он практическио ничего не делает, кроме BeginPaint-EndPaint). Но в любом случае как-то неуклюже, согласись, дважды запрашивать контекст перерисовки... |
| Автор: vvpC 30.5.2006, 12:25 |
| Объясни тогда почему я "обязан" - ведь я не захватываю какие-то ресурсы и забываю их освободить... EndPaint сразу за BeginPaint (или GetDC,ReleaseDC)и больше ничего - имхо бессмыслица... И как обработка WM_TIMER связана с обработкой WM_PAINT? |
| Автор: vvpC 30.5.2006, 18:27 |
Ну тааада лаадно. А если серьезно, то когда я данный вопрос спаем++ обследовал, у меня иногда какраз такое и случалось. Временами нормально, а временами спай как пулемет: WM_PAINT, WM_PAINT. Ну я по простоте душевной не придал этому большого значения |
| Автор: maq 31.5.2006, 22:58 |
| перефразирую вопрос: в данный момент я работаю над созданием класса контрола, который позже станет ActiveX контролом (скажем, контрол А). Естественно, контрол А должен уметь менять размеры при изменении размера окна (скажем, окно B), в котором он будет находиться. Моя цель предотвратить перерисовку неизменяемой клиентской части контрола А при изменении его размера. А при изменении размера окна В происходит перерисовка (моргание) окна В, а следовательно и контрола А. Предполагается, что при Resizing-е окна В происходит Resizing контрола А. Моя задача - найти способ, при котором независимо от типа окна В при его Resizing-е не происходила перерисовка неизменяемой клиентской части контрола А. Заранее спасибо |
| Автор: Earnest 1.6.2006, 07:27 | ||
Про окно A уже все написано.
Попробуй поставить окну В стиль CLIPCHILDREN. |
| Автор: maq 13.6.2006, 06:39 |
| Окну В стиль CLIPCHILDREN поставил, окно А уже не моргает (если не нем больше ничего нет). У окна А убрал CS_VREDRAW и CS_HREDRAW и зарегистрировал. Неизменяемая клиентская часть окна А при ресайзинге окна А не перерисовывается. Но вот если происходит ресайзинг окна В, то независимо от того происходит ресайзинг окна А или нет, окно А перерисовывается! Почему? |
| Автор: maq 15.6.2006, 09:23 |
| При ресайзинге окна В оно посылает сообщения окну А WM_PAINT и WM_ERASEBKGND. Как из окна А перехватить эти сообщения исходящие именно из окна В? |
| Автор: vvpC 15.6.2006, 11:18 |
| объяви собственные сообщения и шли их окну А, а в параметры можно запокавать хендл окна B , чтоб не ошибится... |
| Автор: maq 16.6.2006, 14:08 | ||
а можно по-подробнее? Я не очень-то понял. |
| Автор: vvpC 16.6.2006, 14:56 | ||
|
| Автор: Coocky 16.6.2006, 14:59 | ||
Господи , уже два месяца наблюдаю ваш сериал.. Неужели так ТРУДНО ЗАПРЕТИТЬ перерисовк????? LockWindowUpdate() RedrawWindow() Invalidate() SetRedarw() Ну, может хватит велосипеды изобретать? |
| Автор: maq 16.6.2006, 17:06 | ||
Спасибо за совет, Coocky, но все это я уже перепробовал! |
| Автор: Coocky 16.6.2006, 17:09 |
И что -перерисовывается? А можно узнать-как ты пробывал? |
| Автор: v2v 2.4.2007, 20:13 | ||
простите за мою не образованность но как и где это делается . (в вин апи я знаю как такое сделать, а в мфс)? |
| Автор: Earnest 3.4.2007, 07:43 |
Практически так же. Никто не запрещает делать через WINAPI, только функцию оконную подставить нужно MFC-шную. Но в MFC есть удобные функции-обертки AfxRegisterClass и AfxRegisterWndClass. В частности, они проверяют, что класс не регистрируется повторно и обеспечивают удаление (де-регистрацию) класса на выходе. Эти функции удобно использовать в PreCreateWindow. Кроме того, по моему можно убрать CS_REDRAW из стиля класа прямо у окна, не регистрируя специальный класс... через SetClassLong. |
| Автор: v2v 4.4.2007, 13:33 |
| Перезарегистрировал класс. В коей мере удаление этих стилей помогло,НО! У меня на моей форм-вью есть актив-х контрол, который занимает оснвную область окна: Если размер окна меньше чем 800х600, размер актив-х контрола не менянется, но когда размер окна увеличивается больше указаного, я начинаю растягивать и контрол...вот тогда снова начинается мигание... можно от него(мигания) как то ещё избавиться.... Ps. ещё пробывал OnEraseBackground(...) { return 1; } не помогает...(не влияет на мигание (перерисовку) внутренностей актив-х контрола). |
| Автор: Earnest 4.4.2007, 16:17 |
| C актив-X контролом нужно бороться аналогично (с его окном). Раз мигает он, из парента больше не выжмешь... |
| Автор: v2v 4.4.2007, 17:03 |
| В том то и дело что всё сделал в классе актив х контрола, тоже что и в мди-окне. Не помогло... |
| Автор: Earnest 4.4.2007, 18:16 |
| Да вряд ли в самом актив-Х контроле это сделал - скорее в окне, в которое он помещается... Ты посмотри Спаем, что там за окна, и какие у них стили... Но не факт, что сможешь изменить поведение актив X - все-таки это черный ящик... Можно попробовать перенаправить его вывод в совместимый контекст... но это уже так, фантазии на тему - тут нужно предметно рыться в коде и пробовать. |
| Автор: v2v 4.4.2007, 21:36 | ||
Для меня это черный лес... а времени разбиратся не особо есть.... .... Попробую плясать по другому: Если, допустим, окно перерисовывать на ресайзе, только тогда, когда событие выполнилось, а именно отпустили левую кнопку мыши (уже перетянули форму) .... Немного не красиво, но лучше мигания.... Хм.. как мне перехватить это нажатие OnLButtonUp (..) {..} ведь нажатие происходит не непосредственно в моём классе форм-вью, где я обрабатываю OnSize() {...} ... |
| Автор: Earnest 4.4.2007, 21:55 |
| Для этого есть PreTranslateMessage на одном из родителей... Но сомневаюсь, что поможет: ты разве сам Invalidate вызываешь на ресайзе? |
| Автор: v2v 4.4.2007, 23:28 |
| Нет, но пробывал сам Invalidate вызывать ... для Active-X контрола не помогает. |
| Автор: Earnest 5.4.2007, 06:05 |
| Вот: он сам это делает, и ты вряд ли сможешь этому помешать... Можно попробовать на ресайзе родительского окна исключать из невалидного региона актив-Х контрол - до отпускания правой кнопки мыши. Где-то в вин-апи была тема про борьбу с миганием на ресайзе. Там как раз все эти манипуляции с регионами обсуждались. Может быть она есть в ссылках внизу. В зависимости от задачи, можно просто отключить в настройках Виндоус непрерывную перерисовку при ресайзе (таскать только рамку). По крайней мере, пока вин-апи не перестанет быть для тебе "темным лесом". |
| Автор: v2v 5.4.2007, 22:20 |
| цитатаЯ уже столько тем перечитал про ресайз окон и в вин апи и в мфс В моей ситуации, лучше всего помогает именно убирание вот тех двух стилей как в вин апи, так и в мфс...... но не достаточно. |