Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Почему изображение при изменении размеров мигает?? 
:(
    Опции темы
devmstr
  Дата 27.2.2005, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Developer
**


Профиль
Группа: Участник
Сообщений: 879
Регистрация: 28.4.2004
Где: Ukraine

Репутация: нет
Всего: 11



Почему изображение при изменении размеров мигает???
Код

#include <windows.h>

LONG WINAPI WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,
      int nCmdShow)
{
WNDCLASS WND;
HWND hwnd;
MSG msg;

memset(&WND,0,sizeof(WND));
WND.hbrBackground = (HBRUSH)COLOR_WINDOW;
WND.hCursor = LoadCursor(NULL,IDC_ARROW);
WND.hIcon = LoadIcon(NULL,IDI_APPLICATION);
WND.hInstance = hInstance;
WND.lpfnWndProc = WndProc;
WND.lpszClassName = "Image";
WND.style = CS_VREDRAW|CS_HREDRAW|CS_OWNDC;

if (!RegisterClass(&WND))
{
 MessageBox(NULL,"Cannot create class","Error",MB_OK|MB_ICONERROR);
 return 1;
}

hwnd = CreateWindow("Image","Image",WS_OVERLAPPEDWINDOW,0,0,800,600,NULL,NULL,
     hInstance,NULL);

if (!hwnd)
{
 MessageBox(NULL,"Cannot create window","Error",MB_OK|MB_ICONERROR);
 return 1;
}

ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);

while (GetMessage(&msg,NULL,0,0))
{
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}

return msg.wParam;
}


LONG WINAPI WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
HDC hdc,hCompartibleDC;
PAINTSTRUCT ps;
static HANDLE hBitmap;
HANDLE hOldBitmap;
RECT Rect;
BITMAP Bitmap;
 



switch (uMsg)
{
case WM_CREATE:
 hBitmap = LoadImage(NULL,"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
 break;
case WM_DESTROY:
 PostQuitMessage(0);
 break;

case WM_SIZE:
 InvalidateRect(hwnd,NULL,false);
 break;
case WM_PAINT:
 hdc=BeginPaint(hwnd,&ps);
 if (!hdc)
 {
  MessageBox(NULL,"Cannot receive HDC","Error",MB_OK|MB_ICONERROR);
  SendMessage(hwnd,WM_DESTROY,NULL,NULL);
  return 0;
 }

 GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
 hCompartibleDC = CreateCompatibleDC(hdc);
 hOldBitmap = SelectObject(hCompartibleDC,hBitmap);
 GetClientRect(hwnd,&Rect);
 BitBlt(hdc,0,0,Rect.right,Rect.bottom,hCompartibleDC,0,0,SRCCOPY);

 SelectObject(hCompartibleDC,hOldBitmap);
 DeleteDC(hCompartibleDC);
 EndPaint(hwnd,&ps);
 break;

default:
 return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
[s]


--------------------
Think different ©Steve Jobs 
user posted image
PM MAIL WWW   Вверх
MacTep
Дата 15.5.2005, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: нет
Всего: 4



Попробуй убрать из обработки сообщения WM_SIZE строчку
Код

InvalidateRect(hwnd,NULL,false);

Эта функция изменяет размер действительной части экрана и поэтому происходит мигание. Я думаю так...


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Fixin
Дата 15.5.2005, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Цитата
Эта функция изменяет размер действительной части экрана

LOL.
Это функция принудительной перерисовки области окна. Так как указатель на прямоугольник нулевой, то перерисовываем все окно.
Добавлено @ 19:59
Но убрать надо, или задавать перерисовываемую область.
PM MAIL ICQ   Вверх
Nastya
Дата 16.5.2005, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 3
Всего: 44



А лучше еще выводить с CompatibleDC, и накладывать сверху.
Где-то это на форуме уже обсуждалось


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
Alastis
Дата 16.5.2005, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 251
Регистрация: 15.11.2004
Где: Казахстан, Астана

Репутация: нет
Всего: 10



уберешь ты или оставишь InvalidateRect ничего не изменитсяsmile
нужно обработать WM_ERASEBKGND. Просто поставь заглушку:

Код

case WM_ERASEBKGND:
            
break;



--------------------
Прости, что я говорю, когда ты меня перебиваешь.
PM MAIL WWW ICQ   Вверх
Nastya
Дата 16.5.2005, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 3
Всего: 44



Цитата
уберешь ты или оставишь InvalidateRect ничего не изменится
нужно обработать WM_ERASEBKGND. Просто поставь заглушку:

После чего все начинает просто дико глючить, летали, знаем smile


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
MacTep
Дата 16.5.2005, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: нет
Всего: 4



Ну и как же тогда решить эту проблему? smile


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Fixin
Дата 16.5.2005, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Цитата
задавать перерисовываемую область

PM MAIL ICQ   Вверх
Fixin
Дата 16.5.2005, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Сделай статический элемент без текста и замени ему главную процедуру на свою, чтоб рисовать в этом статике. Может, не будет перерисовываться статик, если изменение размера окна его не затронет.
Но вопрос интересный сейчас поэксперементирую.
PM MAIL ICQ   Вверх
Fixin
Дата 16.5.2005, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Вот что надо делать:
Код
WND.style = 0;
И все!
Добавлено @ 22:54
Все гениальное - просто, как глупость.
Добавлено @ 22:55
По умолчанию, или по случайному распределению памяти, ставится перерисрвка.
PM MAIL ICQ   Вверх
MacTep
Дата 17.5.2005, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1292
Регистрация: 4.8.2003
Где: г. Самара

Репутация: нет
Всего: 4



Цитата
Все гениальное - просто, как глупость.

smile Спасибо!


--------------------
(A)bort, (R)etry, (I)gnore = Haфиг, Heфиг, Пoфиг ... :)
PM MAIL   Вверх
Plamiv
Дата 19.4.2006, 04:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 19.4.2006
Где: г. Брест

Репутация: нет
Всего: нет



Возникла похожая проблема:
Почему изображение при прокрутке скролом мигает???
Код идентичен представленному выше. Может тоже есть что-то простое и гениальное?
 
PM MAIL   Вверх
zhgutov
Дата 26.4.2006, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 14.12.2004

Репутация: 1
Всего: 2



Код
WNDCLASS::hbrBackground = (HBRUSH) GetStockObject (NULL_BRUSH);

Плюс двойная буферизация. При этом можно использовать InvalidateRect (HWND, RECT*, false); Должен получиться ожидаемый результат... 

Это сообщение отредактировал(а) zhgutov - 26.4.2006, 15:04
--------------------
Приполз. Увидел. Укусил.
PM MAIL   Вверх
GremlinProg
Дата 10.5.2006, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Хм... как много всего, но последний пост был наиболее ближе к правильному.
Изображение начинает моргать в двух случаях

1. Перерисовка контрола происходит в несколько итераций, т.е. при изменении каких-либо параметров вы вызываете InvalidateRect, после чего UpdateWindow, а потом так еще 1-2 раза. И это, как вы уже догадываетесь не правильно. Даже если времени на рисование уходит не много, не пытайтесь так перестраховываться. 

2. zhgutov, совершенно верно, только InvalidateRect тут ни при чем. Все дело в WM_ERASEBKGND, как заметил Alastis, только это не заглушка. Поясню: двойной буфер хорош тем, что в него можно рисовать сколько-угодно и как угодно, пусть даже не оптимально, а потом разом показать, т.е. скопировать битмап этого буфера, или только его часть в битмап девайса контрола. Но это не решит проблему, потому что WM_ERASEBKGND закрасит часть девайса цветом заднего фона контрола, а затем вы выводите реальную картинку. Вот в этот момент как раз и происходит маленький моргунчик. Заметьте, даже при двойной буферизации. Чтобы этого не происходило, нужно конечно перекрыть WM_ERASEBKGND. Для этого нужно написать че-то типо этого в обработчике:
Код

case WM_ERASEBKGND:
  return TRUE;// то бишь, вернуть единицу

Но это еще не все. Забудьте о функциях BeginPaint и EndPaint,  если вы не хотите, чтобы так же не моргала неклиентская часть всех окон: функция BeginPaint вызывает перерисовку неклиентской части всех дочерних контролов, и так как это происходит автоматически, то вы не сможете сюда вставить двойной буфер, моргунчик останется(виндовоз просто перечислит все N дочерних окон и произведет N прорисовок на одном девайсе, т.е. если это девайс контрола, то моргание будет видно). Тройная связка: GetUpdateRect(GetUpdateRgn) - GetDC - ValidateRect(ValidateRgn) выполняют то же самое, что и BeginPaint, с небольшим отличием: GetUpdateRgn возвращает аж целый регион коррекции, в отличии от жалкой BeginPaint, которая возвращает только прямоугольник. Если вы не знаете что делает каждая из этих функций, то обратитесь на форум за помощью, здесь я не буду выкладывать их описание. Выполнить прорисовку неклиентской части дочернего контрола можно разными способами, я сам для этого использую сообщения WM_PRINT и WM_PRINTCLIENT. Сейчас я покажу кусок своей системы, но не обольщайтесь, сам по себе, отдельно он работать не будет, вам самим придется делать его под себя, потому что я не использую MFC или WTL, но и не WinMain, просто свою систему классов. Почитайте как я реализовал двойной буфер на WM_PRINT и WM_PRINTCLIENT и сделайте свой вариант.
Код

            case WM_ERASEBKGND:{
                if((wfDoubleBuffer)&&(!wfEraseDC)){
                    BreakProcessMessage(msg);
                    BreakDefaultProcessMessage(msg);
                    msg.lresult    = TRUE;
                }
                break;
            }
            case WM_PRINTCLIENT:{
                HDC hdc    = (HDC)msg.wparam;
                if(msg.lparam&PRF_ERASEBKGND){
                    wfEraseDC    = true;
                    ::SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)hdc,NULL);
                    wfEraseDC    = false;
                    msg.lparam&=~PRF_ERASEBKGND;
                }
                if(msg.lparam&PRF_CLIENT)
                    Notify(msg);
                else{
                    DefaultProcessMessage(msg);
                    BreakProcessMessage(msg);
                }
                break;
            }
            case WM_PRINT:{
                HDC hdc    = (HDC)msg.wparam;
                if(msg.lparam&PRF_ERASEBKGND){
                    wfEraseDC    = true;
                    ::SendMessage(hwnd,WM_ERASEBKGND,(WPARAM)hdc,NULL);
                    wfEraseDC    = false;
                    msg.lparam&=~PRF_ERASEBKGND;
                }
                if(msg.lparam&PRF_NONCLIENT)
                    Notify(msg);
                else{
                    DefaultProcessMessage(msg);
                    BreakProcessMessage(msg);
                }
                break;
            }
            case WM_NCPAINT:{
                BreakDefaultProcessMessage(msg);
                BreakProcessMessage(msg);
                if(msg.wparam!=NULLREGION){
                    ::GetRgnBox((HRGN)msg.wparam,&update);
                    ::MapWindowPoints(HWND_DESKTOP,::GetAncestor(hwnd,GA_PARENT),(POINT*)&update,2);
                    if(!::IntersectRect(&update,&update,&bounds))
                        break;
                }else
                    update    = bounds;
                update    -= low(bounds);
                if(wfDoubleBuffer){
                    CMemoryGraphicDevice hmemdc(update);
                    ::SendMessage(hwnd,WM_PRINT,(WPARAM)(HDC)hmemdc,PRF_NONCLIENT|PRF_ERASEBKGND);
                    HDC hdc    = GetWindowDC(hwnd);
                    ClipClient(hdc);
                    ::BitBlt(hdc,update.left,update.top,::width(update),::height(update),hmemdc,update.left,update.top,SRCCOPY);
                    ::ReleaseDC(hwnd,hdc);
                }else{
                    HDC hdc    = GetWindowDC(hwnd);
                    ::IntersectClipRect(hdc,update.left,update.top,update.right,update.bottom);
                    ClipClient(hdc);
                    ::SendMessage(hwnd,WM_PRINT,(WPARAM)hdc,PRF_NONCLIENT|PRF_ERASEBKGND);
                    ::ReleaseDC(hwnd,hdc);
                }
                break;
            }
            case WM_PAINT:{
                BreakDefaultProcessMessage(msg);
                BreakProcessMessage(msg);
                if((!::GetUpdateRect(hwnd,&update,FALSE))||(IsRectEmpty(&update)))
                    update    = client;
                if(wfDoubleBuffer){
                    ::ValidateRect(hwnd,&update);
                    CMemoryGraphicDevice hmemdc(update);
                    ::SendMessage(hwnd,WM_PRINT,(WPARAM)(HDC)hmemdc,PRF_CLIENT|PRF_ERASEBKGND);
                    ::HideCaret(hwnd);
                    HDC hdc    = (msg.wparam?(HDC)msg.wparam:GetDC(hwnd));
                    RECT rw;
                    for(HWND hchild = ::GetWindow(hwnd,GW_CHILD);hchild;hchild = ::GetWindow(hchild,GW_HWNDNEXT)){
                        if(!::GetWindowRect(hchild,&rw))
                            continue;
                        if(!CWindowCover(hchild).Style[WS_VISIBLE])
                            continue;
                        ::MapWindowPoints(HWND_DESKTOP,hwnd,&low(rw),2);
                        if(!::IntersectRect(&rw,&update,&rw))
                            continue;
                        ::ExcludeClipRect(hdc,rw.left,rw.top,rw.right,rw.bottom);
                        ::MapWindowPoints(hwnd,hchild,&low(rw),2);
                        ::RedrawWindow(hchild,&rw,NULL,RDW_ERASE|RDW_FRAME|RDW_INVALIDATE);
                    }
                    ::BitBlt(hdc,update.left,update.top,::width(update),::height(update),hmemdc,update.left,update.top,SRCCOPY);
                    if(!msg.wparam)::ReleaseDC(hwnd,hdc);
                    ::ShowCaret(hwnd);
                }else{
                    if(msg.wparam){
                        PAINTSTRUCT ps;
                        ::BeginPaint(hwnd,&ps);
                        ::SendMessage(hwnd,WM_PRINT,(WPARAM)ps.hdc,PRF_CLIENT|(ps.fErase?PRF_ERASEBKGND:NULL));
                        ::EndPaint(hwnd,&ps);
                    }else{
                        ::ValidateRect(hwnd,&update);
                        ::SendMessage(hwnd,WM_PRINT,(WPARAM)msg.wparam,PRF_CLIENT|PRF_ERASEBKGND);
                    }
                }
                break;
            }

В каком то разделе винграда я уже обещал выложить нечто подобное, будем считать, что я свое обещание выполнил ). 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 10.5.2006, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Да, кстати, есть еще один простой способ заставить не моргать контролы при прорисовке. Я использую его редко, только если нужно быстро написать програмку, без всяческих ухищрений. Думаю этот способ вам подойдет, но после нескольких экспериментов вы сами увидите его недостатки.

Добавьте к набору флагов dwExStyle, функции CreateWindowEx дополнительный флаг WS_EX_COMPOSITED 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 10.5.2006, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Цитата(GremlinProg @  10.5.2006,  17:28 Найти цитируемый пост)
Забудьте о функциях BeginPaint и EndPaint,  если вы не хотите, чтобы так же не моргала ... 

Эта проблема решается проще - всего лишь флаг WS_CLIPCHILDREN родительскому окну, и дети не включаются в перерисовку. Что касается BeginPaint-EndPaint, то эта парочка делает по-крайней мере одну полезную вещь, которую без нее нужно делать руками (как ты и делаешь) - валидэйтит регион, для которого пришел WM_PAINT. А вовсе не приводит к перерисовке дочерних окон. 
Кроме того, при использовании вне-экранного буфера WM_ERASEBKGND обычно совсем затыкают (или просто можно поставить нулевую кисть классу окна при регистрации), и просто красят фон прямо во время отрисовки (если надо). А посылать для этого WM_ERASEBKGND с "левым" dc как-то криво, согласись.
Кроме того, использовать сообщение WM_PRINT не по назначению тоже не очень хорошо. Тем более всего-то надо функцию свою написать.
Т.е. что я хочу сказать - с точки зрения изучения "как оно все устроено" - ты разобрался прекрасно и твой код весьма полезен (в учебных целях). Но писать так в реальном проекте - боже упаси.
 


--------------------
...
PM   Вверх
GremlinProg
Дата 10.5.2006, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата
Что касается BeginPaint-EndPaint, то эта парочка делает по-крайней мере одну полезную вещь, которую без нее нужно делать руками (как ты и делаешь) - валидэйтит регион, для которого пришел WM_PAINT. А вовсе не приводит к перерисовке дочерних окон.

Весьма поспешное заявление, даже неудобно говорить это Ко-модератор'у. Я пишу только о том, что уже давно проверено. Не мне учить вас как проверить моё утверждение.
Не нужно так громко заявлять, тем более наскоро пробежавшись по тексту. О перерисовке целых контролов я и не говорил, перечитайте, пожалуйста пост.
Цитата
WM_ERASEBKGND с "левым" dc как-то криво, согласись.

WM_PAINT с "левым" dc тоже как-то криво, только это не я придумал, есть стандарт, вам не мешало бы его почитать.
Цитата
Кроме того, использовать сообщение WM_PRINT не по назначению

Вы, видимо считаете, что WM_PRINT предназначен только для вывода на принтер? MSDN вас простит ). 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 10.5.2006, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



...да, да, WS_CLIPCHILDREN отсекает дочерние компоненты при прорисовке, но! Отсекает для родителя, т.е. папа не будет на них рисовать, BeginPaint просто перерисует НЕКлиентскую часть дочек и отсечет регионы их окон из папы, клиента дочек, он конечно же не тронет. Вы можете проверить, когда вызывается WM_NCPAINT, и убедиться в этом. Причем регион, который в дальнейшем выбирается в контекст устройства папы передается в WPARAM'етре. Это как раз и обуславливает такую, мягко говоря, непоследовательную прорисовку неклиентской области окна. WS_CLIPCHILDREN проблему не решит! 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 10.5.2006, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



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

Насчет неклиентской области дочерних окон и WS_CLIPCHILDREN ты, наверно, прав, но мне редко встречались контролы, где это имело бы значение... Что касается BeginPaint - повторюсь - эта функция ничего не перерисовывает! Да, она посылает ERASEBKGND, а также устанавливает регион отсечения, о чем и написано в MSDN... 

Кроме того, она избавляет тебя от возни с кареткой и пр., что иначе нужно делать вручную.
Подкорректировать регион отсечения (исключить из него неклиентскую часть дочерних окон, если приспичило) можно в любой момент - например, на ERASEBKGND (если оно в принципе приходит), а можно и прямо в WM_PAINT. Как-то я это делала на NCPAINT...

Что касается WM_PRINT, то стандартно оно из WM_PAINT не вызывается, и согласно MSDN используется для вывода "most commonly in a printer device". Хотя и необязательно, тут ты прав. Я хотела сказать лишь то, что неразумно посылать самому себе сообщения, упаковывать флаги и параметры, если это сообщение ты же сам и обрабатываешь. Проще функцию написать\вызвать. Уж не говоря о том что это несколько быстрее.
 


--------------------
...
PM   Вверх
GremlinProg
Дата 10.5.2006, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата
Я хотела сказать лишь то, что неразумно посылать самому себе сообщения, упаковывать флаги и параметры, если это сообщение ты же сам и обрабатываешь.

Есть один момент, вернее два, но один проще описать: давненько, когда я еще заморачивался с разными прибамбасами GDI, мне на глаза попалась такая вот задачка: допустим есть Edit, или Rich Edit - стандартно настроенные и нужно например за текстом показать ролик, или сделать анимированную подсветку части текста, причем, естественно, прибегать к формированию собственного текстового компонента было некогда. А сделать надо было корректно, без заплаток типа TRANSPARENT. Так вот решение оказалось довольно простым. Код который я выложил позволяет наследовать прорисовку анцестора, не родителя как до операции, так и после неё, причем дважды копировать девайс не нужно, ну и без морганий, соответственно. Просто сообщение WM_PRINT знают все системные компоненты, вернее его почти ни кто не обрабатывает, поэтому система ведет себя одинаково для всех контролов. Хм, это кстати единственный способ, который я тогда нашел.
Цитата
Что касается BeginPaint - повторюсь - эта функция ничего не перерисовывает!

Хотите - верьте, хотите - проверьте, повторять не буду. Дареному коню в зубы не глядят. Наступайте на грабли, на которые наступало уже несколько поколений программистов, я показал вам где эти грабли лежат, а остальное - дело техники.

Мозоль - не мозоль, но субординацию надо соблюдать!

Доверяй но проверяй, и не кричите, ради бога, пока не проверите! 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 10.5.2006, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



по поводу WM_ERASEBKGND, все таки правильнее оставить его реализацию закраски заднего фона, собственно, сообщение предназначено только для этого, не нужно так прямо его сразу отвергать. Он нужен для простых компонент, в которые не всегда хочется лезти,  ведь намного проще установить один раз кисть для класса, чем вводить обработку сообщения. Это просто правило сохранения стандарта. 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Earnest
Дата 11.5.2006, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Не буду с тобой спорить, все как-то беспредметно. 
Я ведь не говорила, что твой код неправильный. Он просто избыточен и излишне усложнен, и пытается решить все возможные проблемы сразу.
В каждом конкретном контексте возможно свое, гораздо более простое решение.

Насчет ERASEBCKGND - на мой взгляд проще вызвать PatBlt или даже FillRect, поскольку вся прорисовка идет во вне-экранный буфер. Это мое мнение подтверждается многочисленными реализациями нестандартных контролов хотя бы на том же codeproject.
 
В конце концов у каждого свой опыт. 

Цитата(GremlinProg @  10.5.2006,  21:16 Найти цитируемый пост)
Мозоль - не мозоль, но субординацию надо соблюдать!

Интересно, что ты хотел этим сказать? Кто тут из нас двоих начальник? smile  


--------------------
...
PM   Вверх
GremlinProg
Дата 11.5.2006, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



На сколько я понял, у вас слишком большие амбиции, впрочем, флейм здесь неуместен. Если хотите пообщаться флудите в соответствующем этому месте. Я сильно сомневаюсь, что ваша репутация от этого возрастет, а мне до плюсиков нет дела, я - практик. Мое первое сообщение вы подвергли беспочвенной критике, тем самым вы сами себя спровоцировали на безграмотность. Так же сомневаюсь, что среди молодых к вам после этой темы будет доверие. И что теперь толку от ярлыка, который вы сами себе навесили. Начальник не тот кто главнее, а тот, кому можно доверить управление над подчиненными. Мои люди мне доверяют! А по поводу кода, я думаю найдется не мало сообразительных людей, которые подтвердят мои слова. Теория должна опираться на практику.

Цитата
Насчет ERASEBCKGND - на мой взгляд проще вызвать PatBlt или даже FillRect

вы хотя бы раз взгянули, что выполняет DefWindowProc в ответ на это сообщение. Когда посмотрите, задайте себе вопрос: кто говорит о избыточности? Вы ради самовосхваления дезинформируете молодое поколение. Очень плохо.

Рекурсия - то что вы называете "...избыточен и излишне усложнен..." используется в иерархии наследования классов. Если бы вы внимательно читали мой первый пост, то я об этом сразу и сказал, поэтому она оправдана. Вы ведь даже не понимаете о назначении большинства методов, а судите.

Я не намерен более развивать тему, поскольку самых главных вопросов я так и не услышал, если у остальных они появятся, обащайтесь ко мне непосредственно по аське. Вопрос исчерпан окончательно! 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
v2v
Дата 26.2.2007, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1620
Регистрация: 20.9.2006
Где: Киев

Репутация: нет
Всего: 56




Из всего вышесказаного лучше всего помогает
Код

wcex.style= 0;//CS_HREDRAW | CS_VREDRAW;

Но при этом при перерисовке проц забивается на 100 % (это если хорошо потягать окошко) ...  как от этого лечиться??


--------------------
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1351 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.