Приложение Parse
В этом разделе мы представим вашему вниманию приложение Parse. Оно использует функцию AfxParseURL для разбора на составные части адресов URL, которые пользователь может вводить в диалоговой панели приложения (рис. 1.3).
Приложение Parse не выполняет соединение с Internet и вы можете его запустить на компьютере, не имеющем ни модема, ни сетевой карты, и не подключенном к сетям Internet и Intranet. Конечно, пользы от такого приложения не много, но мы предлагаем вам с ним поработать, чтобы лучше разобраться со структурой адресов URL.
Рис. 1.3. Приложение ParseURL
Чтобы упростить приложение, мы выбрали для него интерфейс на основе диалоговой панели. Запустите MFC AppWizard, выбрав из меню File строку New. На экране появится одноименная диалоговая панель. Выберите в ней из списка New строку Project Workspace и нажмите кнопку OK. Откроется диалоговая панель New Project Workspace. В качестве типа создаваемого приложения укажите MFC AppWizard (exe) и введите в поле Name имя проекта - Parse. Затем нажмите кнопку Create.
На экране появится первая диалоговая панель MFC AppWizard - MFC AppWizard - Step 1. В ней вы должны выбрать тип пользовательского интерфейса приложения - Dialog based, то есть приложение с главной диалоговой панелью. В принципе, теперь вы можете нажать кнопку Finish и оставить все остальные характеристики приложения по умолчанию. Но чтобы упростить приложение и сделать его исходный текст более доступным для понимания, мы предлагаем вам сначала перейти к следующей панели MFC AppWizard Step 2 of 4 и отключить в ней переключатель About box. При этом MFC AppWizard не будет подключать к приложению информационную диалоговую панель About. За счет этого можно несколько упростить исходные тексты приложения.
После этого, нажмите кнопку Finish, просмотрите информацию о приложении, которая появится в диалоговой панели New Project Information, и нажмите на кнопку OK. MFC AppWizard создаст проект.
Мы уже детально рассматривали шаблон приложения с пользовательским интерфейсом на основе диалоговой панели в 28 томе серии “Библиотека системного программиста”. Поэтому мы сразу приступим к доработке шаблона приложения и не будем останавливаться на исходных текстах, созданных MFC AppWizard.
Сначала загрузите в редактор ресурсов шаблон главной диалоговой панели IDD_PARSEURL_DIALOG приложения Parse. Разместите на этой диалоговой панели пять полей редактирования IDC_EDIT_URL_ADDRESS, IDC_EDIT_SERVICE_TYPE, IDC_EDIT_SERVER_NAME, IDC_EDIT_OBJECT_NAME и IDC_EDIT_PORT_NUMBER. Все поля редактирования кроме IDC_EDIT_URL_ADDRESS сделайте доступными только для чтения. Для этого в панели свойств этих полей Edit Propeties на странице Styles установите переключатель Read-only. Около каждого поля редактирования сделайте соответствующие текстовые подписи URL Address, Service type, Server name, Object name и Port number.
По умолчанию MFC AppWizard создает в диалоговой панели IDD_PARSEURL_DIALOG две кнопки - кнопку OK с идентификатором IDOK и кнопку Cancel с идентификатором IDCANCEL. Кнопка Cancel нам не понадобится вы можете ее удалить. Вместо нее добавьте кнопку Convert, присвоив ей идентификатор IDC_BUTTON_CONVERT.
В листинге 1.1 мы привели фрагмент файла ресурсов приложения Parse, в котором определяется шаблон диалоговой панели IDD_PARSEURL_DIALOG. Ориентируйтесь на него, когда будете создавать эту диалоговую панель.
Листинг 1.1. Фрагмент файла Parse.rc, шаблон диалоговой панели IDD_PARSEURL_DIALOG
//////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_PARSEURL_DIALOG DIALOGEX 0, 0, 241, 210
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "ParseURL"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,184,183,50,14
EDITTEXT IDC_EDIT_URL_ADDRESS,7,27,227,15, ES_AUTOHSCROLL
LTEXT "URL Address",IDC_STATIC,7,15,43,8
EDITTEXT IDC_EDIT_SERVICE_TYPE,7,73,227,15,ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Service type",IDC_STATIC,7,61,40,8
EDITTEXT IDC_EDIT_SERVER_NAME,7,110,227,15,ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Server name",IDC_STATIC,7,97,41,8
EDITTEXT IDC_EDIT_OBJECT_NAME,7,147,227,15,ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Object name",IDC_STATIC,7,135,41,8
EDITTEXT IDC_EDIT_PORT_NUMBER,7,182,52,15, ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Port number",IDC_STATIC,7,170,39,8
PUSHBUTTON "Convert",IDC_BUTTON_CONVERT,115,183,50,14
END
Все идентификаторы, которые создаются автоматически во время редактирования ресурсов приложения, в том числе диалоговой панели IDD_PARSEURL_DIALOG, записываются в файле resource.h. Исходный текст этого файла мы привели в листинге 1.2.
Листинг 1.2. Файл resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by ParseURL.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_PARSEURL_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_EDIT_URL_ADDRESS 1000
#define IDC_EDIT_SERVICE_TYPE 1001
#define IDC_EDIT_SERVER_NAME 1002
#define IDC_EDIT_OBJECT_NAME 1003
#define IDC_EDIT_PORT_NUMBER 1004
#define IDC_BUTTON_CONVERT 1005
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1006
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
После того, как вы завершите подготовку диалоговой панели IDD_PARSEURL_DIALOG, запустите MFC ClassWizard. С его помощью мы привяжем к полям редактирования диалоговой панели новые элементы данных класса CParseURLDlg.
В диалоговой панели MFC ClassWizard перейдите на страницу Member Variables. Выберите в поле Class name имя класса CParseURLDlg и добавьте к нему с помощью кнопки Add Variable пять переменных, привязав их к полям ввода. К полю IDC_EDIT_URL_ADDRESS привяжите переменную m_UrlAddress, к IDC_EDIT_SERVICE_TYPE - m_ServiceType, IDC_EDIT_SERVER_NAME - m_ServerName и к IDC_EDIT_PORT_NUMBER - m_PortNumber. В качестве типа переменных выберите для всех них класс CString. Тогда используя механизм DDX вы легко сможете обмениваться данными между полями редактирования и соответствующими строками.
В исходных текстах приложения MFC ClassWizard модифицирует конструктор и метод DoDataExchange класса CParseURLDlg. В конструкторе класса CParseURLDlg добавляется программный код, выполняющий инициализацию строк, привязанных к полям редактирования диалоговой панели. Как видно из листинга 1.3, соответствующие команды добавляются внутри блока AFX_DATA_INIT.
Листинг 1.3. Фрагмент файла Parse.cpp, конструктор класса CParseURLDlg
CParseURLDlg::CParseURLDlg(CWnd* pParent /*=NULL*/)
: CDialog(CParseURLDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CParseURLDlg)
m_ObjectName = _T("");
m_PortNumber = _T("");
m_ServerName = _T("");
m_ServiceType = _T("");
m_UrlAddress = _T("");
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
К методу DoDataExchange класса CParseURLDlg MFC ClassWizard добавляет методы DDX_Text, фактически осуществляющие обмен данными между полями редактирования диалоговой панели и соответствующими текстовыми строками. Мы привели фрагмент файла Parse.cpp с определением метода DoDataExchange в листинге 1.4.
Листинг 1.4. Фрагмент файла Parse.cpp, метод DoDataExchange класса CParseURLDlg
void CParseURLDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CParseURLDlg)
DDX_Text(pDX, IDC_EDIT_OBJECT_NAME, m_ObjectName);
DDX_Text(pDX, IDC_EDIT_PORT_NUMBER, m_PortNumber);
DDX_Text(pDX, IDC_EDIT_SERVER_NAME, m_ServerName);
DDX_Text(pDX, IDC_EDIT_SERVICE_TYPE, m_ServiceType);
DDX_Text(pDX, IDC_EDIT_URL_ADDRESS, m_UrlAddress);
//}}AFX_DATA_MAP
}
Мы разместили на диалоговой панели IDD_PARSEURL_DIALOG кнопку Convert. Еще раз воспользуйтесь MFC ClassWizard и добавьте к классу CParseURLDlg обработчик сообщений от этой кнопки. Он будет вызываться когда пользователь будет нажимать на кнопку. MFC ClassWizard предложит вам назвать соответствующий метод именем OnButtonConvert. Согласитесь с этим предложением и в таблице сообщений класса CParseURLDlg появится новая макрокоманда:
BEGIN_MESSAGE_MAP(CParseURLDlg, CDialog)
//{{AFX_MSG_MAP(CParseURLDlg)
. . .
ON_BN_CLICKED(IDC_BUTTON_CONVERT, OnButtonConvert)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
Кроме того, в определении класса CParseURLDlg будет добавлено описание метода OnButtonConvert. Мы привели определение класса CParseURLDlg в листинге 1.5.
Листинг 1.5. Фрагмент файла Parse.h, определение класса CParseURLDlg
class CParseURLDlg : public CDialog
{
// Construction
public:
CParseURLDlg(CWnd* pParent = NULL);
// Dialog Data
//{{AFX_DATA(CParseURLDlg)
enum { IDD = IDD_PARSEURL_DIALOG };
CString m_ObjectName;
CString m_PortNumber;
CString m_ServerName;
CString m_ServiceType;
CString m_UrlAddress;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CParseURLDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CParseURLDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnButtonConvert();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
Определение метода OnButtonConvert размещается в файле Parse.cpp вместе с остальными методами класса CParseURLDlg. MFC ClassWizard создает только шаблон метода, который не выполняет никаких действий. Вы должны самостоятельно доработать метод OnButtonConvert, загрузив его в текстовый редактор Microsoft Visual C++. В листинге 1.6 мы привели фрагменты файла Parse.cpp с определением метода OnButtonConvert класса CParseURLDlg.
Листинг 1.6. Фрагмент файла Parse.cpp, метод OnButtonConvert класса CParseURLDlg
void CParseURLDlg::OnButtonConvert()
{
// Получаем адрес, введенный в диалоговой панели
UpdateData(TRUE);
CString sServer; // Имя сервера
CString sObject; // Имя объекта (с каталогами)
INTERNET_PORT nPort; // Номер порта TCP/IP
DWORD dwServiceType;
// Тип сервиса или протокола
// Разбираем адрес URL, записанный в строке m_UrlAddress
if (!AfxParseURL(m_UrlAddress, dwServiceType, m_ServerName,
m_ObjectName, nPort))
{
AfxMessageBox("AfxParseURL Error");
m_ObjectName = "";
m_PortNumber = "";
m_ServerName = "";
m_ServiceType = "";
}
else
{
switch(dwServiceType)
{
case AFX_INET_SERVICE_FTP:
m_ServiceType = "AFX_INET_SERVICE_FTP";
break;
case AFX_INET_SERVICE_HTTP:
m_ServiceType = "AFX_INET_SERVICE_HTTP";
break;
case AFX_INET_SERVICE_GOPHER:
m_ServiceType = "AFX_INET_SERVICE_GOPHER";
break;
case AFX_INET_SERVICE_FILE:
m_ServiceType = "AFX_INET_SERVICE_FILE";
break;
default:
m_ServiceType.Format("%d", dwServiceType);
}
m_PortNumber.Format("%d", nPort);
}
// Выводим полученные значения в диалоговой панелли
UpdateData(FALSE);
}
Для наглядности во время запуска приложения мы выполняем инициализацию поля ввода адреса URL, записывая в него строку http://host:80/bin/programm/main.htm. Этот адрес содержит все возможные элементы - тип протокола http, имя сервера host, номер порта 80, а также путь и имя объекта /bin/programm/main.htm, на который и указывает данный адрес URL.
Соответствующий программный код, инициализирующий строку адреса надо добавить к методу OnInitDialog класса CParseURLDlg. Мы привели исходный текст этого метода в листинге 1.7.
Листинг 1.7. Фрагмент файла Parse.cpp, метод OnInitDialog класса CParseURLDlg
BOOL CParseURLDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// . . .
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// Инициализируем поле адреса URL
m_UrlAddress = "http://host:80/bin/programm/main.htm";
// Отображаем строку m_UrlAddress в диалоговой панели
UpdateData(FALSE);
return TRUE;
}
Теперь в исходный текст приложения внесены все необходимые изменения. Вы можете построить проект и запустить приложение. На экране появится диалоговая панель ParseURL, внешний вид которой мы уже приводили ранее на рисунке 4.4.
Изначально в поле URL Address отображается адрес http://host:80/bin/programm/main.htm, который мы взяли в качестве примера. Вы можете изменить его по своему усмотрению - поменять тип протокола обмена, имя сервера, путь и имя объекта и номер порта. Вы даже можете попытаться ввести неправильный адрес, не соответствующий формату адресов URL.
Нажмите кнопку Convert. Приложение разберет введенный вами адрес URL на составные части и выведет их в других полях диалоговой панели. Так в поле Service type будет показан тип сервиса (протокола обмена). Это может быть либо текстовая строка, либо число. В поле Server name вы увидите имя сервера, а в поле Object name - имя объекта, включая путь. Если в адрес URL включен номер порта, то он будет показан в поле Port number.
Если вы введете в поле адреса URL неправильную строку, то на экране появится сообщение об ошибке, а поля Service type, Server name, Object name и Port number будут очищены.
Когда вы закончите экспериментировать с разбором различных адресов URL завершите приложение. Для этого достаточно нажать кнопку OK.