Доброе время суток всем.
Суть дела вот в чем: есть 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 решит все проблемы
DefDlgProc(m_hWnd, uMsg, wParam, lParam) я убрал, поскольку происходит вызов моей OnPaint(), зацикливаается пока не падает с переполнением. DefDlgProc() — нет такой, без параметров, поэтому убрал совсем.
В итоге все по — прежнему. Мне кажется где — то запарка с собощениями, кто — то скорее всего тоже получает WM_PAINT и перерисовывает мое окно после меня.
Per aspera ad astra
Re[7]: Проблемы с перерисовкой, хотя OnPaint() есть
Здравствуйте, 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>