Приложение 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 о выполняется в собственном потоке, нужно на этапе компоновки подключить библиотеки поддержки многопоточности.
|