DefDlgProc(m_hWnd, uMsg, wParam, lParam) я убрал, поскольку происходит вызов моей OnPaint(), зацикливаается пока не падает с переполнением. DefDlgProc() — нет такой, без параметров, поэтому убрал совсем.
В итоге все по — прежнему. Мне кажется где — то запарка с собощениями, кто — то скорее всего тоже получает WM_PAINT и перерисовывает мое окно после меня.
Доброе время суток всем.
Суть дела вот в чем: есть CMainFrame, в нем CSplitterWindow, в нем CDialogImpl, у этого диалога есть CTabCtrl с 3 вкладками (в которых я помещаю, в зависимости от выбранной вкладки, динамически созданные диалоги CDialogImpl). Так вот на одной вкладке (там два баттона и два статика) я сам рисую прямоугольники с помощью SetPixel(...). Проблема в том, что когда сварачиваешь окно, а потом разворачиваешь, нарисованные мною прямоугольники исчезают, в чем трабла??? У этого диалога я определил OnPaint:
Во-первых, в обработчике OnPaint нужно использовать BeginPaint, а не GetDC
Во-вторых, нельзя вызывать ::DefWindowProc, нужно вызывать член класса DefWindowProc, можешь даже без параметра
Но в обработчике WM_PAINT вообще лучше не вызывать эту функцию (хотя может понадобится для диалогов, но в таком случае ::DefWindowProc тебе точно не подойдет, так как в диалоге другая дефолтная функция)
В-третьих, что за стиль программирования объявлять локальную переменную с префиксом m_
В-четвертых, где код drawColRect()
D>[ccode] D>LRESULT CColourSet::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) D>{ D> CBrush br; D> RECT rcRect; D> CDC m_DC;
D> LRESULT res = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
D> drawColRect(); // моя функция отрисовки прямоугольника
D> m_ClrLine.GetClientRect(&rcRect); D> m_DC.m_hDC = m_ClrLine.GetDC(); D> br.CreateSolidBrush(line); D> m_DC.FillRect(&rcRect, br.m_hBrush); D> m_ClrLine.ReleaseDC(m_DC.m_hDC); D> m_DC.m_hDC = NULL;
D> br.DeleteObject();
D> m_ClrPit.GetClientRect(&rcRect); D> m_DC.m_hDC = m_ClrPit.GetDC(); D> br.CreateSolidBrush(pit); D> m_DC.FillRect(&rcRect, br.m_hBrush); D> m_ClrPit.ReleaseDC(m_DC.m_hDC); D> m_DC.m_hDC = NULL;
D> return 1; D>}
Здравствуйте, SaloS, Вы писали:
SS>Здравствуйте, Darked, Вы писали:
SS>Во-первых, в обработчике OnPaint нужно использовать BeginPaint, а не GetDC
Почему же именно только BeginPaint, что — то не видел я в WTL-их исходниках вообще BeginPaint, если честно.
SS>Во-вторых, нельзя вызывать ::DefWindowProc, нужно вызывать член класса DefWindowProc, можешь даже без параметра
Посмтрел я член класса DefWindowProc, это же вроде вообще пустышка, которая только возвращает False.
SS>Но в обработчике WM_PAINT вообще лучше не вызывать эту функцию (хотя может понадобится для диалогов, но в таком случае ::DefWindowProc тебе точно не подойдет, так как в диалоге другая дефолтная функция) SS>В-третьих, что за стиль программирования объявлять локальную переменную с префиксом m_
А в чем проблема?
SS>В-четвертых, где код drawColRect()
Вот код:
void CColourSet::drawColRect()
{
RECT rcClient;
int xBegin, yBegin;
int colRGB;
CDC m_CDC;
// вывод прямоугольника для выбора цвета
/*******************************************************************/
GetClientRect(&rcClient);
xBegin = rcClient.left + 70;
yBegin = rcClient.top + 50;
m_CDC.m_hDC = GetDC();
ATLASSERT(m_CDC.m_hDC);
if(m_CDC.m_hDC)
{
for(int i = 0; i < 140; i++)
{
for(int j = 0; j < 100; j++)
{
colRGB = colors(i, j, 140, 100); // функция возвращает значение цвета RGB
m_CDC.SetPixel(xBegin + i, yBegin + j, (COLORREF)colRGB);
}
}
}
ReleaseDC(m_CDC.m_hDC);
/********************************************************************/
}
Per aspera ad astra
Re[3]: Проблемы с перерисовкой, хотя OnPaint() есть
Здравствуйте, Darked, Вы писали:
D>Здравствуйте, SaloS, Вы писали:
SS>>Здравствуйте, Darked, Вы писали:
SS>>Во-первых, в обработчике OnPaint нужно использовать BeginPaint, а не GetDC D> Почему же именно только BeginPaint, что — то не видел я в WTL-их исходниках вообще BeginPaint, если честно.
По этому поводу почитай MSDN. Там черным (или серым) по белому написано, что в обработчике WM_PAINT для получения контекста устройства нужно вызывать BeginPaint. То что ты видел ничего не значит, и вместо того чтобы спорить просто проверил бы
SS>>Во-вторых, нельзя вызывать ::DefWindowProc, нужно вызывать член класса DefWindowProc, можешь даже без параметра D> Посмтрел я член класса DefWindowProc, это же вроде вообще пустышка, которая только возвращает False.
Не совсем пустышка, она вызывает стандартную функцию обработки, а это может быть очень важно для сабклассированных контролов. Для диалога, чтоб ты знал стандартная функция DefDlgProc, а не DefWindowProc.
SS>>Но в обработчике WM_PAINT вообще лучше не вызывать эту функцию (хотя может понадобится для диалогов, но в таком случае ::DefWindowProc тебе точно не подойдет, так как в диалоге другая дефолтная функция) SS>>В-третьих, что за стиль программирования объявлять локальную переменную с префиксом m_ D> А в чем проблема?
префикс m_ это обозначение переменной класса. Для читабильности кода нужно соблюдать хоть какую натацию (но желательно одну и только одну, а не как у тебя).
SS>>В-четвертых, где код drawColRect() D> Вот код:
D>
D>void CColourSet::drawColRect()
D>{
D> RECT rcClient;
D> int xBegin, yBegin;
D> int colRGB;
D> CDC m_CDC;
В данном случае тебе нужно использовать СDCHandle, так как в деструкторе будет попытка удалить DC, который ты не создавал, а получал. Последствия этого я тебе не могу описать.
SS>>>В-четвертых, где код drawColRect() D>> Вот код:
D>>
D>>void CColourSet::drawColRect()
D>>{
D>> RECT rcClient;
D>> int xBegin, yBegin;
D>> int colRGB;
D>> CDC m_CDC;
SS>
SS>В данном случае тебе нужно использовать СDCHandle, так как в деструкторе будет попытка удалить DC, который ты не создавал, а получал. Последствия этого я тебе не могу описать. SS>
Согласен
BHH>Здравствуйте, SaloS, Вы писали:
SS>>Если будешь использовать BeginPaint, то нужно для завершения использовать EndPaint
BHH>CPaintDC решит все проблемы
Здравствуйте, Darked, Вы писали:
D>Здравствуйте, SaloS, Вы писали:
SS>>Здравствуйте, Darked, Вы писали: SS>>А все остальное в OnPaint, также переделал?
D> Ну в конечном варианте OnPaint() теперь выглядит так:
D>
D> В итоге все по — прежнему. Мне кажется где — то запарка с собощениями, кто — то скорее всего тоже получает WM_PAINT и перерисовывает мое окно после меня.
Ты там что-то писал про WM_ERASEBKND, может убери обработчик на эту месагу, и кстати покажи какие сообщения ты обрабатываешь, а еще лучше запости исходники (желательно которые можно скомпилить и запустить)
Здравствуйте, SaloS, Вы писали:
SS>Здравствуйте, Darked, Вы писали:
SS>Ты там что-то писал про WM_ERASEBKND, может убери обработчик на эту месагу, и кстати покажи какие сообщения ты обрабатываешь, а еще лучше запости исходники (желательно которые можно скомпилить и запустить)
Не, WM_ERASEBKND — просто убирает флики. исходникне могу запостить, я использую несколько чужих dll, без которых не запустится, да и я использую несколько изображений в особом формате, которые тоже выслать не могу, секретность
Я проверил, такая фигня происходит на любой вкладке от CTabCtrl. Если я рисую на CDialogImpl, на котором находится CTabCtrl, то все ок. Где — то тут с сообщениями лажа, или хз.
Per aspera ad astra
Re[11]: Проблемы с перерисовкой, хотя OnPaint() есть
D> Не, WM_ERASEBKND — просто убирает флики.
Вообще WM_ERASEBKND не убирает флики, оно рисует фон. То есть, если ты хочешь чтобы окно стало прозрачным, просто при обработке этого сообщения ничего не делай, вот и все. А для уборки фликов делают немного по-другому. Всю перерисовку окна заключают в обработчик WM_ERASEBKND, причем сначала рисуют в памяти, а потом блитят в HDC который тебе приходит. вот.
D> Я проверил, такая фигня происходит на любой вкладке от CTabCtrl. Если я рисую на CDialogImpl, на котором находится CTabCtrl, то все ок. Где — то тут с сообщениями лажа, или хз.
А парентом для вкладки является CTabCtrl? Если да, то проверь, чтобы у таб контрола не менялись размеры, и при минимайзе область, где ты рисуешь не была невидимой. Потому, что если ты рисуешь на невидимой области, то то что ты нарисуешь тоже будет невидимым
D>> Не, WM_ERASEBKND — просто убирает флики. SS>Вообще WM_ERASEBKND не убирает флики, оно рисует фон. То есть, если ты хочешь чтобы окно стало прозрачным, просто при обработке этого сообщения ничего не делай, вот и все. А для уборки фликов делают немного по-другому. Всю перерисовку окна заключают в обработчик WM_ERASEBKND, причем сначала рисуют в памяти, а потом блитят в HDC который тебе приходит. вот.
D>> Я проверил, такая фигня происходит на любой вкладке от CTabCtrl. Если я рисую на CDialogImpl, на котором находится CTabCtrl, то все ок. Где — то тут с сообщениями лажа, или хз. SS>А парентом для вкладки является CTabCtrl? Если да, то проверь, чтобы у таб контрола не менялись размеры, и при минимайзе область, где ты рисуешь не была невидимой. Потому, что если ты рисуешь на невидимой области, то то что ты нарисуешь тоже будет невидимым
В обработчике WM_ERASEBKND у меня стоит только return 1, что убрало перерисовку фона, а соотвественно и флики (по — крайней мере в данном случае).
Да, вкладки у меня на CTabCTrl. Чего — то я не понял про минимайз, объясни пжалуста по-подробнее.
Здравствуйте, Darked, Вы писали:
D>Здравствуйте, SaloS, Вы писали:
D> В обработчике WM_ERASEBKND у меня стоит только return 1, что убрало перерисовку фона, а соотвественно и флики (по — крайней мере в данном случае).
В этом случае лучше использовать стили WS_CLIPCHILDREN | WS_CLIPSIBLINGS. С помощью их можно запретить перерисовку окна по детьми, что должно помочь (в твоем случае, но не всегда)
D>
D>// функция создания вклодок
D>bool Cw32View::createTabs(void)
D>{
D> CString str;
D> RECT rec;
D> CWindow tab = CWindow(GetDlgItem(IDC_TAB_TYPE));
D>// tab.ModifyStyle(0,WS_EX_CONTROLPARENT);
Если я правильно понял по коду, ты добавляешь только 2 вкладки, а здесь ты проверяешь 3
D> switch(cur_pos)
D> {
D> case 0: // активна вкладка с интегральным диалогом
Invalidate в OnPaint, оригинально-с . Вообще так не делают. Если что изменилось, то нужно перерисовывать то что изменилось, а не в перерисовке окна вызывать перерисовку child'а. Если тебе нужно перерисовать child, то перерисовывай только его.
Следующая строчка ненужна, так как установка окна из невидимого состояния в видимое автоматически вызывает перерисовку, и именно из-за этого у тебя и были флики !!!
D> Invalidate(FALSE);
D> return 0;
D>}
D>
Что касается невидимости, я просто думал, что ты обрабатываешь WM_SIZE не проверяя minimize окно или нет, и запоминаешь размер окна, которое было минимизировано, соотвественно там были неправильные координаты.
SS>Если эта вкладка таба, то почему она создается не на CTabCtrl, а на родительском окне(Cw32View)
Тут я понял косяк, сейчас сделал вот так:
RECT rc ;
m_TabType.GetWindowRect(&rc) ;
m_TabType.AdjustRect(FALSE, &rc);
ScreenToClient(&rc) ;
m_Integral = new CIntegral(pParent);
m_Integral->Create(m_TabType.m_hWnd, rc);
m_Integral->ShowWindow(SW_SHOWNORMAL) ;
Но почему — то никак не могу заставить их появлятся в начале вкладки, диалог вставляется в нижнем углу, и естесвенно весь не влазит. Сейчас пытаюсь победить. Интересно, что как бы я не получал rc, какими бы функциями, даже если вообще не получаю, появляются диалоги все равно в нижнем углу.
SS>
SS>Зачем делать одно и тоже при различных значениях. если тебе нужно сделать подобное можно было бы написать SS>case 0: SS>case 1: SS>case 2: SS>Ля-ля-ля три рубля SS>
на счет того что у тебя закрываются вкладки
когда ты получаешь GetClientRect то левый верхний угол будет (0,0) (ЭТО ОТНОСИТЕЛЬНО КЛИЕНТСКОЙ ЧАСТИ ОКНА)
а в Create нужно вставить координаты относительно реального 0,0 положения окна
суть следующая
после этого пульни это Create
(не уверен за минусы и плюсы в параметрах DeflateRect поиграйся посмотри что там получается. они нужна потому как к этому времени в rect верхний левый угол будет отрицательный и мы сдвигаем координаты для диалога на разницу между верхним углом клиентской области и верхним углом таба )
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[16]: Проблемы с перерисовкой, хотя OnPaint() есть
Здравствуйте, BuHHunyx, Вы писали:
BHH>Здравствуйте, DimpLe, Вы писали:
DL>>на счет того что у тебя закрываются вкладки
BHH>По моему красивше:
BHH>RECT rc; BHH>GetClientRect(&rc); BHH>tab.AdjustRect(FALSE, &rc); BHH>::SetWindowPos(m_hVisibleFrame, NULL, BHH> rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, BHH> SWP_NOACTIVATE | SWP_NOZORDER);
возможно это и "красивше" (красота понятие субъективное), но это не является более правильным.
1. Сразу создается окно, а потом передвигается, более парвильно сразу создать окно с нужными размерами. Нет лишних действий.
2. когда ты создаешь 3 закладки то и передвигать тебе нужно будет 3 диалога.
а расчитав один раз размер ты создаешь все три диалога с нужными размерами.
тобишь нет трех лишних действий .
З.Ы. не претендую на оптимальность действий, но то что размер лучше расчитать до создания закладок — это факт.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[18]: Проблемы с перерисовкой, хотя OnPaint() есть
Здравствуйте, DimpLe, Вы писали:
DL>Здравствуйте, BuHHunyx, Вы писали:
BHH>>Здравствуйте, DimpLe, Вы писали:
DL>>>на счет того что у тебя закрываются вкладки
BHH>>По моему красивше:
BHH>>RECT rc; BHH>>GetClientRect(&rc); BHH>>tab.AdjustRect(FALSE, &rc); BHH>>::SetWindowPos(m_hVisibleFrame, NULL, BHH>> rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, BHH>> SWP_NOACTIVATE | SWP_NOZORDER);
DL>возможно это и "красивше" (красота понятие субъективное), но это не является более правильным. DL>1. Сразу создается окно, а потом передвигается, более парвильно сразу создать окно с нужными размерами. Нет лишних действий. DL>2. когда ты создаешь 3 закладки то и передвигать тебе нужно будет 3 диалога. DL>а расчитав один раз размер ты создаешь все три диалога с нужными размерами. DL>тобишь нет трех лишних действий .
DL>З.Ы. не претендую на оптимальность действий, но то что размер лучше расчитать до создания закладок — это факт.
1. если таб ресайзится то нужно видимый фрейм ресайзить по любому. На мой взгляд лучше это делать в одном месте.
2. нет, только видимый фрейм
Вот код контролки которую использую в куче проектов.
Здравствуйте, BuHHunyx, Вы писали:
BHH>Здравствуйте, DimpLe, Вы писали:
DL>>Здравствуйте, BuHHunyx, Вы писали:
BHH>>>Здравствуйте, DimpLe, Вы писали:
DL>>>>на счет того что у тебя закрываются вкладки
BHH>>>По моему красивше:
BHH>>>RECT rc; BHH>>>GetClientRect(&rc); BHH>>>tab.AdjustRect(FALSE, &rc); BHH>>>::SetWindowPos(m_hVisibleFrame, NULL, BHH>>> rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, BHH>>> SWP_NOACTIVATE | SWP_NOZORDER);
BHH>1. если таб ресайзится то нужно видимый фрейм ресайзить по любому. На мой взгляд лучше это делать в одном месте. BHH>2. нет, только видимый фрейм
1. без спорно. Но делать это лучше в On_Size а не как он делает в
bool Cw32View::createTabs(void)
2. твоя мысль мне недоступна расшарь. почему при Create не нужно изменять размеры остальных диалогов?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[20]: Проблемы с перерисовкой, хотя OnPaint() есть
Здравствуйте, BuHHunyx, Вы писали:
BHH>Здравствуйте, DimpLe, Вы писали:
DL>>1. без спорно. Но делать это лучше в On_Size а не как он делает в DL>>bool Cw32View::createTabs(void)
BHH>в моем примере так и делается
Я лично предпочитаю менять размеры всех окон при WM_WINDOWPOSCHANGED
и не менять при переключении таба. Дело вкуса.
DL>>2. твоя мысль мне недоступна расшарь. почему при Create не нужно изменять размеры остальных диалогов?
BHH>тк. размер будет менятся в ОнСайз, размер при добавлении указывать не надо. Еще необходимо менять размер при переключении таба.
Это ты исходишь из того что после WM_CREATE ОБЯЗАТЕЛЬНО вызывается WM_SIZE (дабы изменить начальный размер окна) и вот тут вот начинаются нюансы. Нужна ссылочка на MSDN где об этом сказано, иначе это остается догадкой.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[22]: Проблемы с перерисовкой, хотя OnPaint() есть
Здравствуйте, DimpLe, Вы писали:
DL>>>2. твоя мысль мне недоступна расшарь. почему при Create не нужно изменять размеры остальных диалогов?
BHH>>тк. размер будет менятся в ОнСайз, размер при добавлении указывать не надо. Еще необходимо менять размер при переключении таба.
DL>Это ты исходишь из того что после WM_CREATE ОБЯЗАТЕЛЬНО вызывается WM_SIZE (дабы изменить начальный размер окна) и вот тут вот начинаются нюансы. Нужна ссылочка на MSDN где об этом сказано, иначе это остается догадкой.
табы добавляются гдето так
TCITEM tci = { 0 };
tci.mask = TCIF_TEXT;
tci.pszText = _T("четотам1");
m_WorkTab1Dlg1.Create(*this);
tab.InsertItem(0, &tci, m_WorkTab1Dlg1);
//...
tab.SetCurFocus(0); // здесь собственно и происходит ресайз
проблема в том что после создания таба сфокусирован таб с индексом 0, поэтому контрол не шлет нотификацию. в моей реализации я делаю это сам
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Re[13]: Проблемы с перерисовкой, хотя OnPaint() есть
От:
Аноним
Дата:
07.01.07 23:33
Оценка:
Здравствуйте, Darked, Вы писали:
D> //создаем объект диалога маски пальцев D> m_Mashtab = new CMashtab(pParent); D> m_Mashtab->Create(m_hWnd); D> m_Mashtab->MoveWindow(&rc); D> m_Mashtab->ShowWindow(SW_HIDE);
Возможно привести код класса CMashtab (например)?
Или любого таба.
Re[15]: Проблемы с перерисовкой, хотя OnPaint() есть