Главная arrow С++ (часть 2) arrow Код программы WinDL

Код программы WinDL

Приложение WinDL состоит из двух основных частей. Первая — это код для класса Download, описанного ранее. Вторая — код для реализации GUI-интерфейса, приведенный в листинге 5.4. Назовите этот файл windl.cpp.
Листинг 5.4. Утилита загрузки файлов из Интернета, использующая GUI-интерфейс |
// WinDL: утилита загрузки файлов из Интернета,
// использующая GUI-интерфейс.
#include <windows.h>
#include <commctrl.h>
#include <cstring>
#include <cstdio>
# include " windl.h"
#include <process.h>
#include "dl.h"
const int URL_BUF_SIZE = 1024;
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK DialogFunc(HWND. UINT, WPARAM, LPARAM);
void showprogress(unsigned long total, unsigned long part); void resetprogress();
unsigned _stdcall dlstarc(void * reload);
ффХ szWinName[] = "Dovmload"; // имя класса окна
HINSTANCE hlnst; // дескриптор экземпляра
gjfljD hwnd; // дескриптор главного окна
J^JTJD hProgWhd;     // дескриптор индикатора (progress bar)
HANDLE hThrd =0;    // дескриптор потока unsigned long Tid; // идентификатор (ID) потока
// Счетчики процесса загрузки, int percentdone = 0; int oldpercentdone = 0;
// Небольшая структура для передачи информации в функцию dlstartO struct Thrdlnfo {
char *url;    // указатель на строку с URL
int reload;       // флаг reload
HWND hPBStart; // дескриптор кнопки Start
};
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR IpszArgs, int nWinMode)
{
MSG msg; WNDCLASSEX wcl; INITCOMMONCONTROLSEX cc;
// Определение класса окна. wcl.cbSize = sizeof(WNDCLASSEX);
wcl.hlnstance = hThisInst; // дескриптор этого экземпляра
wcl.IpszClassName = szWinName; // имя класса окна wcl.lpfnWndProc = WindowFunc;    // функция обработки окна wcl.style =0; // текущий стиль
wcl.hlcon = Loadlcon(NULL,  IDI_APPLICATION); // большая пиктограмма wcl.hlconSm = NULL; // использует маленькую версию большой пиктограммы wcl.hCursor = LoadCursor(NULL, IDC_ARROW);    // стиль курсора
wcl.IpszMenuName = NULL; // без меню
wcl.cbClsExtra = 0; // без дополнительной памяти окна (no extras) wcl.cbWndExtra = 0;
wcl.hbrBackground = NULL; //не используется
// Регистрирует класс окна.
if(!RegisterClassEx(&wcl)) return 0;
// Создает главное окно, которое будет невидимым, hwnd = CreateWindow(
szWinName, // имя класса окна
"File Downloader", // заголовок
0, // без стиля
0, 0, 0, 0, // без размеров
NULL, // без родительского окна
NULL, // без меню
hThisInst, // дескриптор экземпляра
NULL // без дополнительных аргументов
);
hlnst = hThisInst; // сохраняет текущий дескриптор экземпляра
// Инициализирует стандартные элементы управления. Это // необходимо индикатору выполнения процесса. cc.dwSize = sizeof(INITCOMMONCONTROLSEX); cc.dwICC = ICC_PROGRESS_CLASS; InitCommonControlsEx(&cc);
// Показывает свернутое окно. ShowWindow(hwnd,  SW_SHOWMINIMIZED);
// Создает диалоговое окно загрузки файла.
DialogBox(hlnst,   "DLDB", hwnd,   (DLGPROC) DialogFunc);
// Создает цикл обработки сообщений.
«hile(GetMessage(&msg, NULL, О, О)) {
TranslateMessage(&msg); // транслирует сообщения от клавиатуры DispatchMessage(&msg); // возвращает управление Windows
}
return msg.wParam;
}
// функция обработки окна.
^RESULT CALLBACK WindowFunc (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)  { case WM_DESTROY:
PostQuitMessage(O); // завершает программу
break; default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
// Диалоговая функция загрузчика.
BOOL CALLBACK DialogFunc(HWND hdwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
// Переменная url инициализируется с конкретным URL-адресом // только для демонстрации, static char url[URL_BUF_SIZE] =
"http://www.osborne.com/products/0072226803/0072226803_code.zip";
static Thrdlnfo ti;
switch (message)  { Case WM_INITDIALOG:
// Инициализирует edit box (поле редактирования) с URL-адресом. SetDlgltemText(hdwnd. IDD_EB1, url);
// Создает progress bar (индикатор выполнения процесса). hProgWnd = CreateWindow(PROGRESS_CLASS,
WS_CHILD I WS_VISIBLE | WS_BORDER,     '
4,  64,  320,  12,
hdwnd, NULL, hlnst, NULL);
// Устанавливает величину приращения равной 1. SendMessage(hProgWnd, PBM_SETSTEP, 1, 0);
return 1; case WM_COMMAND:
switch(LOWORD(wParam))  { case IDCANCEL:
EndDialog(hdwnd, 0) ; PostOuitMessage(0);
return 1;
case IDD_START: // начинает загрузку // Устанавливает поле position в 0. SendMessage(hProgWnd, PBMJSETPOS, 0, 0) ;
// Получает URL из edit box.
GetDlgltemText(hdwnd,  IDD_EB1, url, URL_BUF_SIZE); ti.url = url;
// Получает статус загрузки (состояние переключателя). ti.reload = SendDlglterriMessage(hdwnd, IDD_CB1,
BMjGETCHECK,  0.  0);
// Получает дескриптор кнопки Start. ti.hPBStart = GetDlgltem(hdwnd, IDD_START);
// Переустанавливает счетчики выполнения процесса, гesetprogress();
// Запускает поток загрузки, if(IhThrd)
hThrd = (HANDLE) _beginthreadex(NULL, 0, dlstart, (void *) &ti, 0,  (unsigned *) &Tid);
return 1;
}
)
return 0;
}
// Показывает степень выполнения в progress bar. Вызывается // функцией download () .
void showprogress(unsigned long total, unsigned long part)    {
percentdone = (part*100)/total;
if(percentdone > oldpercentdone) {
for(int i= oldpercentdone; i < percentdone; i++)  { // Сдвигает показания индикатора progress bar. SendMessage(hProgWnd, PBNL.STEPIT, 0, 0);
}
oldpercentdone = percentdone;
}
)
// Переустанавливает счетчики выполнения процесса, void resetprogress() {
percentdone = 0;
oldpercentdone = 0;
}
Ч Потоковая функция (точка входа потока), начинающая загрузку.
^signed _stdcall dlstart(void * param)  {
Thrdlnfo *tip = (Thrdlnfo *) param;
11 Делает кнопку Start недоступной. EnableWindow(tip->hPBStart, 0) ,-
try {
if(tip->reload == BST_CHECKED)
Download::download(t ip->ur1. true. showprogress); else
Download::download(tip->url, false, showprogress); } catch(DLExc exc) { MessageBox(hwnd, exc.geterr(),
"Download Error", MB_OK);
}
// Делает доступной кнопку Start. EnableWindow(tip->hPBStart, 1);
CloseHandle(hThrd); // закрывает дескриптор потока hThrd =0; // делает дескриптор потока неактивным return 0;
}
WinDL применяет файл ресурса, приведенный в листинге 5.5.
Листинг 5.5. Файл ресурса для загрузчика файлов из Интернета
#include <windows.h> #include "windl.h"
DLDB DIALOGEX 18,  18,  164,  100 CAPTION "Download a file"
STYLE DS_MODALFRAME | WS_POP | WS_CAPTION | WS_SYSMENU I WS_VISIBLE
{
PUSHBUTTON "Start",  IDD_START, 42,  80,  30,  14 PUSHBUTTON "Cancel",  IDD_START, 42,  80,  30,  14
CTEXT "Download Progress", IDD_TEXT2, 2, 40, 160, 12
CTEXT "Enter URL",  IDD_TEXTl,  2,  16,  160,  12
EDITTEXT IDD_EB1,  2,  1,  160,  12,  ES_LEFT | WS_CHILD |
WS_VISIBLE I WS_BORDER | ES_AUTOHSCROLL
AUTOCHECKBOX "Reload",  IDD_CB1,  62,  56,  36,  14
}
файлу ресурса и коду программы требуется заголовочный файл windl.h, Приведенный в листинге 5.6.
(ТЁтинг 5.6. Заголовочный файл windl.h
#define IDD_START        100
Idefine IDD_CB1 200
#define IDD_EB1 300
#define IDD_TEXT1 401 fdefine IDD_TEXT2        402
Для компиляции программы WinDL следует создать проект, содержащий следующие файлы:
dl.cpp
windl.cpp
windl.rc
Заголовочные файлы dl.h и windl.h также должны быть доступны. Не забудьте связать вашу программу на этапе компоновки с библиотеками wininet.lib и comctl32.1ib (библиотека comctl32.1ib нужна для индикатора выполнения загрузки). И последнее, поскольку функция download о выполняется в собственном потоке, нужно на этапе компоновки подключить библиотеки поддержки многопоточности.