Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Опять проблемы перерисовки диалога (в продолжении темы)  (Прочитано 26134 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Tuborg
Команда клуба

ee
Offline Offline

« : 18-07-2007 09:34 » 

Проект тот же, диалог, на нём сверрху рисуется диаграмма. Проблемв с отрисовкой диаграммы была решена в https://forum.shelek.ru/index.php/topic,12000.0.html  Но теперь проявилась другая проблема (на тот момент не обратил на неё внимания). Диаграмма то отрисовывается... а вот на диалоге кроме Rectangle с диаграмой есть ещё и другие контролы.... они не перерисовываются.... вернее перерисовываются если я минимизирую окно... но не перерисовываются вместе с диаграммой. Почему так?

Код:
void CWin_CCDlg::OnPaint()
{
   CDC     CMemDC1, CMemDC2, CMemDC3;
   CBitmap pBitmap1, pBitmap2, pBitmap3, *pOldBitmap;   
   
   if (IsIconic())   {... }
   else
   {
     
      CRect FrameRect;
      CWnd *pWnd1=this->GetDlgItem(IDC_GRAPH_FRAME1); // Прямоугольник1 типа Rectangle
      (Код для прямоугольника 2 и 3 удаляю так как всё также)
     
      if(graphComplete){ // Флаг который выставляется процедурой чтения данных из файла
                                                // после того как порция данных была преобразована в график во
                                                // внутренних структурах класса отвечающих за график
 
         CPaintDC dc(this);

         pWnd1->GetWindowRect(FrameRect);// Привожу координаты прямоугольника
         this->ScreenToClient(FrameRect);       // к координатам окна

         CMemDC1.CreateCompatibleDC(&dc); // Создаю MemDC для способа быстрой перерисовки
                                                                                 // Буду рисовать на MemDC а потом поточечно копировать на DC прямоугольника 1

        if (CMemDC1) {
          //Делаю на DC битмап для рисования, а точнее чтоб потом проще было на реальный
                        //DC копировать
          pBitmap1.CreateCompatibleBitmap(&dc, FrameRect.Width()-1, FrameRect.Height()-1);
          pOldBitmap = (CBitmap*)CMemDC1.SelectObject(pBitmap1);
         
         
           ch_Graph->DrawGraph(&CMemDC1, FrameRect.Width(), FrameRect.Height(),1,ch_Graph->GetSeriesQuantity()+1);  // Вызов процедуры вывода графика на указанный DC
         
          // копируем биты из памяти на DC прямоугольника
          dc.BitBlt(0, 0,FrameRect.Width()-2, FrameRect.Height()-2, &CMemDC1, 0, 0, SRCCOPY);
          // возвращаем старый bitmap
         CMemDC1.SelectObject(&pOldBitmap);
          // освобождаем контекст
         DeleteDC(CMemDC1);
        }
      }   

   }
}

Умом понимаю... что в OnPaint'е я в принципе и не прошу перерисовать контролы.... А как об этом "попросить"?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 18-07-2007 09:50 » 

помести
CPaintDC dc(this);

сразу после

else
{
Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #2 : 18-07-2007 09:57 » 

Я вынес его вообще в самое начало (перед if) не помогает. Он и занимается отрисовкой всего остального?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 18-07-2007 10:03 » 

Tuborg, поставь там, где я показал )  Там и ТОЛЬКО ТАМ , больше нигде!

это создаётся контекст окна. Альтернатива вызову OnPaint() родительского класса
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 18-07-2007 10:04 » 

для теста ещё заремарь всё остальное в else после CPaintDC dc(this);
Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #5 : 18-07-2007 10:26 » 

поставил после else сразу, всё остальное закомментил. Результат тот же.... если двигаю часть окна за экран и возвращаю обратно контролы исчезают
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 18-07-2007 10:31 » 

значит дело в другом...

ну попробуй ещё так для интереса
Код:
void CWin_CCDlg::OnPaint()
{
   CPaintDC dc(this);
}

и, в конце концов, вот так
Код:
void CWin_CCDlg::OnPaint()
{
   CDialog::OnPaint();
}

« Последнее редактирование: 18-07-2007 10:32 от Алексей1153++ » Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #7 : 18-07-2007 10:56 » 

Результат тот же... Тут мои мозги проснулись и кое что откопали... не перерисовывается только контролы Picture Control  и только в тот момент когда я запускаю PLAY и отдельный поток начинает этому диалогу говорить Invalidate(0) если комментирую Invalidate то всё ок. Invalidate (1) после перерисовки этих контролов все заливает серым цветом (под цвет формы и их не видно становится).... Всё вернулось к Invalidate как и в прошлый раз =) что он такое делает? Я его неправильно использую? Я заполняю массив данных какими-то значениями потом делаю Invalidate, затем внутри OnPaint выкидываю эти значения в контекст устройства.... если расскоментить всё в OnPaint то графики нормально рисуются и перерисовываются... а вот PictureControl на каждый Invalidate заливаются серым цветом.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 18-07-2007 11:29 » 

Tuborg, Invalidate лишь помечает (обрати внимание!) окно как инвалидное, то есть оно будет перерисовано при очередном попадании сообщения WM_PAINT из очереди сообщений в оконную процедуру. Не факт, что сообщение будет в очереди! Его надо туда положить. И не факт, что если мы его туда и положим, сообщение скоро дойдёт до оконной процедуры, если к окну идёт интенсивный поток сообщений.  Поютому, раз в , скажем, 100мс вызываем для окна UpdateWindow() , что приводит к немедленной отправке WM_PAINT непосредственно в оконную процедуру. Сильно часто UpdateWindow() вызывать не нужно - будут тормоза. По идее - чтобы было приятно глазу, не чаще. Но и не реже Улыбаюсь

и ещё опять повторю,что тебе ранее писал
Invalidate(0) - помечает окно как инвалидное
Invalidate(1) - помечает окно как инвалидное + стирает
Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #9 : 18-07-2007 12:09 » 

А как раз в 100 mc вызывать? Сделать EventHandler для Timer'a на 100мс?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 18-07-2007 13:06 » 

Tuborg, если вычисления в цикле, то можно воспользоваться ::GetTickCount

Код:
DWORD dwdLast=0;
DWORD dwdCurr=0;
DWORD dwdDiff=100;

for(;;)
{

//смотрим разницу
dwdCurr=::GetTickCount();
if(dwdCurr-dwdLast>dwdDiff)
{
dwdLast=dwdCurr;

//выполняем UpdateWindow нужного окна
}

//тут код твоих вычислений
//...
}
« Последнее редактирование: 18-07-2007 13:38 от Алексей1153++ » Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #11 : 18-07-2007 13:35 » 

О, спасибо! Я думаю этот код в отдельный поток запихну
Записан
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #12 : 18-07-2007 13:50 » 

Результат не очень впечатлил. Прилагаю снимок экрана. UpdateWindow по прежнему не лучшее решение =) На снимке экрана видно как прямоугольники за диаграмами прорисовались на половину.... что самое интересное эффект происходит не так уж часто.... это если я возьму окно и начинаю его быстро-быстро перемещать по экрану... Переключившись на другую вкладку и вернувшись обратно - прямоугольники прорисуются.... если водить медленно, такого не происходит =(

* GUI.JPG (58.28 Кб - загружено 1075 раз.)
Записан
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #13 : 18-07-2007 13:59 » 

Добавил на диалог кнопку, по нажатии на которую происходит this->UpdateWindow(). Добился глюка в прорисовке и нажал.... Прямоугольник не восстановился, глюк не исчез =(
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 18-07-2007 15:30 » 

Tuborg, если пишешь в VC6 , скинь проект.  Похоже ты фон не дорисовываешь, что ли...
Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #15 : 19-07-2007 09:02 » 

К сожалению пишу в Visual Studio 2005
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 19-07-2007 09:25 » 

тогда скинь файлы своего контрола
Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #17 : 19-07-2007 09:55 » 

Обращение к контролу в OnPaint происходит так:

Код:

Graph *ch_graph;
...

// рисуем все что требуется

pBitmap1.CreateCompatibleBitmap(&dc, FrameRect.Width(), FrameRect.Height());
pOldBitmap = (CBitmap*)CMemDC1.SelectObject(pBitmap1);


 ch_Graph->DrawGraph(&CMemDC1, FrameRect.Width(), FrameRect.Height(),1,ch_Graph->GetSeriesQuantity()+1);
 
// копируем биты
  dc.BitBlt(FrameRect.left+2, FrameRect.top+2,FrameRect.Width()-4, FrameRect.Height()-4, &CMemDC1, 0, 0, SRCCOPY);
// возвращаем старый bitmap
CMemDC1.SelectObject(&pOldBitmap);
// освобождаем контекст
DeleteDC(CMemDC1);

Я тут начал уже эксперементировать с границами... потому что думал что что то затираю при  рисовании... оказалось не так... =(

* graph.rar (12.31 Кб - загружено 982 раз.)
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 19-07-2007 10:56 » 

>>pBitmap1.CreateCompatibleBitmap(&dc, FrameRect.Width(), FrameRect.Height());

>>dc.BitBlt(FrameRect.left+2, FrameRect.top+2,FrameRect.Width()-4, FrameRect.Height()-4, &CMemDC1, 0, 0, SRCCOPY);

(sorry za translit - gluk , russkaja raskladka ne vrubaetsa....)

eta ramka v 2 pixela - ona zhe u tebja ne inicializirovana, vot i polu4aetsja tak. Nuzhno tozhe zakrasit` eto
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #19 : 19-07-2007 11:37 » 

Tuborg, выложи проект или кинь на мыло - у меня все версии студии есть.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #20 : 19-07-2007 11:56 » 

Алексей1153++, я её закрашиваю и закрашивается рамка... белым цветом, то же не есть гуд =( я и делал отступ как раз для того, чтобы как мне казалось не накрывать рамку =) я убрал.... результат не очень
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 19-07-2007 12:12 » 

Tuborg, закрась рамку цветом таким :

RGB color = ::GetSysColor(COLOR_3DFACE);

(это настроенный в системе цвет для фона диалога, обычно серый)
« Последнее редактирование: 19-07-2007 12:14 от Алексей1153++ » Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #22 : 19-07-2007 16:55 » 

Джон, я отправил тебе проект на почту. Алексей1153++,  проблема то не в фоне заливки.... а был у меня Picture Control... утопленный в диалог (с рамочкой и прочей ерундой...) рисую поверх этого Picture Control свой график, а он иногда... стирает эту симпатичную рамочку.... иногда не стирает.... вопрос не в цвете...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 20-07-2007 03:31 » 

Tuborg, попробуй поймать сообщение WM_NCPAINT (добавь визардом обработчик и там нарисуй рамку)

или вообще убери рамку, а нарисуй её сам
Записан

Tuborg
Команда клуба

ee
Offline Offline

« Ответ #24 : 20-07-2007 11:19 » 

А как рамку нарисовать? Это какие-то боксы определённого цвета? Выход конечно хороший... но хотелось бы вс таки понять что за глюк происходит. А чем сообщение WM_NCPAINT отличается от WM_PAINT ?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 20-07-2007 11:41 » 

Цитата
The WM_NCPAINT message is sent to a window when its frame must be painted.
LRESULT CALLBACK WindowProc(
  HWND hwnd,       // handle to window
  UINT uMsg,       // WM_NCPAINT
  WPARAM wParam,   // handle to update region (HRGN)
  LPARAM lParam    // not used
);

wParam - Handle to the update region of the window. The update region is clipped to the window frame. When wParam is 1, the entire window frame needs to be updated.

lParam -This parameter is not used.


но как-то я склоняюсь всё же к нарисованию своей рамки в OnPaint() Улыбаюсь

для рамки можно воспользоваться
CDC::Draw3dRect( )

или просто отрисовать при помощи 4 вызовов
CDC::FillSolidRect()

зы. Если честно - надо ждать Джона, он посоветует, что истинно правильно Улыбаюсь
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #26 : 20-07-2007 13:53 » 

Так... пытаюсь разобраться с проектом. Я конечно не ожидал, что получу ВСЁ. На будущее, Tuborg, если можно - только пример с неработающей частью (например только график и только одну кнопку). И если можно, то либо русский в юникоде, либо аглицкий (пусть хоть с ошибками). Русский в ANSI  у меня отображается закорючками.

Пока наблюдаю след эффект (загрузил данные из файла imit_pila.scd):

сначала всё нормально - вижу и график и кнопки, нажимаю "проигрывать" всё тоже в порядке. Сразу после нажатия на "стоп" пропадают всё контролы на этой страничке. Последующее "воспроизведение" и изменение размеров окна не помогают. Они  появляются только если переключиться на другую страничку, а потом обратно.

Те это и является проблемой? Или я что-то просмотрел?


зы так замечания по коду:

 как ты ф-ции обработки событий вставляешь?

ON_BN_CLICKED(ID_PAUSEREPLAY, &CPageControl::OnBnClickedPause)

можешь просто писать без &CPageControl::

ON_BN_CLICKED(ID_PAUSEREPLAY, OnBnClickedPause)

в С++ имя функции автоматически является указателем, а принадлежность указывается в BEGIN_MESSAGE_MAP(CPageControl, CDialog)

Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #27 : 20-07-2007 15:10 » 

Ну в принципе я так сразу и подумал. После остановки ни одно из условий в OnPaint у тебя не выполняется:

if(graphComplete)

if (dis_graphComplete)

if (measure_graphComplete)

Те НИЧЕГО НЕ ПРОИСХОДИТ в OnPaint.

Ну ессно почему так происходит я тебе не могу сказать. Ты должен проверить эти переменные. Потом будем дальше посмотреть. А ну и ещё ты намутил в обработке нажатия на стоп с Update/Invalidate. Не надо их там столько.

Вобще-то так не делается. Я конечно не знаю почему ты сделал именно так. Теория простая:

1. Если ты делаешь своё контрол, наследуя его от CWnd, то и вся отрисовка происходит в OnPaint этого контролла. В диалоге нет ничего, кроме передачи размеров при OnSize и внешнего управления (Вкл/Выкл). Ну типа стандартных контроллов.
Ведь нет у тебя в OnPaint диалога ни кнопок, ни каких других элементов, а ведь они отрисовываются. Самостоятельно.

2. Если твой контрол не наследован от CWnd, а использует DC родителя, то тогда он отрисовывается в OnPaint родителя. Обычно у него есть своя ф-я в которую родитель передаёт указатель на свой DC, чтобы не загромождать код родителя.

Всё. А у тебя? И CPageControl хранит указатель на диалог, являясь в свою очередь его ребёнком (если это необходимо - есть ф-я GetParent), и вызывает ф-ции работы с графиком в нём, хотя логичней предположить, что он сам должен быть родителем графика. Ну и тд. Плюс ко всему оформление кода... Читать и разбираться очень трудно. Посмотри для примера оформление кода С++ MFC  в MSDN, codeguru.com codeproject.com.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #28 : 20-07-2007 15:13 » 

Да самое главное - начни с бумаги. Нарисуй сначала модель программы. Что где находится и от чего зависит. Структуру классов. Если точно ещё не значешь какие именно это должны быть объекты - ничего страшного. Называй как хочешь, главное что они стоят на нужном месте. Потом по такой шпаргалке самому легче будет разбираться.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #29 : 20-07-2007 19:16 » 

Спасибо за проведённые исследования. Извиняюсь за бардак в структуре классов... но это я перелажу на прогу с несколькими табами.... раньше была прога с одним диалогом и ничего мудрённого в ней не было... а щас....  =)   
  Да Юникод я не очень люблю, так как стандартом он и не стал, увы.... на будущее для себя учту - буду писать в английском ANSI.

Цитата

сначала всё нормально - вижу и график и кнопки, нажимаю "проигрывать" всё тоже в порядке. Сразу после нажатия на "стоп" пропадают всё контролы на этой страничке. Последующее "воспроизведение" и изменение размеров окна не помогают. Они  появляются только если переключиться на другую страничку, а потом обратно.

Те это и является проблемой? Или я что-то просмотрел?

Да именно это проблемой и является.... есть и ещё одна.... если диалог потаскать мышкой... то исчезает PictureControl на которых рисуется график.... но эта одна и та же проблема... 
просто вылазит поразному =)

Цитата
Ну в принципе я так сразу и подумал. После остановки ни одно из условий в OnPaint у тебя не выполняется:

if(graphComplete)

if (dis_graphComplete)

if (measure_graphComplete)

Те НИЧЕГО НЕ ПРОИСХОДИТ в OnPaint.

Не рисуется график... я бы с этим смирился... но почему беда с Picture Control происходит? Ведь я как понимаю не должен отвечать за прорисовку Picture Control?
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines