Дипломная (вкр): Разработка программного продукта обеспечивающего экспорт спецификации из приложения PartList

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Рисунок 4.7

Для элемента формы типа «List Control», с идентификатором ресурса «IDC_LIST1» определим три обработчика следующих сообщений: «LVN_ITEMCHANGED», «LVN_DELETEITEM», «LVN_ITEMACTIVATE». Первый будет вызываться при выборе элемента, рассматриваемого объекта. Второй при его удалении. Третий при двойном щелчке мышкой по элементу. Для их добавления, необходимо щёлкнуть правой кнопкой мыши по рассматриваемому элементу, в окне редактора форм, и в появившемся меню выбрать «Add Event Handler». В выведенном окне (Рисунок 4.8): выбрать сообщение; указать класс (в данном случае «CXMLConverterDlg»), в который будет добавлена функция; ввести имя добавляемого метода в поле с названием «Function handler name» или оставить предложенное по умолчанию. После выполнения описанных действий щёлкнуть по кнопке «Add and Edit».

Рисунок 4.8

В рассматриваемом элементе формы должны отображаться три столбца. Для определения их количества, размеров и имён заголовков напишем следующий фрагмент программного кода.

CListCtrl *pList = (CListCtrl*) GetDlgItem(IDC_LIST1);>InsertColumn(0,_T("Полный путь к xml-файлу"),0,370,-1);>InsertColumn(1,_T("Статус"),0,100,-1);>InsertColumn(2,_T("Состояние"),0,100,-1);

Здесь, с помощью функции GetDlgItem( ) получаем указатель на оконный элемент с идентификатором «IDC_LIST1». Метод InsertColumn() создаёт колонку. В него в качестве параметров передаются: порядковый номер, название, положение текста (0 означает, что текст будет выравниваться по левому краю), ширина, связь с другими колонками (если значение -1, связи нет). Макрос _T( ) применяется для преобразования строки в Unicode. Рассмотренный фрагмент кода необходимо поместить в виртуальную функцию OnInitDialog( ), которая вызывается Windows при инициализации диалогового окна [6].

Данные выводятся в «IDC_LIST1» с помощь функций: InsertItem( ) и SetItem( ). Первый метод используется для добавления элементов в главный (первый) столбец. Второй для добавления элементов в дочнрние столбцы. В качестве параметра в каждую из функций передается указатель на структуру типа «LV_ITEM». Которая содержит переменные определяющие: номер (позицию) элемента в строке, номер столбца, выводимый текст, максимальную длину выводимой строки. Структура инициализируется перед вызовом функций: InsertItem() и SetItem() [6]. Демонстрационный пример кода представлен ниже.

CListCtrl *pList = (CListCtrl*) GetDlgItem(IDC_LIST1);_ITEM lvitem;.mask = LVIF_TEXT;.iItem = 0;.iSubItem = 0;.pszText = str.GetBuffer();.cchTextMax = lstrlen(str);>InsertItem(&lvitem);.iSubItem = 1;.pszText = _T("Не выполнено");.cchTextMax = lstrlen(_T("Не выполнено"));

pList->SetItem(&lvitem);

Флаг «LVIF_TEXT» разрешает вывод текста. Переменная str строкового типа CString, который является классом входящем в MFC и предоставляет широкие возможности работы со строкой. Переменная данного типа является динамической, то есть память под нее выделяется по мере необходимости. Так как переменная pszText, структуры lvitem, должна присвоить указатель, адресующий статический блок памяти, необходимо сделать его таковым. Для этого применяется метод класса CString именуемый GetBuffer() [6].

Чтобы считать данные из элемента типа «List Control», нужно заменить в рассмотренном коде вызов функции InsertItem() на GetItem(). После её выполнения в переменной str окажется текст требуемой ячейки.

Чтобы удалить необходимую строку, используют функцию DeleteItem(), как показано ниже.

CListCtrl *pList = (CListCtrl*) GetDlgItem(IDC_LIST1);

pList->DeleteItem(m_nSelectItem);

Где m_nSelectItem - порядковый номер удаляемой строки. Весь элемент «List Control» очищают с помощью метода DeleteAllItems().

Для ввода полного пути к преобразуемому xml-файлу, воспользуемся стандартным диалоговым классом CFileDialog, предоставляемым MFC. Объявим переменную типа этого класса. Определим значения три, которые будут передаваться его конструктору. Нас интересуют первый и третий атрибут. Первый, определяет, будет ли диолог открывать файл или напротив его сохранять. Второй установим в 0. Третий, указывает, какого типа файлы будут видны в диалоге. Для запуска построения модального диалогового окна открытия файла воспользуемся функцией DoModal( ). Данный метод возвратит управление основному окну приложения только после закрытия им вызванного.

То есть, пользователь не сможет обратится к главному окну, пока не закроет дочернее. Код реаализующий описанные события представлен ниже.fdialog(TRUE,0,_T("*.xml"));

fdialog.DoModal();

Для выбора директории в которую будут сохраняться pdf-файлы, воспользуемся стандартным диалогом Windows. Для этого объявим структуру BROWSEINFO, присвоим переменным, принадлежащем ей, значения, как показано ниже.

wchar_t sDir[512];brinfo;.hwndOwner = 0;.pidlRoot = 0;.pszDisplayName = sDir;.lpszTitle =_T("Выберите папку для вывода pdf-файлов");.ulFlags = BIF_RETURNONLYFSDIRS;.lpfn = 0;

brinfo.lParam = 0;

Для вывода диалогового окна воспользуемся функцией SHBrowseForFolder(&brinfo). Которая возвращает значение типа LPITEMIDLIST. Используя переменную рассмотренного типа и функцию SHGetPathFromIDList() получим путь к выбранной пользователем папке. Пример представлен ниже.pDirList = SHBrowseForFolder(&brinfo);(pDirList,sDir);

В результате будет выводится диалог представленный на рисунке 4.9.

Рисунок 4.9

Для того, чтобы сделать не активными кнопки программы необходимо воспользоваться функциями: GetDlgItem() и EnableWindow(). Первая возврвщает указатель на объект. Вторая делает его пассивным, либо активным, в зависимости от значений FALSE или TRUE, соответственно. Применение этих функций продемонстрированно ниже.

GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);

Для предусмотрения возможности ввода количества отступов до и после раздела в генерируемой спецификации, создадим с помощью редактора форм диалоговое окно. Для этого в меню «Resource View» (Рисунок 4.4) нужно щёлкнуть правой кнопкой мыши по элементу «Dialog» и выбрать «Add Resource». В появившемся окне (Рисунок 4.10) выбрать «Dialog» и щёлкнуть «New». В результате в проект будет добавлен новый шаблон диалога. После выполнения ряда действий, принципы проведения которых были описаны ранее, получется диалоговое окно представленное на рисунке 4.11.

Рисунок 4.10

Рисунок 4.11

После создания формы диалога, необходимо добавить для нее класс в проект. Для этого необходимо щёлкнуть правой кнопкой мыши по форме и в появившемся контекстном меню выбрать «Add Class». В выведенном на экран окне указать имя создаваемого класса «CSetting» в поле «Class name». В качестве базового класса, методы которого будут наследоваться, оставить предложенный по умолчанию CDialog. Щелкнуть «Finish». При добавлении событий для элементов формы, их обрабочики будут помещаться в определённый для них класс Setting. То есть, в только что созданный. Далее неообходимо указать заголовочный файл нового диалога в cpp-файле основного диалога. Затем внести объявление класса в виде записи «class CSetting» в заголовочный файл класса CXMLConverterDlg. Для вызова окна представленного на рисунке 4.11 при щелчке мышкой по кнопке в главном диалоге, необходимо внести в обработчик соответствующего события код представленный ниже.*pSitting = new CSitting();>DoModal();[] pSitting;

Для того, чтобы считывать и хранить значения вносимые в элемент «Edit Controll» необходимо добавить переменную. Для этого в редакторе форм необходимо щёлкнуть правой кнопкой мыши по нужному объекту, выбрать в меню «Add Variable». В появившемся окне указать категорию, имя и тип переменной. Возможно так же ввести минимальное и максимальное её значения. Пример представлен на рисунке 4.12.

Рисунок 4.12

В результате выполнения работ описанных в текущей главе, был разработан пользовательский интерфейс приложения XMLConverter.

4.1.2 Разработка функций реализующих алгоритм преобразования исходного XML в новый XML

Во время выполнения настоящей квалификационной работы был разработан алгоритм преобразования xml-документа в промежуточный xml-документ. При его рассмотрении примем во внимание, что все расчёты количества добавляемых строк ведутся с учётом заданных величин отступов сверху и снизу для разделов в спецификации. Отступы представлены в виде пустых строк. Введём в алгоритм счётчик общего количества строк i. Он нужен для контроля позиции текущего элемента, а также, чтобы вычислить количество пустых строк, которые необходимо добавить в конец xml-документа. Перед запуском алгоритма i равно 0. Под элементами будем понимать, теги <line/> и <section/>. Преобразование рассматривается на уровне этих объектов. Рассматривая их, будем иметь в виду, что они несут с собой данные, хранимые в атрибутах. Каждый из этих элементов (<line/> и <section/>) образует строку таблицы спецификации. То есть, говоря о строке pdf-документа, будем подразумевать, что это <line/> или <section/> xml-документа и наоборот.

Алгоритм состоит из следующих шагов.

1 этап.        Увеличиваем счётчик на единицу. Рассматриваем i-ю строку xml-документа. Если это <section/>, переходим к этапу 2. Иначе переходи к этапу 5.

2 этап.        Проверяем, не попадёт ли раздел на вторую строку страницы спецификации, при добавлении пустых строк (по одной, начиная с нуля) сверху, в пределах заданного отступа. Если да, вносим необходимое число пустых элементов <line/> и увеличиваем счётчик на количество добавленных строк. Переходим к этапу 7. Иначе, увеличиваем счётчик на величину заданного отступа. Переходим к этапу 3.

этап. Проверяем, не получается ли разрыв между разделом и первой не пустой строкой, после него, в виде переноса последней на другой лист спецификации, при добавлении пустых строк (по одной, начиная с нуля) снизу, в пределах заданного отступа. Если да, добавляем перед <section/> необходимое число <line/>, сдвигая, таким образом, раздел на вторую строку следующего листа. Увеличиваем счётчик на число добавленных строк. Переходим к этапу 7. В противном случае переходим к этапу 4.

этап. Проверяем, не попадёт ли раздел на первую строку страницы спецификации. Если да, добавляем перед <section/> один пустой <line/> и увеличиваем счётчик на единицу. Переходим к этапу 7.

этап. Проверяем, не попадёт ли <line/> на последнюю строку страницы спецификации. Если да, добавляем перед ним две пустых строки и увеличиваем счётчик на два. исло добавленных строкего, в виде переноса последней люсмые в атрибутах. Переходим к следующему этапу.

этап. Проверяем, не попадёт ли <line/> на первую строку страницы спецификации. Если да, добавляем перед ним один пустой <line/> и увеличиваем счётчик на единицу. Переходим к этапу 8.

этап. Увеличиваем счётчик на величину заданного отступа снизу раздела. Переходим к следующему этапу. исло добавленных строкего, в виде переноса последней люсмые в атрибутах.

этап. Проверяем, если, достигнут конец xml-документа, вычисляем количество, пустых строк, которые необходимо добавить, чтобы последний лист спецификации pdf, был заполнен полностью. В противном случае переходим к этапу 1.

Перейдем к программной реализации представленного алгоритма. Чтение данных из xml-файла производится с помощью функции ReadFile(). Но, для начала, необходимо открыть файл с помощью функции CreateFile() [10]. Рассмотрим следующий фрагмент кода.

HANDLE hFile = CreateFile(sDir,GENERIC_READ,0,0,OPEN_EXISTING,0,0);

DWORD fileSize = GetFileSize(hFile,0);

char *fileBuffer = new char[fileSize];

DWORD bytesRead;

ReadFile(hFile,fileBuffer,fileSize,&bytesRead,0);

Первый параметр передаваемый в функцию CreateFile() - это строковая переменная содержащая путь к открываемому xml-файлу. Флаг GENERIC_READ означает, что файл открывается только для чтения. Флаг OPEN_EXISTING сведетельствует от том будет открыт существующий файл. Рассматривыемый метод возвращает идентификатор открытого ресурса (файла). Функция GetFileSize() возвращает размер открытого файла. С помощью функции ReadFile() данные всего файла считываются в оперативную память (по адресу содержащемуся в fileBuffer). Третий параметр рассматриваемого метода - количество байт для чтения. После выполнения функции, переменная bytesRead будет содержать число реально прочитанных байт.

Для программной проверки, не попадёт ли раздел на вторую строку страницы спецификации (этап 2, рассмотренного алгоритма) был разработан следующий фрагмент кода.

for(DWORD k = 0; k < kline_before + 1; k++)

{(((*line) + k == 2)||((*line) + k == (K+2))||((( (*line) + k - (K+2))% T == 0)&&(( (*line) + k ) > (K+2))))

{[section][2] = k;= true;;

}

}

Здесь переменная kline_before содержит значение количесива пустых <line/> добавляемых сверху <section/>. По адресу хранящимуся в line, находится значение счётчика строк. Переменная K - это количество строк на первой странице спецификации. Т - количество строк на 2й и последующих страницах спецификации. Переменная section содержит количество просмотренных разделов. И соответственно, номер текущего раздела. Переменая массива positionSectionStart[section][2] содержит количество строк добавляемых перед текущим разделом. Переменная массива positionSectionStart[section][0] содержит позицию символа < (текущего тега <section/> или <line/>) в xml-файле. Значение элемента массива positionSectionStart[section][1] информирует о том, что positionSectionStart[section][0] содержит позицию объекта <section> или <line/>.

Для программной проверки разрыва между разделом и первой не пустой строкой, после него, в виде переноса последней на другой лист спецификации (этап 3, рассмотренного алгоритма), был разработан следующий фрагмент кода.

for(DWORD k = 0; k < kline_after + 2; k++)

{

//Проверяем не попала ли секция в конец листа спецификации((((*line)+k) == K)||(((((*line)+k-K)%T) == 0)&&(((*line)+k) > K)))

{

(*section10_29)++;_29[*section10_29][0] = section;

//Должны быть добавлены как минимум 2 строки_29[*section10_29][1] = k + 2;

*line += k + 2;;

}

}

Здесь переменная kline_after одержит значение количесива пустых <line/> добавляемых снизу <section/>. По адресу хранящимуся в section10_29 находится значение счётчика разделов попавших в начало или конец листа спецификации. Элемент массива positionSection10_29[*section10_29][0] содержит порядковый номер раздела в xml-документе. Переменая positionSection10_29[*section10_29][2] содержит число дополнительно добавляемых строк перед разделом, для переноса его на новый лист спецификации.

Программная реализация проверки попадания раздела в конец листа спецификации представлена ниже.

if((*line == 1)||(*line == (K+1))||(((*line - (K+1))%T== 0)&&((*line > (K+1))))

{

(*section10_29)++;_29[*section10_29][0] = section;_29[*section10_29][1] = 1;

*line ++;;

}

Проверка на этапах 5 и 6 реализуется аналогично.

Код функций, реализующих алгоритм преобразования xml-файла в новый xml-документ, представлен в приложении B.

.2 Создание инсталляционного пакета

Для создания пакета инсталляции разработанного приложения и всех сопутствующих компонентов воспользуемся бесплатно распространяемой программой NetScat Extreme Installer, версии 1.04. Для этого, после её запуска на вкладке «Общие» введём данные, как показано на рисунке 4.13.

На вкладке «Файлы» укажем директорию, в которой находятся файлы, предназначенные для компоновки создаваемого инсталлятора. Вкладка «Ярлыки» предназначена для ввода данных о ярлыках, которые необходимо создать инсталлятору при установке приложения. Соответствующие информационные поля заполняются, как показано на рисунке 4.14. Запись «%Desktop%» обозначает, что ярлык будет создан на рабочем столе. То есть вместо этой записи будет подставлен путь к папке рабочего стола. Запись «%Dest%» обозначает путь к рабочей папке устанавливаемого приложения. Далее необходимо набрать текст лицензионного соглашения на вкладке «Соглашение». Есть возможность загрузить уже существующее соглашение из файла с расширением rtf или txt. На вкладке «Языки» выбираются языки, перечень которых будет предложен при запуске инсталляционного пакета, созданного NetScat Extreme Installer. Результат выбора определит, какой из представленных языков будет использован мастером, для ведения диалога с пользователем во время установки.

Рисунок 4.13

Рисунок 4.14

Последним этапом настройки параметров создаваемого инсталлятора является выбор вкладки «Построение», в которой указывается степень сжатия. После чего необходимо щёлкнуть «Построить». В появившемся окне ввести имя файла и выбрать папку для его сохранения. Щёлкнуть «Ok».

Источник: https://www.bibliofond.ru/detail.aspx?id=784574