Операционная система Microsoft Windows 3.1 для программиста -том 3

       

Файл oem3ansi/oem3ansi.cpp


// ---------------------------------------- // Перекодировка текстового файла // из OEM в ANSI с использованием // дополнительной таблицы перекодировки // ----------------------------------------

#define STRICT #include <windows.h>
#include <commdlg.h>
#include <mem.h>

// Прототипы функций HFILE GetSrcFile(void);
HFILE GetDstFile(void);
int Oem3Ansi(HFILE, HFILE);

// Указатель на таблицу перекодировки, // которая будет загружена из ресурсов char far * lpXlatTable;

// Идентификатор копии приложения HINSTANCE hInst;

// ------------------------------- // Функция WinMain // -------------------------------

#pragma argsused int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { // Идентификаторы файлов HFILE hfSrc, hfDst;

// Положение ресурса в файле HRSRC hResource;

// Идентификатор таблицы перекодировки HGLOBAL hXlatTable;

// Сохраняем идентификатор копии приложения // в глобальной переменной hInst = hInstance;

// Определяем расположение ресурса hResource = FindResource(hInstance, "XlatTable", "XLAT");

// Получаем идентификатор ресурса hXlatTable = LoadResource(hInstance, hResource);

// Фиксируем ресурс в памяти, получая его адрес lpXlatTable = (char far *)LockResource(hXlatTable);



// Если адрес равен NULL, при загрузке или // фиксации ресурса произошла ошибка if(lpXlatTable == NULL) { MessageBox(NULL, "Resource loading error", NULL, MB_OK);
return(-1);
}

// Открываем входной файл. hfSrc = GetSrcFile();
if(!hfSrc) return 0;

// Открываем выходной файл hfDst = GetDstFile();
if(!hfDst) return 0;

// Выполняем перекодировку файла if(Oem3Ansi(hfSrc, hfDst)) { MessageBox(NULL, "Low Memory", NULL, MB_OK);
}

// Закрываем входной и выходной файлы _lclose(hfSrc);
_lclose(hfDst);

// Разблокируем и освобождаем ресурс UnlockResource(hXlatTable);
FreeResource(hXlatTable);

return 0; }

// ------------------------------- // Функция GetSrcFile // Выбор файла для перекодировки // -------------------------------




HFILE GetSrcFile(void) { OPENFILENAME ofn;

char szFile[256]; char szFileTitle[256]; char szFilter[256] = "Text Files\0*.txt;*.doc\0Any Files\0*.*\0"; HFILE hf;

szFile[0] = '\0'; memset(&ofn, 0, sizeof(OPENFILENAME));

// Инициализируем нужные нам поля

// Добавляем флаг OFN_ENABLETEMPLATE, который // разрешает использование шаблона ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLETEMPLATE;

// Идентификатор модуля, содержащего шаблон // диалоговой панели. В нашем случае это // идентификатор копии приложения ofn.hInstance = hInst;

// Имя ресурса, содержащего шаблон ofn.lpTemplateName = (LPSTR)"Open";

// Заполняем остальные поля ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = NULL;

// Выбираем входной файл if (GetOpenFileName(&ofn)) { // Открываем на чтение hf = _lopen(ofn.lpstrFile, OF_READ);
return hf; } else return 0; }

// ------------------------------- // Функция GetDstFile // Выбор файла для записи // результата перекодировки // -------------------------------

HFILE GetDstFile(void) { OPENFILENAME ofn;

char szFile[256]; char szFileTitle[256]; char szFilter[256] = "Text Files\0*.txt;*.doc\0Any Files\0*.*\0";

HFILE hf;

szFile[0] = '\0';

memset(&ofn, 0, sizeof(OPENFILENAME));

// Добавляем флаг OFN_ENABLETEMPLATE, который // разрешает использование шаблона ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLETEMPLATE;

// Идентификатор модуля, содержащего шаблон ofn.hInstance = hInst;

// Имя ресурса, содержащего шаблон ofn.lpTemplateName = (LPSTR)"Open";

// Изменяем заголовок диалоговой панели ofn.lpstrTitle = (LPSTR)"Выберите выходной файл";

// Заполняем остальные поля ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = NULL;



// Выбираем выходной файл if (GetSaveFileName(&ofn)) {

// Открываем на запись. // При необходимости создаем файл hf = _lcreat(ofn.lpstrFile, 0);
return hf; } else return 0; }

// ------------------------------- // Функция Oem3Ansi // Перекодировка файла // -------------------------------

int Oem3Ansi(HFILE hfSrcFile, HFILE hfDstFile) { // Счетчик прочитанных байт DWORD cbRead;

// Размер файла DWORD dwFileSize;

// Идентификатор глобального блока // памяти, который будет использован для // чтения файла HGLOBAL hglbBuf;

// Указатель на глобальный блок памяти unsigned char huge * hBuf;

// Определяем размер файла. Для этого // устанавливаем текущую позицию на // конец файла dwFileSize = _llseek(hfSrcFile, 0l, 2);

// Устанавливаем текущую позицию // на начало файла _llseek(hfSrcFile, 0l, 0);

// Заказываем глобальный блок памяти, // размер которого равен длине файла hglbBuf = GlobalAlloc(GMEM_FIXED, dwFileSize);
hBuf = (unsigned char huge *)GlobalLock(hglbBuf);

// Если мало свободной памяти, // возвращаем код ошибки if(hBuf == NULL) return(-1);

// Читаем файл в полученный блок памяти cbRead = _hread(hfSrcFile, hBuf, dwFileSize);

// Выполняем перекодировку for(long i=0; i < cbRead; i++) { // Перекодировка по таблице, // загруженной из ресурсов hBuf[i] = lpXlatTable[hBuf[i]];

// Перекодировка из OEM в ANSI OemToAnsiBuff((const char far*)&hBuf[i], (char far*)&hBuf[i], 1);
}

// Сохраняем содержимое блока памяти в // выходном файле _hwrite(hfDstFile, hBuf, dwFileSize);

// Расфиксируем и освобождаем // блок памяти GlobalUnlock(hglbBuf);
GlobalFree(hglbBuf);
return 0; }

Функция WinMain сохраняет идентификатор копии приложения в глобальной переменной hInst. Этот идентификатор потребуется впоследствии для загрузки шаблона диалоговой панели из ресурсов приложения.

Далее, так же как и первой версии приложения OEM3ANSI, функция WinMain загружает из ресурсов дополнительную таблицу перекодировки, сохраняя ее адрес в переменной lpXlatTable.

Затем функция WinMain открывает входной и выходной файлы, вызывая функции GetSrcFile и GetDstFile, определенные в нашем приложении.


Эти функции выбирают файлы с использованием шаблона, созданного нами на основе стандартного шаблона диалоговой панели "Open" и функций GetOpenFileName, GetSaveFileName.

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

Так как диалоговые панели выбора входного и выходного файла отличаются только заголовком, для них мы создали только один шаблон. В файле ресурсов этот шаблон имеет имя "Open".

Перед тем, как вызвать функцию GetOpenFileName, предназначенную для выбора входного файла, мы должны подготовить соответствующим образом структуру ofn типа OPENFILENAME. В частности, для обеспечения возможности работы с шаблоном в поле Flags структуры ofn необходимо указать флаг OFN_ENABLETEMPLATE. В поле hInstance этой же структуры необходимо записать идентификатор копии приложения, ресурсы которого содержат шаблон, а в поле lpTemplateName нужно записать указатель на строку имени ресурса:

ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLETEMPLATE; ofn.hInstance = hInst; ofn.lpTemplateName = (LPSTR)"Open";

Функция GetDstFile инициализирует структуру ofn аналогичным образом. Единственное отличие заключается в том, что в поле lpstrTitle записывается адрес строки, содержащей заголовок "Выберите выходной файл":

ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLETEMPLATE; ofn.hInstance = hInst; ofn.lpTemplateName = (LPSTR)"Open"; ofn.lpstrTitle = (LPSTR)"Выберите выходной файл";

Для перекодирования файла в приложении OEM3ANSI определена функция с именем Oem3Ansi.

Прежде всего эта функция определяет размер входного файла. Для этого она выполняет позиционирование на конец файла, используя функцию _llseek:

dwFileSize = _llseek(hfSrcFile, 0l, 2);

Эта функция возвращает текущее смещение в файле от начала файла. Так как мы установили текущую позицию н конец файла, текущее смещение от начала файла, очевидно, равно размеру файла.



После определения размера файла необходимо установить текущую позицию на начало файла. В противном случае при попытке прочитать данные мы получим состояние "Конец файла". Для установки текущей позиции на начало файла мы вызываем функцию _llseek еще раз, но с другими параметрами:

_llseek(hfSrcFile, 0l, 0);

После определения размера входного файла функция Oem3Ansi заказывает фиксированный блок из глобальной области памяти (при помощи функции GlobalAlloc), и фиксирует его для получения адреса (при помощи функции GlobalLock). Адрес блока записывается в переменную hBuf типа unsigned char huge*. Размер заказанного блока равен размеру файла.

Затем весь файл читается в буфер, для чего используется функция _hread:

cbRead = _hread(hfSrcFile, hBuf, dwFileSize);

Перекодировка выполняется в следующем цикле:

for(long i=0; i < cbRead; i++) { hBuf[i] = lpXlatTable[hBuf[i]]; OemToAnsiBuff((const char far*)&hBuf[i], (char far*)&hBuf[i], 1);
}

Для перекодировки по дополнительной таблице мы адресуемся к блоку памяти через указатель типа huge, так как размер блока памяти может превышать 64 Кбайт.

Функция OemToAnsiBuff может перекодировать буфер размером не более 64 Кбайт, поэтому мы вызываем ее отдельно для каждого байта перекодируемого буфера.

После подготовки буфера мы записываем его в выходной файл, вызывая функцию _hwrite:

_hwrite(hfDstFile, hBuf, dwFileSize);

Перед возвратом управления функция Oem3Ansi расфиксирует и освобождает заказанный ранее блок памяти, вызывая функции GlobalUnlock и GlobalFree.

Файл описания ресурсов приложения OEM3ANSI приведен в листинге 4.4.


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