Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Мерцание BitMap BitBlt рисование


Автор: Oreshin 10.9.2007, 10:10
У меня проблема с мерцанием, вроде ба как понял надо битмап и битблт юзать.
Но что то у меня ни как не получается, у меня теперь рисуется все черно-белое и мерцание как было так и осталось.
Вот код:
Код

hdc = GetDC(hwnd);
cdc=CreateCompatibleDC(hdc);
b=CreateCompatibleBitmap(cdc,1000,560);
HPEN hWhitePen, hBlackPen, hOldPen;
HBRUSH hGreenBrush,hWhiteBrush, hOldBrush;
hWhitePen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
hBlackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
hWhiteBrush = CreateSolidBrush(RGB(255,255,255));
hGreenBrush = CreateSolidBrush(RGB(0, 255, 0));
SelectObject(hdc, b);
SelectObject(hdc, hBlackPen);
SetBkMode(cdc, TRANSPARENT);  // прозрачный фон
SetTextColor(hdc,RGB(100, 100, 100)); // цвет текста
Ukladka[0] == FALSE ? hOldBrush = (HBRUSH)SelectObject(hdc,WhiteBrush):hOldBrush = (HBRUSH)SelectObject(hdc, hGreenBrush);
Rectangle(hdc, 16, 460, 16+xUkl, 482);
TextOut(hdc, 31, 462, (LPSTR)"1", 1);
RECT rt;
GetClientRect(hwnd, &rt);
ico0= LoadIcon(hThisInst, (LPCSTR)IDI_ICON3);
ico1= LoadIcon(hThisInst, (LPCSTR)IDI_ICON1);
ico2= LoadIcon(hThisInst, (LPCSTR)IDI_ICON2);
DrawIconEx(hdc,xuklad,482,ico0,30,30,0,0,DI_IMAGE);
event1==FALSE ? DrawIconEx(hdc,16,65,ico1,11,11,0,0,DI_IMAGE) : DrawIconEx(hdc,16,65,ico2,11,11,0,0,DI_IMAGE);
event2==FALSE ? DrawIconEx(hdc,80 * cxChar,65,ico1,11,11,0,0,DI_IMAGE) : DrawIconEx(hdc,80 * cxChar,65,ico2,11,11,0,0,DI_IMAGE);
BitBlt(  
hdc,// handle to destination device context 
0,    // x-coordinate of destination rectangle's upper-left corner
0,    // y-coordinate of destination rectangle's upper-left corner
1000,    // width of destination rectangle 
560,    // height of destination rectangle 
cdc,    // handle to source device context 
0,    // x-coordinate of source rectangle's upper-left corner  
0,    // y-coordinate of source rectangle's upper-left corner
SRCCOPY    // raster operation code 
);
// вернуть старый объекты pen и brush в DC
SelectObject(hdc, b);
SelectObject(hdc, hOldPen);
SelectObject(hdc, hOldBrush);


Автор: Alexeis 10.9.2007, 10:27
  Разумеется, ведь рисовать нужно на битмапе, а потом битмап рисовать на окне.

Код

SelectObject(hdc, b); // cdc  а не hdc
SelectObject(hdc, hBlackPen);


и дальше по тексту везде нужно заменить.

т.е. все рисовать на невидимой поверхности, которую потом рисовать одной операцией.

Автор: zkv 10.9.2007, 11:04
добавлю
Цитата(Oreshin @  10.9.2007,  10:10 Найти цитируемый пост)
b=CreateCompatibleBitmap(cdc,1000,560);

насколько я помню правильно так:
CreateCompatibleBitmap(hdc //...
те создавать битмап совместимый с исходным контекстом, а то проблема с глубиной цвета может быть.
Цитата(Oreshin @  10.9.2007,  10:10 Найти цитируемый пост)
SelectObject(hdc, b);

явно лишнее

Автор: Oreshin 10.9.2007, 12:51
Сделал соответствующие поправки в коде. Теперь у меня на экране появляются  цветные элементы которые я рисую, но к сожалению вся область за исключением тех элементов каторые я рисую закрашивается черным цветом smile и не показываются мои button и progress bar, а если я двигаю экран то у меня появляются те элементы каторые я  в WM_CREATE создаю т.е. button и progress bar , а все элементы каторые я рисую на битмапе не рисуются и черная заливка проподает smile Kстати я перерисовываю InvalidateRact(hwnd,NULL,TRUE);
с частотой 100 Гц.
Вот код после исправлений:
Код

hdc = GetDC(hwnd);
cdc=CreateCompatibleDC(hdc);
b=CreateCompatibleBitmap(hdc,1000,560);
HPEN hWhitePen, hBlackPen, hOldPen;
HBRUSH hGreenBrush,hWhiteBrush, hOldBrush;
hWhitePen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
hBlackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
hWhiteBrush = CreateSolidBrush(RGB(255,255,255));
hGreenBrush = CreateSolidBrush(RGB(0, 255, 0));
SelectObject(cdc, b);
SelectObject(cdc, hBlackPen);
SetBkMode(cdc, TRANSPARENT);  // прозрачный фон
SetTextColor(cdc,RGB(100, 100, 100)); // цвет текста
Ukladka[0] == FALSE ? hOldBrush = (HBRUSH)SelectObject(cdc,WhiteBrush):hOldBrush = (HBRUSH)SelectObject(cdc, hGreenBrush);
Rectangle(cdc, 16, 460, 16+xUkl, 482);
TextOut(cdc, 31, 462, (LPSTR)"1", 1);
RECT rt;
GetClientRect(hwnd, &rt);
ico0= LoadIcon(hThisInst, (LPCSTR)IDI_ICON3);
ico1= LoadIcon(hThisInst, (LPCSTR)IDI_ICON1);
ico2= LoadIcon(hThisInst, (LPCSTR)IDI_ICON2);
DrawIconEx(hdc,xuklad,482,ico0,30,30,0,0,DI_IMAGE);
event1==FALSE ? DrawIconEx(cdc,16,65,ico1,11,11,0,0,DI_IMAGE) : DrawIconEx(hdc,16,65,ico2,11,11,0,0,DI_IMAGE);
event2==FALSE ? DrawIconEx(cdc,80 * cxChar,65,ico1,11,11,0,0,DI_IMAGE) : DrawIconEx(cdc,80 * cxChar,65,ico2,11,11,0,0,DI_IMAGE);
BitBlt(  
hdc,// handle to destination device context 
0,    // x-coordinate of destination rectangle's upper-left corner
0,    // y-coordinate of destination rectangle's upper-left corner
1000,    // width of destination rectangle 
560,    // height of destination rectangle 
cdc,    // handle to source device context 
0,    // x-coordinate of source rectangle's upper-left corner  
0,    // y-coordinate of source rectangle's upper-left corner
SRCCOPY    // raster operation code 
);
// вернуть старый объекты pen и brush в DC
SelectObject(cdc, b);
SelectObject(cdc, hOldPen);
SelectObject(cdc, hOldBrush);

Автор: Andrey44 10.9.2007, 13:08
Так сделай FillSolidRect() - нужным цветом smile

Добавлено через 1 минуту и 34 секунды
И обработай WM_ERASEBKGND smile 

Автор: Alexeis 10.9.2007, 13:13
  Это все делается в обработчике WM_PAINT?


Автор: Andrey44 10.9.2007, 15:05
FillSolidRect() - в WM_PAINT
WM_ERASEBKGND  - return true; smile 

Автор: zkv 10.9.2007, 15:09
Andrey44, я думаю Alexeis в курсе, и не у тебе спрашивал  smile  

Автор: Andrey44 10.9.2007, 17:34
 smile  Таки точно не у меня! Как-то я сразу не сообразил smile 
Извиняюсь за пост не по теме smile 

Автор: Oreshin 10.9.2007, 19:54
Да это все в WM_PAINT делается, а то что мне посоветовали я завтра на работе с утра попробую и напишу результат.

Автор: Oreshin 11.9.2007, 08:56
Стал рисовать и то что я в ПАИНТЕ рисую и те элементы которые в КРЕАТЕ после hdc = GetDC(hwnd) на hdc = BeginPaint(hwnd,&sp);
 И мерцания по меньше стало после добавления SetForegroundWindow(hwnd);
Сейчас сделаю фон как советовал Andrey44 через FillSolidRect(), а точнее через FillRect() т.к. если я не ошибаюсь то FillSolidRect() в WinAPI нет smile , но мерцание мне кажется маленькое останется :-(

Исправленный код:

Код

SetForegroundWindow(hwnd);
hdc = BeginPaint(hwnd,&sp);
cdc=CreateCompatibleDC(hdc);
b=CreateCompatibleBitmap(hdc,1000,560);
HPEN hWhitePen, hBlackPen, hOldPen;
HBRUSH hGreenBrush,hWhiteBrush, hOldBrush;
hWhitePen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
hBlackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
hWhiteBrush = CreateSolidBrush(RGB(255,255,255));
hGreenBrush = CreateSolidBrush(RGB(0, 255, 0));
SelectObject(cdc, b);
SelectObject(cdc, hBlackPen);
SetBkMode(cdc, TRANSPARENT);  // прозрачный фон
SetTextColor(cdc,RGB(100, 100, 100)); // цвет текста
Ukladka[0] == FALSE ? hOldBrush = (HBRUSH)SelectObject(cdc,WhiteBrush):hOldBrush = (HBRUSH)SelectObject(cdc, hGreenBrush);
Rectangle(cdc, 16, 460, 16+xUkl, 482);
TextOut(cdc, 31, 462, (LPSTR)"1", 1);
RECT rt;
GetClientRect(hwnd, &rt);
ico0= LoadIcon(hThisInst, (LPCSTR)IDI_ICON3);
ico1= LoadIcon(hThisInst, (LPCSTR)IDI_ICON1);
ico2= LoadIcon(hThisInst, (LPCSTR)IDI_ICON2);
DrawIconEx(hdc,xuklad,482,ico0,30,30,0,0,DI_IMAGE);
event1==FALSE ? DrawIconEx(cdc,16,65,ico1,11,11,0,0,DI_IMAGE) : DrawIconEx(hdc,16,65,ico2,11,11,0,0,DI_IMAGE);
event2==FALSE ? DrawIconEx(cdc,80 * cxChar,65,ico1,11,11,0,0,DI_IMAGE) : DrawIconEx(cdc,80 * cxChar,65,ico2,11,11,0,0,DI_IMAGE);
BitBlt(  
hdc,// handle to destination device context 
0,    // x-coordinate of destination rectangle's upper-left corner
0,    // y-coordinate of destination rectangle's upper-left corner
1000,    // width of destination rectangle 
560,    // height of destination rectangle 
cdc,    // handle to source device context 
0,    // x-coordinate of source rectangle's upper-left corner  
0,    // y-coordinate of source rectangle's upper-left corner
SRCCOPY    // raster operation code 
);
// вернуть старый объекты pen и brush в DC
SelectObject(cdc, hOldPen);
SelectObject(cdc, hOldBrush);

Автор: zkv 11.9.2007, 09:11
Oreshin, WM_ERASEBACKGROUND (забыл как дословно, догадаешься) обработал?
нужно просто TRUE вернуть.

PS о чем говорил Andrey44.

Автор: Alexeis 11.9.2007, 09:34
Код

DrawIconEx(hdc,xuklad,482,ico0,30,30,0,0,DI_IMAGE);

  Все еще рисуется на окне, а не на битмапке.

Автор: Oreshin 11.9.2007, 13:41
Теперь все на битмапе рисую, и кстати говоря решил пока что не использовать WM_ERASEBKGND, а то с ним глючит сильно. Я фон по методу  FillRect() сделал и вроде все нормально пока что smile .

НО появилась фигня какая-то smile или я что- то не так делаю.

Я обнавляю изображение через InvalidateRact() с частотой 100 Гц и спустя полторы секунды у меня перестае отображаться bitmap smile  может я где то забываю ресурсы освободить или еще что? Ни как причину понять не могу токого поведения smile 

А может у кого ни то есть примерчик с решением проблемы мерцания smile  smile 




Автор: Alexeis 11.9.2007, 13:56
  Все выделенные битмапы, кисти, иконки должны быть удалены, а контексты освобождены по выходу.

Автор: Oreshin 11.9.2007, 14:15
Как освободить битмап и контекст?

Автор: Alexeis 11.9.2007, 14:26
Контекст ReleaseDC(); 
битмап    DeleteObject();

Автор: zkv 11.9.2007, 14:56
Цитата(Oreshin @  11.9.2007,  13:41 Найти цитируемый пост)
Я обнавляю изображение через InvalidateRact() с частотой 100 Гц

это тебе действительно нужно?

BeginPaint() есть, а где EndPaint()?

Автор: Oreshin 12.9.2007, 09:27
Не хватало DeleteDC();

Большое ВСЕМ СПАСИБО за помощь и терпение smile

Автор: Podarochek 28.2.2009, 18:50
извините, что не по теме smile , но ->

Цитата(Oreshin @  11.9.2007,  13:41 Найти цитируемый пост)
Я обнавляю изображение через InvalidateRact() с частотой 100 Гц


как вы это делаете..оч. инетерсно!

Автор: Alexeis 28.2.2009, 19:52
Podarochek, например по таймеру. Таймер дает разрешение в 10мс, т.е. как раз 100Гц.

Добавлено через 44 секунды
хотя нафик это нада, больше 25 Гц все равно не воспринимается.

Автор: Podarochek 28.2.2009, 19:58
а...smile...ну стандартный я знаю...меня смутило 100Гц...думаю прикольно можна частоту ставить в Гц..а мож. и естьsmile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)