реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Обновление GUI через таймер, Visual Studio 2013 C++
nice_vladi
сообщение Dec 25 2017, 06:49
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 7-09-16
Из: Томск
Пользователь №: 93 239



Все привет!

Очередной вопрос, связанный с Visual Studio и языком C++, в частности.

На форме имеется статусбар. В нем несколько полей, которые обновляются в одном таймере. Конструкция типа:

CODE

void CMain::OnTimer(UINT nIDEvent)
{
Upd0(var0);
Upd1(var1);
Upd2(var2);
}


Где каждая функция обновления что-то вроде:

CODE

void CMain::Upd0(int var)
{
CString _str;

_str.Format(L"%d", var);

status_bar.SetIcon(1, m_ico_ena);
status_bar.SetSetText(_str, 1, NULL);
}


Т.е. обновляется текст и иконка.

При обновлении ПЕРВОГО поля (в функции Upd0) на форме это поле мерцает. При обновлении последующих полей мерцания нет. Хочется, что бы мерцания не было и в первом поле. Не могу понять, как это связано.

Использую MFC.

Спасибо.

smile3046.gif
Go to the top of the page
 
+Quote Post
alexunder
сообщение Dec 25 2017, 14:14
Сообщение #2


unexpected token
****

Группа: Свой
Сообщений: 899
Регистрация: 31-08-06
Из: Мехелен, Брюссель
Пользователь №: 19 987



Цитата(nice_vladi @ Dec 25 2017, 07:49) *
При обновлении ПЕРВОГО поля (в функции Upd0) на форме это поле мерцает. При обновлении последующих полей мерцания нет. Хочется, что бы мерцания не было и в первом поле. Не могу понять, как это связано.

Странный эффект. Если поле находится во власти класса типа CDialog, то попробуйте в конце каждой фунцкии Upd поставить UpdateData(FALSE).


--------------------
А у тебя SQUID, и значит, мы умрем.
Go to the top of the page
 
+Quote Post
nice_vladi
сообщение Dec 26 2017, 05:51
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 7-09-16
Из: Томск
Пользователь №: 93 239



Цитата(alexunder @ Dec 25 2017, 14:14) *
Странный эффект. Если поле находится во власти класса типа CDialog, то попробуйте в конце каждой фунцкии Upd поставить UpdateData(FALSE).


Спасибо за совет. Но, к сожалению, этот флаг не помог. Я пробовал и другие варианты включения/выключения обновления данных, в т.ч. и статусбара - но результата не добился.

В качестве костыля создал еще одно поле в статусбаре, шириной 1 пиксель и первым обновляю его. При этом мне очень стыдно.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Dec 27 2017, 12:28
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



У меня два дилетантских вопроса (MFC я когда-то давно так и не освоил, а сейчас, по-видимому, уже поезд ушёл :-) )
- SetSetText() - это не опечатка, так и надо?
- не лучше ли делать setIcon(), setText() только тогда, когда что-то ДЕЙСТВИТЕЛЬНО поменялось?


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
jcxz
сообщение Dec 27 2017, 12:43
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(nice_vladi @ Dec 26 2017, 07:51) *
В качестве костыля создал еще одно поле в статусбаре, шириной 1 пиксель и первым обновляю его. При этом мне очень стыдно.

Часто для убирания мерцания, достаточно запретить стирание перед рисованием. Ну и рисовать потом так, чтобы новая картинка полностью обновляла старую.
Go to the top of the page
 
+Quote Post
nice_vladi
сообщение Dec 27 2017, 14:30
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 7-09-16
Из: Томск
Пользователь №: 93 239



Цитата(esaulenka @ Dec 27 2017, 12:28) *
У меня два дилетантских вопроса (MFC я когда-то давно так и не освоил, а сейчас, по-видимому, уже поезд ушёл :-) )
- SetSetText() - это не опечатка, так и надо?
- не лучше ли делать setIcon(), setText() только тогда, когда что-то ДЕЙСТВИТЕЛЬНО поменялось?

SetSetText() - очепятка)

Отображаемые данные и так меняются примерно раз в секунду. Так что разницы нет(
И, на мой взгляд, проще со строго дискретным промежутком времени проверять флаги и по их состоянию обновлять ГУЙ.

Цитата(jcxz @ Dec 27 2017, 12:43) *
Часто для убирания мерцания, достаточно запретить стирание перед рисованием. Ну и рисовать потом так, чтобы новая картинка полностью обновляла старую.

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


Штудировал интернеты и книжки различные - все равно не могу понять, какого черта мерцает только первое обновляемое поле?! smile3046.gif
Go to the top of the page
 
+Quote Post
jcxz
сообщение Dec 27 2017, 16:09
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(nice_vladi @ Dec 27 2017, 16:30) *
100% новая картинка не полностью будет обновлять старую (разная длина выводимых сообщений). Наверное, можно добить пробелами остающееся место, но это мне совсем не нравится, лучше уж дергать одно узкое поле в начале.

Значит надо так формировать, чтобы 100%-но перекрывала старую.
Не знаю, что такое "добить пробелами остающееся место" и почему не нравится, но я не раз делал вывод строк текста через цикл TextOut() + 4шт. FillRect() от краёв текста до соответствующих границ клиентской области окна - работает нормально и быстро.
Если контрол содержит сложное изображение, а не просто текст, то можно отрисовку всю сделать на битовой плоскости в памяти, а потом - BitBlt(). Тоже без всяких стираний.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Dec 27 2017, 21:21
Сообщение #8


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Я бы добавил некую "атомарность" этой перерисовке.
Перед вызовом первого Upd0(var0); запрещаем перерисовку(перестаем обрабатывать WM_PAINT), делаем все изменения и отрисовываемся один раз.
Мне кажется что в ином случае постоянно будет что-то мерцать и подергиваться потому что ваши изменения не синхронизированы с развёрткой монитора(или точнее с внутренним механизмом DirectDraw или какая там подсистема в винде окошки рисует)...

Почитайте вот тоже https://msdn.microsoft.com/en-us/library/ms969905.aspx
Меня это наводит на мысли, что в кишках MFC
Вот это
status_bar.SetIcon(1, m_ico_ena);
status_bar.SetSetText(_str, 1, NULL);
реализовано без применения описанной техники двойной буферизации. Надо глубже копать либо применить какой-нибудь хак типа предложенного мной выше. Как это конкретно применить к MFC не знаю.

Кажется CWnd::LockWindowUpdate() очень похоже на правду.
https://msdn.microsoft.com/en-us/library/1x...ockwindowupdate

Цитата
While window updates are locked, the system keeps track of the bounding rectangle of any drawing operations to device contexts associated with a locked window. When drawing is reenabled, this bounding rectangle is invalidated in the locked window and its child windows to force an eventual WM_PAINT message to update the screen. If no drawing has occurred while the window updates were locked, no area is invalidated.


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Dec 27 2017, 21:28
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(sigmaN @ Dec 27 2017, 23:21) *
Я бы добавил некую "атомарность" этой перерисовке.
Перед вызовом первого Upd0(var0); запрещаем перерисовку(перестаем обрабатывать WM_PAINT), делаем все изменения и отрисовываемся один раз.
Мне кажется что в ином случае постоянно будет что-то мерцать и подергиваться потому что ваши изменения не синхронизированы с развёрткой монитора(или точнее с внутренним механизмом DirectDraw или какая там подсистема в винде окошки рисует)...

У вас в голове каша из разных понятий.
Обработка WM_PAINT, как и других виндовых сообщений, выполняется в одном GUI-потоке. Если WM_PAINT выбрано из очереди сообщений окна и обрабатывается (идёт отрисовка), то никакой другой обработки сообщений (данного окна) быть не может и ничего его прервать не может.
А развёртка монитора - это совсем другое. И никакая "атомарность" перерисовок бороться с ней не может. Да и развёртка монитора никак не может приводить к мерцаниям картинки. По определению. Она может приводить только к некоторым артефактам на динамических картинках.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th June 2025 - 08:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.0144 секунд с 7
ELECTRONIX ©2004-2016