Я реализовал сложную отрисовку фона главного окна и его дочерних статических элементов управления.
На рисунке ниже показано, как это выглядит.
Статические элементы управления имеют SS_NOTIFY
стиль, который важно упомянуть, поскольку определенные вещи происходят, когда пользователь нажимает на них.
На данный момент действия, активируемые при нажатии на них, не актуальны.
Как основное окно, так и статические элементы управления имеют градиентный фон, который был сделан с помощью GradientFill(...)
API.
Верхний баннер главного окна создается серой кистью, а линии сетки — LineTo(...)
а также MoveTo(...)
API.
Карта на оранжевом статическом контроле, а верхний левый логотип EMF
файлы, верхний правый логотип PNG
файл и другие изображения являются растровыми изображениями.
Оранжевый статический элемент управления имеет 4 дочерних статических элемента управления, которые owner drawn
а также есть SS_NOTIFY
стиль.
Это был единственный способ, которым я мог придумать, который позволил мне получить контроль так, как меня просили (если я могу улучшить это, пожалуйста, предложите мне, я приму любое разумное предложение).
Чтобы покрасить оранжевый статический элемент управления, я решил покрасить его фон в WM_CTLCOLORSTATIC
обработчик, а владельцу нарисовать дочерние статические элементы управления в процедуре подкласса.
Уведомления, полученные от дочерних статических элементов управления, также обрабатываются в процедуре подкласса оранжевых статических элементов управления, поскольку я не знал, как переслать их в родительское окно, но опущен, поскольку они также не имеют значения в данный момент.
Я решил предоставить ссылку на демонстрационный проект, вместо того, чтобы сделать этот пост довольно длинным с фрагментами кода.
Я попытался подать демо-заявку как можно меньше и проще.
Я не скупился на комментарии, поэтому считаю, что все хорошо освещено и объяснено в исходном коде.
Если есть еще вопросы, пожалуйста, оставьте комментарий, и я отвечу как можно скорее (обычно сразу или в тот же день, по крайней мере).
Вот ссылка на демонстрационный проект:http://www.filedropper.com/geotermistgrafika_1
/ ================================================= ========= /
Текст ниже в квадратных скобках был первоначальной частью вопроса, но теперь он опущен, так как в проекте были утечки памяти. Приведенная выше ссылка ссылается на улучшенную версию.
[ Обновлено в ответ на комментарий участника xMRi: Эта ссылка должна быть в порядке: http://www.filedropper.com/geotermistgrafika ]/ ================================================= ========= /
Я работаю на Windows XP, используя MS Visual Studio C ++ и чистый Win32 API.
Одна запись: с экспресс-издания VS не имеет редактора ресурсов, файл ресурса и заголовок ресурса были созданы с использованием ResEdit отсюда: http://www.resedit.net/.
Когда я изменяю размер окна, статические элементы управления слегка мерцают.
Я считаю, что в моем коде нет утечек памяти, поэтому я сомневаюсь, что это проблема, но будучи неопытным, я был бы очень признателен, если бы мое предположение можно было как-то подтвердить.
Я думаю, что я правильно справился WM_ERASEBKGND
и я исключил стили CS_VREDRAW
а также CS_HREDRAW
из моего окна класса — поэтому мерцание не должно быть вызвано из-за этого.
Я забыл упомянуть, что мое окно имеет WS_CLIPCHILDREN
стиль, поэтому я упоминаю, что сейчас, в ответ на комментарий ниже, сделанный участником Роджер Роуланд.
Я реализовал двойную буферизацию для обоих обработчиков, чтобы избежать мерцания.
Как я могу изменить код в демонстрационном проекте, чтобы избавиться от мерцания?
Мне нужен совет о том, как оптимизировать оба WM_PAINT
а также WM_CTLCOLORSTATIC
обработчики, поэтому мой код рисования становится более эффективным и быстрым.
Небольшая заметка для второго вопроса:
Я думал улучшить свой код, рисуя всю картинку на фоне главного окна, и поместить прозрачные статические элементы управления поверх той части изображения, которая соответствует фону статических элементов управления.
Таким образом, я бы только вернулся NULL_BRUSH
в моем WM_CTLCOLORSTATIC
обработчик, и делать всю работу в WM_PAINT
,
Я на правильном пути с этой идеей? Может ли это работать?
Спасибо.
С уважением.
Во-первых, ваше приложение чертовски дырявое. Не искали утечек, но большинство из них должно быть в WM_CTLCOLORSTATIC
как вы забыли удалить HBITMAP (используйте эту аккуратную бесплатную http://www.nirsoft.net/utils/gdi_handles.html искать утечки gdi).
Во-вторых, ваш код — это путь к большому. Я заметил, что вы не использовали функции, возможно, потому что вы не знаете, на что они способны. Например, я бы использовал:
void DrawBackground(HDC &hDC, SOMEINFOSTRUCT GradientInfo, LPCTSTR Text);
значительно упростить ваш код.
Во всяком случае достаточно лекций, давайте вернемся к вашей проблеме. В WM_CTLCOLORSTATIC
Вы должны вернуть кисть, вы хотите нарисовать фон с. Теперь вы рисуете фон вручную, используя Bitblt()
, затем верните кисть NULL и программа нарисует ее на уже окрашенном фоне. Вместо того, чтобы красить это самостоятельно, позвольте кисти делать работу.
Просто вместо последнего Bitblt()
использование CreatePatternBrush()
, но тогда вам нужно позаботиться об этой кисти и вот что вы должны сделать:
HBRUSH TempBrush = NULL; //Create global brush
//Some Code....
case WM_CTLCOLORSTATIC:
{
if (TempBrush != NULL)
{
DeleteObject(TempBrush);
TempBrush = NULL;
}
//Let's skip to the end....
GradientFill( MemDC, vertex3, 3, &gTriangle, 1,
GRADIENT_FILL_TRIANGLE );
TempBrush = CreatePatternBrush(bmp);// these 3 line should be at the
//end of every if
DeleteDC(MemDC); // or put them once outside if's
DeleteObject(bmp); // also if you delete HDC first, you don't need to
//unselect hbitmap
}
return (LRESULT)TempBrush;
}
break;
case WM_CLOSE:
{
if (TempBrush != NULL)
{
DeleteObject(TempBrush);
TempBrush = NULL;
}
//.......
Других решений пока нет …