Здравствуйте.
Делаю простое GUI на GDI+. Создал окно WC_STATIC с стилем WS_POPUP | SS_NOTIFY и в нем отрисовываю пару кнопок на GDI+
В сообщении WM_MOUSEMOVE просчитываю над какой кнопкой находится мышь, меняю картинку, если мышка над кнопкой и перерисовываю окно.
Если начать быстро двигать мышкой по кнопкам, при перерисовке окна загрузка CPU подымается до 20%. Хотелось бы оптимизировать этот показатель. Может кто ни будь подскажет секреты при создании окон для использования одного лишь GDI+ без других контролов, Или может по другому сообщения обрабатывать от этого окно... Не нашел как их либо вразумительных ответов в инете по этому вопросу.
А как кнопки ищешь? GraphicsPath.IsOutlineVisible? Сейчас посмотрел, тоже при быстром движении мыши до 20-30% проц занимается, но у меня просто поиск отрисованных графических объектов. Видать такая особенность GDI+.
Здравствуйте, Serpuh, Вы писали:
S>А как кнопки ищешь? GraphicsPath.IsOutlineVisible? Сейчас посмотрел, тоже при быстром движении мыши до 20-30% проц занимается, но у меня просто поиск отрисованных графических объектов. Видать такая особенность GDI+.
А меня свой класс виджета. У виджета задан прямоугольник. И просто перебираю все виджеты над которым мышь, если найден, останавливаю цикл поиска.
Но это я уже протестировал. Оставлял поиск, но убирал перерисовку — нагрузка 0-1%. Возвращаю перерисовку — опять при движении мышки 17-20%.
Здравствуйте, AlexBP, Вы писали: ABP>Но это я уже протестировал. Оставлял поиск, но убирал перерисовку — нагрузка 0-1%. Возвращаю перерисовку — опять при движении мышки 17-20%.
Перерисовка всегда была дорогая в GDI+. Так что это нормально. Просто интересно, а почему тебя заботит такой локальный момент с загрузкой процессора?
S>Перерисовка всегда была дорогая в GDI+. Так что это нормально. Просто интересно, а почему тебя заботит такой локальный момент с загрузкой процессора?
Думал может где то что то упустил.
Похожие приложения не так грузят CPU. Возможно они не на GDI+ сделаны.
Посмотрел некоторые программы с нестандартным GUI и лаунчеры для игр. Максимум они грузят на 2-3%
А какая тогда альтернатива может быть для разработки графического GUI? Direct2D не подойдет, так как хотелось бы поддержку XP.
А вот интересно что Qt использует? Тоже GDI+?
Здравствуйте, rean, Вы писали:
ABP>>В сообщении WM_MOUSEMOVE просчитываю над какой кнопкой находится мышь, меняю картинку, если мышка над кнопкой и перерисовываю окно.
R>Видимо какой-то баг в обработке сообщений.
R>1. Очень похоже, что вы перерисовываете кнопку на каждый пиксел перемещения мышки. Таким образом, проход мышки под кнопкой будет сопряжен постоянной перерисовкой, пока мышка в движении.
Перерисовываю только тогда когда изменяется состояние кнопки.
R>2. Не понятно, для чего перерисовывать всё окно. В Win32 есть механизм отсечения, да и просто можно же определить, что именно стоит перерисовать, не затрагивая остальное.
Перерисовываю не все окно, а регион виджета.
С помощью программы Dependency Walker заметил, что Qt использует Windows GDI (gdi32.dll), а не GDI+. Значит GDI быстрее чем GDI+, или все же дело в обработке сообщений от окна
ABP>Посмотрел некоторые программы с нестандартным GUI и лаунчеры для игр. Максимум они грузят на 2-3% ABP>А какая тогда альтернатива может быть для разработки графического GUI? Direct2D не подойдет, так как хотелось бы поддержку XP.
WTL, возможно, в некоторых случаях HTMLayout.
ABP>А вот интересно что Qt использует? Тоже GDI+?
Совет. Если хотите нормальный быстрый UI на win/C++, забудьте про GDI+, это АД. А также желательно забыть про QT и WPF/xaml. Написать контрол с нормальным биндингом на WTL не сильно сложнее, чем на любом из вышеперечисленных фреймворков, а по пользовательскому восприятию это обычно в разы лучше за счет использования стандартных контролов системы, где сценарии использования (поведение контрола, хоткеи и прочее) проработаны на порядок детальнее, чем в любом другом варианте.
AS>Совет. Если хотите нормальный быстрый UI на win/C++, забудьте про GDI+, это АД. А также желательно забыть про QT и WPF/xaml. Написать контрол с нормальным биндингом на WTL не сильно сложнее, чем на любом из вышеперечисленных фреймворков, а по пользовательскому восприятию это обычно в разы лучше за счет использования стандартных контролов системы, где сценарии использования (поведение контрола, хоткеи и прочее) проработаны на порядок детальнее, чем в любом другом варианте.
WTL использует обычные контролы виндовс. У нас в GUI контролы не используются. Из WinAPI только создание окна и инъекция в GUI событий мышки. GUI имеет несколько платформ отрисовки — DirectX, OpenGL... Теперь хотим его прикрутить к GDI+. Вот я и пытаюсь понять — при перерисовке проблема в GDI+ или в обработке сообщений от окна.
Здравствуйте, rean, Вы писали:
ABP>>С помощью программы Dependency Walker заметил, что Qt использует Windows GDI (gdi32.dll), а не GDI+. Значит GDI быстрее чем GDI+, или все же дело в обработке сообщений от окна
R>Сейчас все, что можно, внутри винды использует видеокарту, даже GDI. Потери времени могут быть только на обвязку и инициализации. А их можно и там и там вынести за код отрисовки. Сейчас лучше всего рисовать через Direct2D. Vista+. Если же нужно очень качественно рисовать наклонные линии, рекомендую Antigrain.
R>Что именно у вас не так, не понятно. Попробуйте логгировать отрисовку и потом найти узкие места с помощью Performance Counters. Весь возможный код инициализации, включая загрузку картинок и шрифтов, выносите за пределы кода отрисовок. Если все-равно все кажется неоптимальным, можно кешировать целые куски изображения и быстро кидать их по BitBlt.
R>PS. У меня на достаточно древнем ноутбуке Все окно Firefox при изменении размера окна и полной перерисовки жрет меньше одного ядра (30% CPU). Так что ищите у себя баг или неоптимальное использование ресурсов. Не должно быть так.
Инициализация в отрисовке ) нет конечно.
Про Direct2D уже сказал выше. Для GUI уже подключена платформа DirectX — 9 версия работает и в XP.
Кешировать нет смысла, когда перерисовывается только необходимый регион.
Здравствуйте, AlexBP, Вы писали:
ABP>Делаю простое GUI на GDI+. Создал окно WC_STATIC с стилем WS_POPUP | SS_NOTIFY и в нем отрисовываю пару кнопок на GDI+
А почему статик, а не нормальный диалог? ABP>Если начать быстро двигать мышкой по кнопкам, при перерисовке окна загрузка CPU подымается до 20%. Хотелось бы оптимизировать этот показатель. Может кто ни будь подскажет секреты при создании окон для использования одного лишь GDI+ без других контролов, Или может по другому сообщения обрабатывать от этого окно... Не нашел как их либо вразумительных ответов в инете по этому вопросу.
А что там делается такого через GDI+, что нельзя сделать через GDI?
У меня в подписи как раз есть примерчик с нестандартными кнопками, используется GDI, причём состояние(перерисовка) кнопки меняется постоянно по таймеру, ничего не тормозит.
Общий принцип такой:
1. снимаем с контекста байтовый массив, через GetDIBits
2. делаем обработку над массивом. Это обычная память, всё работает быстро.
3. заливаем SetDIBitsToDevice.
Т.о. с самой видеопамятью работают только две простые функции.
Здравствуйте, AlexBP, Вы писали:
ABP>Здравствуйте. ABP>Делаю простое GUI на GDI+. Создал окно WC_STATIC с стилем WS_POPUP | SS_NOTIFY и в нем отрисовываю пару кнопок на GDI+ ABP>В сообщении WM_MOUSEMOVE просчитываю над какой кнопкой находится мышь, меняю картинку, если мышка над кнопкой и перерисовываю окно. ABP>Если начать быстро двигать мышкой по кнопкам, при перерисовке окна загрузка CPU подымается до 20%. Хотелось бы оптимизировать этот показатель. Может кто ни будь подскажет секреты при создании окон для использования одного лишь GDI+ без других контролов, Или может по другому сообщения обрабатывать от этого окно... Не нашел как их либо вразумительных ответов в инете по этому вопросу.
На текущем проекте куча ЮИ (самописного, постепенно уходим в сторону стнадартных контролов) на GDI+. Никаких сверхъестественных тормозов.
1. Если еще не пробовали в релизе, проверте, часто дебаг тормозит в самых неожиданных местах.
2. Если и там тормоза, проследите за сообщениями перерисовки (WM_PAINT, WM_ERASEBACKGROUND) если приходят когда не должны (т.е. стейт не меняется) -- ищите косяк.