Метод OnInitDialog
После того, как метод InitInstance главного класса приложения CFtpViewApp создает объект dlg класса CFtpViewDlg, представляющий диалоговую панель, для него вызывается метод DoModal:
int nResponse = dlg.DoModal();
Этот метод кроме прочего передает диалоговой панели сообщение WM_INITDIALOG. В ответ на сообщение WM_INITDIALOG вызывается метод OnInitDialog, объявленный как виртуальный метод класса CDialog. Обратите внимание, что таблица сообщений класса CFtpViewDlg не содержит макрокоманд для обработки сообщения WM_INITDIALOG. Метод OnInitDialog вызывается непосредственно MFC.
Первоначально метод OnInitDialog был переопределен MFC AppWizard во время создания приложения. Затем мы его изменили, добавив программный код для инициализации органов управления диалоговой панели и инициализации сеанса работы с WinInet. Рассмотрим метод OnInitDialog более подробно.
Сначала вызывается метод OnInitDialog базового класса CDialog. Он выполняет основную работу по инициализации диалоговой панели - загружает соответствующий шаблон диалоговой панели из ресурсов приложения и т. д.:
CDialog::OnInitDialog();
Затем два раза вызывается метод SetIcon, определенный в базовом классе CWnd. Этот метод устанавливает пиктограммы стандартного и уменьшенного размера, которые будут отображаться в случае минимизации диалоговой панели:
SetIcon(m_hIcon,TRUE); // Пиктограмма стандартного размера
SetIcon(m_hIcon,FALSE); // Пиктограмма маленького размера
Первый параметр m_hIcon, передаваемый методам SetIcon, представляет собой индекс пиктограммы IDR_MAINFRAME. Эта пиктограмма загружается конструктором класса CFtpViewDlg, описанным выше.
Далее метод OnInitDialog выполняет инициализацию списка IDC_FTP_LIST, в котором будет отображаться содержимое каталогов сервера FTP.
Для временного использования объявляются несколько переменных - объект rectList класса CRect, структура lv_column типа LV_COLUMN и список строк szColHeader:
// Структура, для описания характеристик колонок списка
LV_COLUMN lv_column;
// Переменная для определения размера списка
CRect rectList;
// Названия для колонок списка
TCHAR szColHeader[COL_NUM][10] = {
_T("Name"),
_T("Length"),
_T("Date"),
_T("Time"),
};
В переменную rectList записывается размер области диалоговой панели, которую занимает список IDC_FTP_LIST. Для этого мы вызываем метод GetWindowRect объекта, управляющего списком. Размеры списка нам потребуются, когда мы будем определять ширину колонок, входящих в список:
m_FtpList.GetWindowRect(&rectList);
Затем мы заполняем поля структуры lv_column. Эта структура определяет характеристики колонки списка. Мы будем ее использовать при создании колонок.
Сначала заполняется поле mask. В него заносится комбинация нескольких констант, определяющих какие поля данной структуры будут иметь значение. Мы указали, что используются четыре поля структуры lv_column - fmt, iSubItem, pszText и cx:
lv_column.mask = LVCF_FMT | // Используется поле fmt
LVCF_SUBITEM | // Используется поле iSubItem
LVCF_TEXT | // Используется поле pszText
LVCF_WIDTH; // Используется поле cx
Поле fmt задает выравнивание по левому краю колонки ее заголовка и текста элементов. Мы выбрали выравнивание по левому краю, записав в это поле значение LVCFMT_LEFT:
lv_column.fmt = LVCFMT_LEFT;
В поле cx заносится ширина колонки. Мы указываем для всех колонок списка одинаковую ширину, разделив на равные части ширину всего списка:
lv_column.cx = (rectList.Width() / COL_NUM) - 1;
Остальные поля структуры lv_column - iSubItem и pszText различаются для каждой колонки. Поэтому мы заполняем их отдельно. Поле iSubItem означает номер колонки списка, а поле pszText - текст его заголовка.
В следующем цикле заполняются последние два поля структуры и метод InsertColumn включает колонку в список. Номера колонок изменяются от 0 до 3, а названия полей берутся из списка строк szColHeader:
// Определяем характеристики колонок списка
for (int i = 0; i < COL_NUM; i++)
{
// Номер колонки
lv_column.iSubItem = i;
// Зааголовок колонки
lv_column.pszText = szColHeader[i];
// Добавляем колонку с заданными свойствами к списку
m_FtpList.InsertColumn(i, &lv_column);
}
Новые колонки добавляются в список с помощью метода InsertColumn, определенного в классе CListCtrl. Этому методу передается номер колонки и заполненная структура lv_column, описывающая добавляемую колонку.
В списке сервера FTP могут фигурировать два типа объектов - каталоги и файлы. Для выделения их в списке им присваиваются различные пиктограммы.
Чтобы в списке можно было отмечать отдельные элементы при помощи пиктограмм, необходимо сформировать список изображений. Для этого в состав библиотеки MFC включен класс CImageList. Метод OnInitDialog создает объект этого класса, представляющий список из двух изображений размером 16 х 16 пикселов и включает в него пиктограммы с изображением каталога (пиктограмма с идентификатором IDI_DIRECTORY) и файла (пиктограмма с идентификатором IDI_FILE):
// Создаем список из двух изображений размера 16 х 16
m_ImageList = new CImageList();
m_ImageList -> Create(16, 16, TRUE, 2, 2);
// Добавляем в список две пиктограммы -
// IDI_DIRECTORY (изображение каталога) и
// IDI_FILE(изображение файла )
m_ImageList -> Add(AfxGetApp()->LoadIcon(IDI_DIRECTORY));
m_ImageList -> Add(AfxGetApp()->LoadIcon(IDI_FILE));
Полученный список изображений выбирается для использования в списке IDC_FTP_LIST с помощью метода SetImageList класса CListCtrl. Первый параметр метода SetImageList содержит указатель на список изображений, а второй определяет их размер. Константа LVSIL_SMALL означает, что данный список изображений будет использоваться при отображении пиктограмм маленького размера:
m_FtpList.SetImageList(m_ImageList, LVSIL_SMALL);
По завершении инициализации списка IDC_FTP_LIST, метод OnInitDialog выводит в поле редактирования IDC_FTP_ADDRESS, адрес сервера FTP. Адрес сервера FTP, который будет использоваться по умолчанию записывается в элемент данных m_FtpAddress класса CFtpViewDlg:
m_FtpAddress = "dials.ccas.ru"; // Сервер FTP “ДиалогНаука”
Для нашего примера мы использовали сервер FTP АО “ДиалогНаука”, который имеет адрес ftp://dials.ccas.ru. Вы можете заменить этот адрес на адрес любого другого сервера FTP по своему усмотрению.
Поле редактирования, предназначенное для ввода адреса сервера, мы связали со строкой m_FtpAddress. Поэтому чтобы вывести ее на экран вызывается метод UpdateData и в качестве параметра ему указывается значение FALSE:
UpdateData(FALSE);
Далее метод OnInitDialog приступает к инициализации сеанса связи с Internet (программного интерфейса WinInet). Создается новый объект класса CInternetSession. В качестве параметров конструктору класса CInternetSession указывается только имя приложения - строка FtpView. Вы можете указать здесь любую другую строку или не использовать этот параметр совсем. Указатель на созданный объект заносится в элемент данных m_InternetSession, принадлежащий классу CFtpViewDlg:
// Создаем сеанс связи с Internet, указываем в качестве
// имени программы-клиента название приложения FtpView
m_InternetSession = new CInternetSession("FtpView");
В случае возникновения ошибки при создании объекта класса CInternetSession мы отображаем на экране соответствующее сообщение и завершаем работу приложения:
if(!m_InternetSession)
{
AfxMessageBox("New Session Error", MB_OK);
OnOK();
}
Если объект класса CInternetSession создан, инициализируем указатель m_FtpConnection, также принадлежащий классу CFtpViewDlg:
m_FtpConnection = NULL;
После того как приложение установит связь с сервером FTP, адрес объекта класса CFtpConnection, представляющего сеанс связи с эти сервером, будет занесен в элемент данных m_FtpConnection.
Метод OnInitDialog возвращает значение TRUE. Это означает, что фокус ввода будет установлен на первый орган управления диалоговой панели (первый орган диалоговой панели можно выбрать в редакторе диалоговой панели, выбрав из меню Layout строку Tab Order).
По завершении работы диалоговая панель отображается на экране и пользователь может с ней работать - изменять адрес сервера FTP, соединятся с ним и просматривать содержимое его каталогов.