Форум программистов CodeGuru
20 Июнь 2018, 13:20:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
Новости:
 
   Начало   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Перерисовать фон в WinAPI  (Прочитано 24071 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Letchik
Новичок
*
Офлайн Офлайн

Сообщений: 2


Просмотр профиля
« : 04 Январь 2010, 21:46:35 »

Всем привет!
После долгих и мучительных копаний во всемирной паутине я так и не нашёл ответ на свой вопрос.
И так. Имеется элементарная прога. Открывается и сразу отображается картинка (.bmp). При изменении размеров окна картинка НЕ мерцает.  Поставил пустой обработчик на WM_ERASEBKGND, который возвращает значение TRUE. Только вот беда: фон ведь прозрачный! А как его правильно перерисовать? И чтобы картинка не мерцала!
Пытался в отдельном DC (в памяти; memDc) нарисовать сначала фон, потом там-же нарисовать изображение, а потом вывести на экран с помощью BitBlt(). Но фон всеравно прозрачный... Что не так?
P.S. я очень редко задаю вопросы на форумах, но сейчас я уже отчаялся...
Записан
3V
Администратор
Ветеран
*****
Офлайн Офлайн

Сообщений: 1347



Просмотр профиля WWW
« Ответ #1 : 04 Январь 2010, 23:33:54 »

Сразу скажу - было бы неплохо привести код (код обработки WM_PAINT как минимум (ну или где там производится рисование)).

Только вот беда: фон ведь прозрачный!

Не совсем понял, что значит "прозрачный фон".

Пытался в отдельном DC (в памяти; memDc) нарисовать сначала фон, потом там-же нарисовать изображение, а потом вывести на экран с помощью BitBlt().

Да, так и надо делать.

Но фон всеравно прозрачный... Что не так?

Ну, чтобы понять, что не так, надо бы посмотреть код.
Имхо, суть проблемы в каких либо достаточно простых вещах - типа установка не того дескриптора кисти при отрисовке фона, отрисовка фона за пределами региона отсечения, вывод не той области в целевой контекст устройства, и.т.д.
Записан

Letchik
Новичок
*
Офлайн Офлайн

Сообщений: 2


Просмотр профиля
« Ответ #2 : 05 Январь 2010, 09:17:48 »

Код:
void my_gdi::Initialize(HWND hWindow) //этот метод вызываем в обработчике WM_CREATE
{

/*hWnd является членом класса my_gdi. Его определяем для дальнейшего использования */

hWnd = hWindow;

hImg = LoadImage(NULL, _T("D:/letchik.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); //Заружаем .bmp

memDc = CreateCompatibleDC(hdc); //Создаём контекст устройства в памяти

//Заполняем memDc цветом
GetClientRect(hWnd, &rc);
FillRect(memDc, &rc, (HBRUSH)COLOR_BTNFACE + 1);
/*ВНИМАНИЕ: не обращайте внимания на то, что при изменении размеров окна
заливка будет не во всей клиентской области, а только в пределах указанного прямоугольника.
Это сейчас не главное :) */

//рисуем картинку в memDc
SelectObject(memDc, hImg);
BitBlt(memDc, 10, 10, 480, 384, memDc, 0, 0, SRCCOPY);
//по идее, в memDc сейчас должнен быть нарисован .bmp на коричневатом фоне

}

void my_gdi::DrawImg() //этот метод вызываем в обработчике WM_PAINT
{
hdc = BeginPaint(hWnd, &ps);


BitBlt(hdc, 0, 0, 640, 480, memDc, 0, 0, SRCCOPY); //выводим на экран содержимое memDc
/*Обратите внимание на размеры и координаты. 640*480 это размеры окна */

EndPaint(hWnd, &ps);

}

//--------------------------------------------------------------------------------------------//

LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
/*Класс my_gdi разработан мною*/

switch (message)
{
case WM_CREATE:

GDI.Initialize(hwnd); //Загружаем картинку
break;
case WM_PAINT:

GDI.DrawImg(); //Выводим картинку на экран
break;

case WM_DESTROY:
GDI.~my_gdi();
PostQuitMessage(0);
break;
case WM_ERASEBKGND:
return TRUE;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
break;
}

return 0;
}

Прозрачный фон и результат моих стараний  выглядят во так:


Записан
3V
Администратор
Ветеран
*****
Офлайн Офлайн

Сообщений: 1347



Просмотр профиля WWW
« Ответ #3 : 05 Январь 2010, 23:19:42 »

Не, надо не так делать.

Вообще, алгоритм действий такой:
 - создаем memDC при помощи CreateCompatibleDC, совместимый с контекстом, полученным при обработке WM_PAINT
 - создаем еще контекст (ну, допустим, bmDC) при помощи CreateCompatibleDC, совместимый с контекстом,, полученным при обработке WM_PAINT
 - создаем растр (допустим, hDstBitmap) при помощи CreateCompatibleBitmap, совместимый с контекстом, полученным при обработке WM_PAINT, с размерами прямоугольника, в котором будем рисовать (фон + картинка)
 - делаем SelectObject(memDC, hDstBitmap)
 - делаем SelectObject(bmDC, hImg)
 - закрашиваем в hDstBitmap необходимый прямоугольник цветом фона
 - делаем BitBlt из bmDC в hDstBitmap картинку
 - делаем BitBlt из hDstBitmap в контекст, полученный при обработке WM_PAINT уже всего подготовленного изображения


Т.е. сначала готовим все изображение (с фоном, и.т.д.), а потом копируем его на контекст устройства клиентской области окна.
Для подготовки изображения как раз и используем memory device context. При этом в него надо выбрать битмап, в котором будет храниться подготавливаемое изображение (его надо создать с размерами изображения, которое в итоге будет выводиться в окно).

З.Ы. в общем случае memory dc создают каждый раз при отрисовке. При этом, в принципе, можно хранить контекст с выбранным битмапом (по тексту выше это bmDC), однако обычно хранят дескриптор изображения, а bmDC также надо создавать каждый раз, чтобы не занимать попусту GDI-ресурсы.
« Последнее редактирование: 05 Январь 2010, 23:22:26 от 3V » Записан

Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!