Разработка приложений для Internet


Приложение 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.


Содержание раздела