Объяснение визуального бага VB 6 под Windows 7

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

Объяснение визуального бага VB 6 под Windows 7

Сообщение Filyus » 11.03.2013 (Пн) 14:07

Наконец-то удалось понять почему VB 6 лагает при измнении размеров элементов на форме при включенной композиции рабочего стола. Он использует довольно необычный подход к рисованию. Код примерно такой:
Код: Выделить всё
hDC =  GetDC(0)
GetClientRect hWndForm, WindowRect
MapWindowPoints hWndForm, 0, FrameRect, 2
...
hBrush = GetStockObject(GRAY_BRUSH)
hOldBrush = SelectObject(hDC, hBrush)
PatBlt ..., PATINVERT
PatBlt ..., PATINVERT
PatBlt ..., PATINVERT
PatBlt ..., PATINVERT
SelectObject hDC, hBrush
ReleaseDC 0, hDC
RedrawWindow 0,0,0,RDW_ALLCHILDREN Or RDW_UPDATENOW

Проблема в том, что VB 6 использует окно рабочего стола вместо окна формы для рисования рамки выделения. Из-за этого каждая операция PatBlt длится около 0,026 секунды, все четыре операции вместе - около 0,1 секунды, что довольно существенно для рисования.
В Windows 7 проблема устраняется отключением композиции рабочего стола (в настройках быстродействия системы или в настройках ярлыка).
В Windows 8 проблема устраняется установкой совместимости с Windows Vista SP 2 или ниже.
Вложения
GUI Bug Demonstration.rar
(2.02 Кб) Скачиваний: 78
Последний раз редактировалось Filyus 09.04.2013 (Вт) 20:11, всего редактировалось 3 раз(а).

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

Re: Объяснение визуального бага VB 6 под Windows 7

Сообщение Хакер » 11.03.2013 (Пн) 19:27

Filyus писал(а):Проблема в том, что VB 6 использует окно рабочего стола вместо окна формы для рисования рамки выделения

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

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Объяснение визуального бага VB 6 под Windows 7

Сообщение Filyus » 11.03.2013 (Пн) 22:06

Хакер писал(а):
Filyus писал(а):Проблема в том, что VB 6 использует окно рабочего стола вместо окна формы для рисования рамки выделения

Так при рисовании используются DC, а не окна. Окна не являются контейнерами графики в принципе, а все DC равноправны между собой.

Рисование на DC рабочего стола соответствует рисованию на соответствующих окнах. Если раньше у всех окон была общая память для вывода, то с введением DWM в Windows Vista она стала у каждого своя. Если объединение поверхностей для получения финальной картинки работает ещё достаточно быстро, то обратная операция похоже оптимизирована достаточно плохо.

Подробнее про Desktop Window Manager:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff684179(v=vs.85).aspx

The desktop composition feature, introduced in Windows Vista, fundamentally changed the way applications display pixels on the screen. When desktop composition is enabled, individual windows no longer draw directly to the screen or primary display device as they did in previous versions of Windows. Instead, their drawing is redirected to off-screen surfaces in video memory, which are then rendered into a desktop image and presented on the display

Drawing To and Reading From the Screen -- Baaaad!

Lastly, since we're on the redirection topic, one particularly dangerous practice is writing to the screen, either through the use of GetDC(NULL) and writing to that, or attempting to do XOR rubber-band lines, etc. There are two big reasons that writing to the screen is bad:

It's expensive... writing to the screen itself isn't expensive, but it is almost always accompanied by reading from the screen because one typically does read-modify-write operations like XOR when writing to the screen. Reading from the video memory surface is very expensive, requires synchronization with the DWM, and stalls the entire GPU pipe, as well as the DWM application pipe.
It's unpredictable... if you somehow manage to get to the actual primary and write to it, there can be no predictability as to how long what you wrote to the primary will remain on screen. Since the UCE doesn't know about it, it may get cleared in the next frame refresh, or it may persist for a very long time, depending on what else needs to be updated on the screen. (We really don't allow direct writing to the primary anyhow, for that very reason... if you try to access the DirectDraw primary, for instance, the DWM will turn off until the accessing application exits)

DWM.png
DWM.png (15.22 Кб) Просмотров: 1544

Demonx
Бывалый
Бывалый
 
Сообщения: 237
Зарегистрирован: 25.06.2003 (Ср) 0:08
Откуда: Литва/Висагинас

Re: Объяснение визуального бага VB 6 под Windows 7

Сообщение Demonx » 19.03.2013 (Вт) 20:42

как избавиться от этого бага?
Изображение

Filyus
Обычный пользователь
Обычный пользователь
 
Сообщения: 81
Зарегистрирован: 07.07.2011 (Чт) 11:54

Re: Объяснение визуального бага VB 6 под Windows 7

Сообщение Filyus » 27.03.2013 (Ср) 14:36

Demonx писал(а):как избавиться от этого бага?

Делать пока некогда, могу только предложить:
1. Перехватывать GetDC(0) и возвращать не hDC рабочего стола, а hDC главного окна (через GetForegroundWindow), смещать координаты относительно левого верхнего угла окна и левого верхнего угла рабочего стола (через GetDCOrgEx), смещать обратно перед вызовом перехваченной ReleaseDC.
Достоинство: точно будет работать.
Недостаток: приложением не будет рисоваться то, что за пределами его главного окна.
2. Реализовать свои функции рисования, которые будут рисовать на рабочем столе быстрее стандартных. В основном, это функция PatBlt. Функция WindowFromPoint при включенной композиции работает примерно с той же скоростью, так что находите все окна в которых нужно нарисовать, находите их hDC, смещаете координаты GetDCOrgEx, рисуете, смещается обратно и вызываете ReleaseDC.
3. В Windows 8 можно выбрать режим совместимости с Windows Vista SP 2 или ниже, но тогда вместо тёмно-серой рамки будет рисоваться ярко-красная.


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

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

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

    TopList