AutoRedraw на "чистом" Api - как правильно?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 2:13

Здраствуйте. Я попробовал реализовать свойство "autoredraw" на "чистом" API. Общая идея:
    1.Cоздаётся "задний буфер". Размеры "заднего буфера" равны текущему разрешению экрана.
    2. В обработчике сообщения WM_PAINT вызовом BeginPaint заполнить структуру PAINTSTRUCT.
    В поле .rcPaint структуры PAINTSTRUCT будут координаты куска окна, которое нужно перерисовать.
    3.По этим координатам сделать BitBlt из "заднего буфера"
Вопрос: Кривой ли приведённый мною вариант? Есть ли более интересные способы реализации?
Во вложении - исходный код, в котором реализуется описанная идея.
Я заранее благодарен всем ответившим за потраченное на мой вопрос личное время.
Вложения
API autoredraw test.rar
AutoRedraw на "чистом" Api
(3.17 Кб) Скачиваний: 63
Sub or Function not defined

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Хакер » 08.01.2009 (Чт) 4:11

Эх... (эх потому, что описание одно, а на деле совсем другое. Я писал большой текст на тему того, почему вариант кривой, а когда открыл, оказалось, что всё совсем иначе.)

В том виде, в котором ты описал, вариант кажется кривым.
В том виде, в котором оно на самом деле сделано, вариант кажется нормальным.

За написание на чистом API — респект.
За использование Call — дизреспект.
(Первый больше второго)

И всё таки, кажется, что что-то у тебя не так, ибо у меня после пары запусков VB упал.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

EUGY
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 214
Зарегистрирован: 09.11.2006 (Чт) 22:51
Откуда: Мурманск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение EUGY » 08.01.2009 (Чт) 4:30

Что же, каждое окно будет использовать битмэп размером с экран?
Рисуй сразу в WM_PAINT, создавая там контекст в памяти.
Лень переписывать на vb, но принцип такой:
Код: Выделить всё
case WM_ERASEBKGND:
   return 0;
case WM_PAINT:
   PAINTSTRUCT pa;
   RECT rc;
   HDC scrDC, memDC;
   HBITMAP hbmp;
   GetClientRect(hwnd, &rc);
   BeginPaint(hwnd, &pa);
   scrDC = GetDC(0);
   memDC = CreateCompatibleDC(0);
   hbmp  = CreateCompatibleBitmap(scrDC, rc.right, rc.bottom);
   ReleaseDC(0, scrDC);
   SelectObject(memDC, hbmp);
   Paint( memDC, &rc ); // CALL MY PAINT IN BUFFER
   BitBlt(pa.hdc, 0, 0, rc.right, rc.bottom, memDC, 0, 0, SRCCOPY);
   DeleteObject(hbmp);
   DeleteDC(memDC);
   EndPaint(hwnd, &pa);
break;

Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 5:35

2 Хакер
С описанием - да, неточно выразился. Использование Call повышает читабельность кода (ИМХО). По поводу падений IDE: а если обрабатывать только WM_DESTROY? Падения продолжатся? (Проверил корректность объявлений - вроде бы всё правильно... у меня ничего не падает...)

2 EUGY
По поводу приведённого тобой кода:

    1. Зачем ты получаешь контекст дисплея? :roll: Это я про GetDC(0)
    2. BitBlt у тебя перерисовывает полностью всю клиентскую область окна, а нужно лишь область, требующую обновления.
    3.Создавать и разрушать битмапу каждый раз когда окно хочет чтобы его перерисовали - это жестоко. Лучше один раз создать.
И самое главное. А если мне нужно нарисовать на окне допустим из WM_LBUTTONDOWN?

З.Ы. Писать на чистом API - интересно. :oops:
Sub or Function not defined

EUGY
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 214
Зарегистрирован: 09.11.2006 (Чт) 22:51
Откуда: Мурманск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение EUGY » 08.01.2009 (Чт) 6:04

1. Да используй любой с не монохромным битмэпом. Хоть pa.hdc.
У меня он здесь попал только потому, что копипастил из WM_NCPAINT.
2. Ты это уже реализовал.
3. Также ты знаешь решение. Создавать битмэп в WM_SIZE.
case WM_LBUTTONDOWN:
InvalidateRect(hwnd, NULL, FALSE);

P.S.
Создавать и разрушать битмапу каждый раз когда окно хочет чтобы его перерисовали - это жестоко.

Нет, если экономишь память. А на C++ при оптимальном коде рисования окна хоть во весь экран задержка не ощутима.

Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 7:32

Когда я писал про "AutoRedraw на чистом Api" я имел в виду "AutoRedraw" в том виде, в каком он есть в Visual Basic. По принципу "нарисовал один раз и забыл" То есть при включенном у формы "AutoRedraw" мне достаточно 1 раз вызвать к примеру DrawIcon. Именно этого я и пытаюсь добиться. Когда я написал первый пост, я надеялся что мне скажут про кривость моего кода и расскажут про какой - нибудь не описанный в MSDN стиль окна (или стиль класса окна) указав который можно добиться того, что для моё окно будет сохранять свою клиентскую область в виде битмапы в памяти, и при необходимости перерисовываться. Короче как CS_SAVEBITS но только для себя самого.
Немного подумав:
2 EUGY
А если моё окно - к примеру смотрелка рисунков и почти всегда развёрнуто во весь экран? В этом случае ИМХО правильнее хранить содержимое клиентской области окна в битмапе в памяти.
Sub or Function not defined

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение tyomitch » 08.01.2009 (Чт) 8:04

Йода писал(а):Когда я написал первый пост, я надеялся что мне скажут про кривость моего кода и расскажут про какой - нибудь не описанный в MSDN стиль окна (или стиль класса окна) указав который можно добиться того, что для моё окно будет сохранять свою клиентскую область в виде битмапы в памяти, и при необходимости перерисовываться. Короче как CS_SAVEBITS но только для себя самого.

В Висте действительно такой функционал появился.
Изображение

EUGY
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 214
Зарегистрирован: 09.11.2006 (Чт) 22:51
Откуда: Мурманск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение EUGY » 08.01.2009 (Чт) 8:18

Вот WS_EX_COMPOSITED - интересный стиль, двойная буферизация, может пригодится. Правда криво работает с MDI.
А вообще, при выборе - хранить битмэп в памяти или создавать на лету, то я бы придерживался такого правила: если преобладают детали - хранить в памяти, преобладает фон - создавать в WM_PAINT и уничтожать.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Хакер » 08.01.2009 (Чт) 8:23

Да он не выбирал.

Он поставил себе задачу вручную реализовать механизм авто-перерисовки VB. И решил это задачу. А теперь спрашивает, правильно ли решил или криво.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 8:34

2 tyomitch
Нужна совместимость с XPюшей. Совсем хорошо - совместимость с Win9x. Висту я снёс через 5 дней после установки :lol: . Кроме шахмат ничего не понравилось...
2 EUGY
Подумав ещё сильнее я понял что если буду делать гипотетическую смотрелку растровых рисунков, то буду юзать FileMapping + SetDIBitsToDevice. И для "экономии памяти" мне придётся открывать файл, отображать его в память, создавать битмапу в памяти, рисовать растр, затем, освободив все ресурсы и хэндлы, повторить все сначала при следующем WM_PAINT... :cry:

Заюзав волшебную кнопку "Правка":
Ушёл гуглить WS_EX_COMPOSITED :oops:
Sub or Function not defined

dr.MIG
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1441
Зарегистрирован: 18.12.2004 (Сб) 9:53
Откуда: г.Ярославль

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение dr.MIG » 08.01.2009 (Чт) 13:42

У меня если из среды запустить программу и не завершив программу закрыть среду разработки, то вывалится ошибка о том, что инструкция по адресу 0х001с3711 обратилась к памяти по адресу 0х00000000 и память не может быть "written". В других случаях падений не наблюдалось.
Salus populi suprema lex

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Хакер » 08.01.2009 (Чт) 15:52

Это нормально.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 16:29

Ещё бы. У меня там сабклассинг в чистом виде... Когда ты закрываешь IDE, выгружается исполняемый код программы. Затем происходит попытка закрыть окно программы, тем самым вызывая оконную процедуру обработки сообщений. Но код уже выгружен, его не существует. Соответственно IDE падает.
По поводу WS_EX_COMPOSITED:
Во первых: стиль появился только в XP.
Во вторых: окно с установленным стилем WS_EX_COMPOSITED рисует всех потомков по порядку снизу вверх, используя двойную буферизацию.

Зачем был упомянут данный расширенный стиль окна - мне не понятно :roll:.
Sub or Function not defined

EUGY
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 214
Зарегистрирован: 09.11.2006 (Чт) 22:51
Откуда: Мурманск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение EUGY » 08.01.2009 (Чт) 17:17

Зачем был упомянут данный расширенный стиль окна - мне не понятно

Неужели:) Если бы я упомянул, скажем, WS_EX_LEFT, то было бы действительно непонятно.
Одна из главных причин использовать буфер - избавиться от мерцания при перерисовке и ресайзе окна. И выводить графику в "едином порыве".
Именно по этому и был упомянут WS_EX_COMPOSITED.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение tyomitch » 08.01.2009 (Чт) 17:26

EUGY писал(а):Одна из главных причин использовать буфер - избавиться от мерцания при перерисовке и ресайзе окна. И выводить графику в "едином порыве".

О рлы?
А я думал -- избавиться от необходимости хранить всё визуальное состояние в воспроизводимом виде. И автор, по-моему, так же.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Хакер » 08.01.2009 (Чт) 18:23

Избавиться от мерцания позволит не буфер, а установка такого региона отсечения, который соответствует освобождённой и нуждающейся в перерисовке области. Что, собственно, BeginPaint и так делает.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

EUGY
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 214
Зарегистрирован: 09.11.2006 (Чт) 22:51
Откуда: Мурманск

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение EUGY » 08.01.2009 (Чт) 18:41

Согласился бы, но как быть, если графика зависит (масштабируется) пропорционально размеру окна?

Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 20:00

А как собственно реализован сабж в самом Visual Basic?
Sub or Function not defined

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение tyomitch » 08.01.2009 (Чт) 20:55

Думаю, так же, как у тебя.
Вряд ли есть несколько способов реализации.
Изображение

Йода
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 99
Зарегистрирован: 06.01.2008 (Вс) 21:04
Откуда: Московская область

Re: AutoRedraw на "чистом" Api - как правильно?

Сообщение Йода » 08.01.2009 (Чт) 21:22

В таком случае я остановлюсь на своём первоначальном варианте.

Мне кажется, что тема исчерпала себя и конструктива в дальнейшем не предвидится.
Огромное спасибо всем! С уважением, Йода.
Sub or Function not defined


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 42

    TopList