Здравствуйте! Сегодня мы с вами напишем свой класс progress bar’a, который вы потом сможете использовать в своих проектах.
Для начала я вам скажу, что вы научитесь за этот урок:
- Загружать рисунки ( из ресурсов/файлов )
- Выводить рисунки
- Работа с классами
- Работа с таймерами
Вот и все (. Далее нам нужно сформировать список функций, которые будет использовать наш контролл:
- Задание размеров
- Задание положения
- Задание рисунка-загрузки
- Перерисовка контролла
- Увеличение количества процентов
- Получение поличества процентов
Думаю, все.
Давайте теперь продумаем работу:
Создаем объект прогресс бара. После создания хендла окна вызываем методы, с помощью которых мы настроим наш прогресс бар( размеры, расположение, рисунки ). После этого вызываем метод инициализации, там мы будет грузить рисунки задавать начальное количество процентов и т.д.. Далее дописываем метод перерисовки контролла в сообщение WM_PAINT.
Ну что же, приступим к объявлению класса. Создаем новый файл: CModProgressBar.h.
Вот его код:
#ifndef _CMODPROGRESSBAR_H_ #define _CMODPROGRESSBAR_H_
class CModProgressBar { private: int barSizeX; int barSizeY; int barPosX; int barPosY;
int barPercent; BITMAP bitmap; char *setLoadingPict; int drawPixels; HBITMAP progressLoading; public: CModProgressBar(); ~CModProgressBar(); int getPercent() {return barPercent;}; bool setBarSize( int x, int y ); bool setBarPos( int x, int y ); bool setBarPercent( int percent ); bool setLoadingPicture( char *dest ); bool renderBar( HWND hWnd, HINSTANCE hInst ); bool renderBar( HWND hWnd, HINSTANCE hInst, HDC dc ); };
#endif
|
Все, базовую часть работы сделали. Приступим к основному, реализации функций-членов нашего класса. Для этого создайте новый файл CModProgressBar.cpp, в нем мы и будем реализировать все функции. В самом начале нужно подключить наш заголовочный файл с классом:
#include "stdafx.h" #include "CModProgressBar.h"
|
Первое, что нужно сделать, это реализовать конструктор и деструктор. В них мы зададим переменным-членам класса стандартные( начальные ) значения:
CModProgressBar::CModProgressBar() { barSizeX = 100; barSizeY = 20; barPosX = 10; barPosY = 10; setLoadingPict = ""; barPercent = 0; };
CModProgressBar::~CModProgressBar() { };
|
Далее начнем с размера прогресс бара. Здесь все просто:
bool CModProgressBar::setBarSize( int x, int y ) { barSizeX = x; barSizeY = y; return true; };
|
Тепер задаем положения относительно нашего окна:
bool CModProgressBar::setBarPos( int x, int y ) { barPosX = x; barPosY = y; return true; };
|
Ну а далее все похоже( кроме основной функции – рендера бара ):
bool CModProgressBar::setBarPercent( int percent ) { barPercent = percent; return true; };
|
Рисунок загрузки:
bool CModProgressBar::setLoadingPicture( char *dest ) { setLoadingPict = dest; return true; };
|
Теперь напишем основную функцию, она будет перепросчитывать заданные ей проценты под длину прогресс бара и отрисовывать картинку:
bool CModProgressBar::renderBar(HWND hWnd, HINSTANCE hInst) { progressLoading = (HBITMAP)LoadImage( hInst, setLoadingPict, IMAGE_BITMAP, 0,0, LR_LOADFROMFILE );
HDC appDC = GetDC( hWnd ); HDC progressLoadingDC = CreateCompatibleDC( appDC );
SelectObject( progressLoadingDC, progressLoading ); GetObject( progressLoading , sizeof( BITMAP ), &bitmap );
int drawPixels = ( barPercent * bitmap.bmWidth ) / 100; BitBlt( appDC, barPosX, barPosY, drawPixels, barSizeY, progressLoadingDC, 0,0, SRCCOPY ); ValidateRect( hWnd, NULL );
DeleteDC( progressLoadingDC ); DeleteDC( appDC );
return true; };
|
СОВЕТ
Внимание! Не забывайте смотреть в MSDN, там можно найти очень много полезной информации.
|
Теперь переписываем последнюю функцию, только с учетом того, что будем рисовать на заданном DC.( Используется, при получении сообщения WM_PAINT ).
bool CModProgressBar::renderBar( HWND hWnd, HINSTANCE hInst, HDC dc ) { HBITMAP progressLoading = (HBITMAP)LoadImage( hInst, setLoadingPict, IMAGE_BITMAP, 0,0, LR_LOADFROMFILE ); HDC progressLoadingDC = CreateCompatibleDC( dc ); SelectObject( progressLoadingDC, progressLoading ); GetObject( progressLoading , sizeof( BITMAP ), &bitmap ); drawPixels = ( barPercent * bitmap.bmWidth ) / 100; BitBlt( dc, barPosX, barPosY, drawPixels, barSizeY, progressLoadingDC, 0,0, SRCCOPY ); ValidateRect( hWnd, NULL ); DeleteDC( progressLoadingDC );
return true; };
|
Вот и все! Мы реализовали все нужные функции нашего контролла… Хотя назвать наш прогресс бар контроллом тяжело, он не отсылает/принимает никаких сообщений( разве, только, перерисовку ). Теперь попытаемся использовать его на практике. Я использовал этот прогресс бар для вывода количества процентов набранной строки. Но это уже выходит за рамки проекта, и вы увидите эту реализацию на следующем проекте( по которому будет статья ).
А сейчас мы просто будем увеличивать проценты по таймеру. Создайте новый проект, если хотите. Подключите к нему .h && .cpp файлы.
Теперь создаем в главном .cpp файле объект класса нашего прогресс бара. Создавать нужно глобально( в самом начале, чтобы было доступно всем функциям );
Теперь, после создания нашего главного окна:
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
|
Проинициализируем наш прогресс бар:
bar->setBarPos( 200, 150 ); bar->setBarSize( 100, 15 ); bar->setLoadingPicture( "loading.bmp" ); bar->renderBar( hWnd, hInst );
|
Теперь установим таймер( идентификатор его «1», но посколько будем использовать только один таймер в приложении – мы не будем проверять от какого пришло сообщение), который каждые пол секунды будет посылать сообщение WM_TIMER и там мы уже будем отрисовывать.
SetTimer( hWnd, 1, 500, NULL );
|
Теперь идем к функции WndProc. Создайте в самом начале переменную:
Будем использовать ее, при увеличении процентов.
Далее, в конструкции «разбора» сообщений находим прием сообщения WM_PAINT и дописываем прорисовку:
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); bar.renderBar( hWnd, hInst, hdc ); EndPaint(hWnd, &ps); break;
|
Ну и последнее! Допишите обработку сообщения WM_TIMER:
case WM_TIMER: temp1 = bar.getPercent(); bar.setBarPercent( temp1+5 ); bar.renderBar( hWnd, hInst ); break;
|
И долгожданный конец! Начинаем билд и запускаем программу. (
Вот вам пару скринов:



Конечно, в этом контроле много недостатков. Например, нету проверки на превишение границы процентов( чтобы не более 100% было ), но это уже работа
для вас! Желаю вам удачи во всем!
Тысленко Максим (Ockonal)
29.06.2008