на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Файловая система
p align="left">// возникла ошибка - может быть функция не поддерживается

} else {

// все в порядке, работаем как обычно}

Несколько неожиданно, что в Windows 98 эти функции не устанавливают код ошибки, функция GetLastError возвращает код ERROR_SUCCESS. Однако о корректной работе функций говорить к сожалению не приходиться... Подробнее -- в приводимом ниже примере.

Пример 2B -- работа с томами

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

Интересно рассмотреть, каким образом осуществляется вывод информации о томах в окно приложения. Это можно было-бы реализовать разными способами:

Хуже некуда. Изменить в примере 1B.CPP обработку сообщения WM_PAINT (функция Cls_OnPaint), так, что бы при обработке сообщения опрашивать все устройства и выводить необходимую информацию. Очень плохо в этом то, что такой опрос может занимать значительное время, и приводить к обращениям к устройствам при каждой перерисовке окна. Еще хуже то, что при попытке чтения информации с устройства возможно возникновение ошибок, о которых система будет сообщать в отдельном всплывающем окошке, например Cannot read from drive A:”. Это окошко окажется, с большой вероятностью, поверх окна приложения, следовательно, при закрытии окна сообщения, наше приложение снова получит сообщение WM_PAINT, снова попробует обратиться к тому-же устройству ... и так далее (что бы этого избежать можно воспользоваться функцией SetErrorMode, отключив вывод сообщений об ошибках).

Чуть лучше. Считывать информацию об устройствах при создании окна, формировать где-то в памяти весь текст, затем отображать его при обработке WM_PAINT. Этот способ качественно лучше тем, что получение данных и их отображение осуществляется в разных местах программы и в разное время. Однако и у него есть минусы -- список устройств может изменяться во время работы приложения, а оно этого не отразит, и, кроме того, список может оказаться достаточно большим -- больше размеров окна. Первую проблему мы решать сейчас даже не будем -- этого легко добиться введя меню с командой Обновить (Refresh) или выполняя такое обновление через определенный интервал времени. Вторая проблема приведет к добавлению собственного интерфейса -- обработке сообщений клавиатуры и мыши, что потребует написания значительного кода и продолжительной отладки.

Еще лучше. Чуть разовьем второй способ -- получать информацию будем при создании окна, а отображение и работу с мышью и клавиатурой переложим на Windows. Windows предоставляет разработчикам несколько стандартных классов окон, реализующих самые распространенные элементы управления -- кнопки, флажки, списки, простейшее окно-редактор и другие. Вот окном-редактором мы и воспользуемся, причем специально укажем, что текст является неизменяемым, то есть редактор будет работать как окно просмотра. В этом случае при создании главного окна приложения, мы должны создать дочернее окно-редактор, занимающее всю внутреннюю область главного окна Подробнее о работе с окнами смотри в соответствующих разделах.. Затем, сформировав весь необходимый текст, передать его редактору. Окно редактирования будет снабжено полосами прокрутки, поддерживать работу с клавиатурой и мышью, осуществлять передачу текста в буфер обмена -- и все само, без разработки дополнительного кода. Мы должны доделать совсем немного -- обрабатывать сообщения, связанные с изменением размера главного окна (соответственно менять размер дочернего окна), при уничтожении главного окна не забыть уничтожить окно-редактор, а сообщение WM_PAINT мы можем вообще не обрабатывать.

Приложение рассчитано на работу в Win32, однако это связано только лишь с применением функций Win32 API для получения информации о томах. При создании приложения для Windows 3.x вместо функций, не декларированных в Windows API, используются функции-эмуляторы, включаемые в это приложение при компиляции 16ти разрядного приложения. Это обеспечивает возможность нормальной компиляции и работы приложения на обеих платформах, но с несколько ограниченными возможностями в случае применения Windows API (строго говоря, функции-эмуляторы можно было бы сделать и более мощными, опираясь на функции и структуры данных MS-DOS -- просто это выходит за рамки данной книги).

Функции DefineDosDevice и QueryDosDevice, применяемые в числе прочих в этом приложении, работают только в виде 32х разрядного приложения и только под Windows NT, так как они имеют смысл исключительно для реализации Win32 в Windows NT.

Файл 2B.CPP

#define STRICT

#include <windows.h>

#include <windowsx.h>

#define UNUSED_ARG(arg) (arg)=(arg)

#ifndef __NT__

// определим необходимые функции при компиляции для Windows API

#include "2b16.cpp"

// текст файла 2b16.cpp приведен ниже

#endif

static char szWndClass[]= "test volume functions";

static HINSTANCE hInstance;

BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)

{UNUSED_ARG(lpCreateStruct);

char *temp, *p, *s;

DWORD n, i, sernum, complen, flags, spc, bps, fc, tc;

char file_system[ 128 ], buffer[ 1024 ];

UINT count, errmode;

HWND hwndView;

RECT rc;

HFILE hf;

static OFSTRUCT ofs;

static char tempfile[] = “c:\\test.txt”;

static char devZ[] = “Z:”;

// создадим окно-редактор, занимающее всю внутреннюю область окна

GetClientRect(hwnd, &rc);

// теоретически в CREATESTRUCT указаны размеры окна, но к сожалению они

// могут быть указаны как нулевые, хотя это не так. Функция GetClientRect

// в этом случае все равно возвращает корректные данные

hwndView = CreateWindow(

"EDIT", "",

WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|ES_MULTILINE|ES_READONLY,

0, 0, rc.right, rc.bottom, hwnd, (HMENU)1, hInstance, NULL);

if (!IsWindow(hwndView)) {

// если окно просмотра создать не удалось, то завершаем приложение

// сообщив об ошибке

MessageBox(NULL, "Cannot create viewer window!", NULL, MB_OK);

return FALSE;}

// для красоты используем моноширинный шрифт (подробнее см. GDI)

SetWindowFont(hwndView, GetStockObject(ANSI_FIXED_FONT), FALSE);

// функция SetWindowFont в документации не описана, это макрос, определяемый

// в windowsx.h Подробнее -- см. исходный текст этого файла.

// запоминаем хендл окна просмотра в структуре описания главного окна

// (при регистрации класса надо зарезервировать 4 байта -- что бы и в

// Windows API и в Win32 API использовать одинаковые значения и функции)

SetWindowLong(hwnd, 0, (LONG)hwndView);

// 1. мы не знаем заранее, как много места понадобиться для описания всех

// томов и устройств DOS. Для простоты создадим временный файл с заранее

// заданным именем c:\test.txt (строго говоря, надо было бы проверить наличие

// переменной TEMP или TMP, убедиться, что она указывает на корректный

// каталог - в жизни часто она указывает на несуществующий каталог, диск

// или даже на защищенный диск - всякое бывает - и создать файл там -- но это

// все слишком громоздко для примера).

// 2. в этом файле мы соберем нужный текст, а затем разом передадим его окну

// просмотра, после чего файл удалим.

// 3. для работы с файлами используем функции Windows API, что бы сохранить

// переносимость между разными платформами

hf = _lcreat(tempfile, 0);

if (hf == HFILE_ERROR) {

// при ошибке - сообщаем и заканчиваем (окно просмотра будет уничтожено

// позже, при обработке WM_DESTROY

MessageBox(NULL, "Cannot create temporary file!", NULL, MB_OK);

return FALSE;}

// пишем первый заголовок

_lwrite(hf, "******** GET VOLUME INFORMATION ********\r\n\r\n", 44);

SetLastError(ERROR_SUCCESS);

n = GetLogicalDriveStrings(0, NULL);

if (GetLastError() != ERROR_SUCCESS) {

// Функция GetLogicalDriveStrings не реализована в Win32s и (в книгах

// часто утверждают) в Windows-95, возможно, иногда это и так, но у меня

// в Windows-95 версии 4.00.950a, локализованной для России, работает.

// если все же нет, то эмулируем ее работу посредством GetLogicalDrives

// которая точно есть во всех реализациях Win32

n = GetLogicalDrives();

// узнаем, сколько всего устройств

count = 0;

for (i = 1; i; i <<= 1) if (n & i) count++;

// формируем строку с именами устройств

temp = new char [ count * 4 + 1 ];

if (temp) {

p = temp;

for (i = 0; i < 32; i ++) if (n & (1L << i)) {

*p++ = (char)('A' + i); *p++ = ':'; *p++ = '\\'; *p++ = '\0';}

*p++ = '\0';}

} else {

// если функция GetLogicalDriveStrings работает, то используем ее

temp = new char [ n + 1 ];

if (temp) GetLogicalDriveStrings(n, temp);

}

if (temp) {

// исключаем обработку сообщений о критической ошибке

errmode = SetErrorMode(SEM_FAILCRITICALERRORS);

// если строка получена, то разбираем ее по частям

for (p = temp; *p; p += lstrlen(p) + 1) {

wsprintf(buffer, "Root: %s", p);

switch (GetDriveType(p)) {

case 0: s = "???"; break;

case 1: s = "invalid"; break;

case DRIVE_REMOVABLE: s = "REMOVABLE"; break;

case DRIVE_FIXED: s = "FIXED"; break;

case DRIVE_REMOTE: s = "REMOTE"; break;

case DRIVE_CDROM: s = "CD-ROM"; break;

case DRIVE_RAMDISK: s = "RAM DISK"; break;

default: s = "what?!"; break;}

// укажем явное преобразование указателя на строку `s' к типу

// LPSTR -- так как в Windows API для моделей памяти с одним сегментом

// данных (tiny,small,medium) указатели по умолчанию 16-ти разрядные

// а для функций Windows обязательно нужны 32-х разрядные

wsprintf(buffer+lstrlen(buffer), " type=%s volume='", (LPSTR)s);

sernum = complen = flags = 0; file_system[0] = '\0';

if (

GetVolumeInformation(

p, buffer+lstrlen(buffer), 64,

&sernum, &complen, &flags,

file_system, sizeof(file_system)))

{// если информация о томе прочитана -> получаем и выводим более

// подробные сведения

wsprintf(buffer+lstrlen(buffer), "' serial=%08lX\r\n", sernum);

_lwrite(hf, buffer, lstrlen(buffer));

spc = bps = fc = tc = 0L;

GetDiskFreeSpace(p, &spc, &bps, &fc, &tc);

bps *= spc;

wsprintf(

buffer,

" comp. length=%lu cluster=%lu total=%luK free=%luK\r\n",

complen, bps, bps*tc/1024, bps*fc/1024);

_lwrite(hf, buffer, lstrlen(buffer));

wsprintf(buffer, " file system ='%s' flags=", file_system);

s = buffer + lstrlen(buffer);

if (flags & FS_CASE_IS_PRESERVED) {

lstrcpy(s, "CASE_PRESERVED "); s+= lstrlen(s);}

if (flags & FS_CASE_SENSITIVE) {

lstrcpy(s, "CASE_SENSITIVE "); s+= lstrlen(s);}

if (flags & FS_UNICODE_STORED_ON_DISK) {

lstrcpy(s, "UNICODE "); s+= lstrlen(s);}

if (flags & FS_PERSISTENT_ACLS) {

lstrcpy(s, "ACL "); s+= lstrlen(s);}

if (flags & FS_FILE_COMPRESSION) {

lstrcpy(s, "MAY_COMPRESS "); s+= lstrlen(s);}

if (flags & FS_VOL_IS_COMPRESSED) {

lstrcpy(s, "COMPRESSED "); s+= lstrlen(s);}

lstrcpy(s, "\r\n");

_lwrite(hf, buffer, lstrlen(buffer));

} else {

// если информация о томе не получена, то просто сообщаем

lstrcpy(

buffer+lstrlen(buffer),

"' ***** NO VOLUME INFORMATION!\r\n");

Страницы: 1, 2, 3, 4, 5, 6, 7



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.