Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

288

PostQuitMessage(0); return 0;

}

return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

Рис. 8.8 Программа ENVIRON

В программе ENVIRON создается два дочерних окна: окно списка стиля LBS_STANDART и статическое окно стиля SS_LEFT (текст с выравниванием по левому краю). В программе ENVIRON для получения списка строк окружения используется переменная environ (объявленная как внешняя в STDLIB.H). Программа использует сообщение LB_ADDSTRING для размещения каждой строки в окне списка.

Когда вы запускаете программу ENVIRON, то с помощью мыши или клавиатуры можете выбрать переменную окружения. Каждый раз, когда вы изменяете выбор, окно списка посылает своему родительскому окну сообщение WM_COMMAND, которое попадает в процедуру WndProc. Когда WndProc получает сообщение WM_COMMAND, она проверяет равно ли младшее слово параметра lParam (идентификатор дочернего окна) единице, и равно ли старшее слово параметра wParam (код уведомления) величине LBN_SELCHANGE. При наличии соответствующих значений она, с помощью сообщения LB_GETCURSEL, получает индекс выбранного элемента, а с помощью сообщения LB_GETTEXT — сам текст выбранного элемента, т. е. имя переменной окружения. Для получения строки, соответствующей этой переменной окружения, в программе ENVIRON используется функция языка С getenv, а функция SetWindowText используется для передачи этой строки статическому дочернему окну управления, в котором собственно и выводится на экран содержимое строки.

Обратите внимание, что в программе ENVIRON для индексирования переменной environ и получения строки нельзя использовать индекс, возвращаемый сообщением LB_GETCURSEL. Поскольку окно списка имеет стиль LBS_SORT (являющийся частью стиля LBS_STANDART), индексы не совпадают.

Список файлов

Лучшее оставлено напоследок: самым мощным сообщением окон списка является сообщение LB_DIR. Следующий оператор заполняет список перечнем файлов каталога, иногда с подкаталогами и именами доступных дисков:

SendMessage(hwndList, LB_DIR, iAttr,(LPARAM) szFileSpec);

Использование атрибутов файлов

Параметр iAttr — это код атрибута файла. Младший значащий байт — обычный атрибут файла, используемый при вызовах функций MS-DOS:

Параметр iAttr

Значение

Атрибут

DDL_READWRITE

0x0000

Обычный файл

DDL_READONLY

0x0001

Файл только для чтения

DDL_HIDDEN

0x0002

Скрытый файл

DDL_SYSTEM

0x0004

Системный файл

DDL_DIRECTORY

0x0010

Подкаталог

DDL_ARCHIVE

0x0020

Файл с установленным архивным битом

Старший байт обеспечивает некоторый дополнительный контроль:

Параметр iAttr

Значение

Опция

DDL_DRIVES

0x4000

включение имен дисков

DDL_EXCLUSIVE

0x8000

включать только файлы с указанными

 

 

атрибутами

Когда значение iAttr сообщения LB_DIR равно DDL_READWRITE, то в списке перечисляются обычные файлы, файлы только для чтения и файлы с установленным архивным битом. Это соответствует логике, используемой функциями MS-DOS для поиска файлов. Если значение iAttr сообщения LB_DIR равно DDL_DIRECTORY, то в список, дополнительно к файлам, включаются имена подкаталогов в квадратных скобках. Если значение iAttr сообщения LB_DIR равно DDL_DRIVES | DDL_DIRECTORY, то в список добавляются буквенные идентификаторы всех доступных дисков, при этом они расположены между черточками.

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

289

Упорядочивание списков файлов

Параметр lParam — это указатель на строку, задающую спецификацию файлов, например, "*.*". Такая спецификация файлов не влияет на подкаталоги, которые содержатся в списке.

Сообщение LBS_SORT можно использовать для окна списка файлов. Окно списка будет сначала отображать файлы, удовлетворяющие спецификации, а затем, необязательно, список доступных дисков в виде:

[-A-]

и (тоже необязательно) имена подкаталогов. Первый подкаталог будет выглядеть следующим образом:

[..]

Эта "двоеточие" — точка входа в подкаталог на уровень выше в сторону корневого каталога. (Точка входа не появится, если вы перечисляете файлы корневого каталога.) И наконец, указанные имена подкаталогов перечисляются в виде:

[SUBDIR]

Если вы не используете сообщение LBS_SORT, имена файлов и подкаталогов выводятся вперемешку, а имена доступных дисков оказываются в конце списка.

Утилита Head для Windows

Хорошо известная в операционной системе UNIX утилита "head" (заголовок) выводит на экран начальные строки файла. Давайте используем окно списка для написания аналогичной программы для Windows. В программе HEAD, представленной на рис. 8.9, в списке перечисляются все файлы и подкаталоги. Вы можете выбрать файл для отображения с помощью двойного щелчка мыши на имени файла или, если имя файла выделено, нажав клавишу <Enter>. Вы также можете изменить подкаталог, используя любой из этих способов. Программа HEAD выводит на экран в правую часть рабочей области окна до 8 килобайт информации из начала файла.

HEAD.MAK

#--------------------

# HEAD.MAK make file

#--------------------

head.exe : head.obj

$(LINKER) $(GUIFLAGS) -OUT:head.exe head.obj $(GUILIBS)

head.obj : head.c

$(CC) $(CFLAGS) head.c

HEAD.C

/*---------------------------------------------

 

HEAD.C --

Displays beginning(head) of file

 

(c) Charles Petzold, 1996

---------------------------------------------

*/

#include <windows.h> #include <string.h> #include <direct.h>

#define

MAXPATH

256

#define

MAXREAD

8192

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK ListProc(HWND, UINT, WPARAM, LPARAM);

WNDPROC fnOldList;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

{

static char szAppName[] = "Head"; HWND hwnd;

MSG msg;

290

WNDCLASSEX wndclass;

 

wndclass.cbSize

= sizeof(wndclass);

wndclass.style

= CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc

= WndProc;

wndclass.cbClsExtra

= 0;

wndclass.cbWndExtra

= 0;

wndclass.hInstance

= hInstance;

wndclass.hIcon

= LoadIcon(NULL, IDI_APPLICATION);

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH)(COLOR_BTNFACE + 1);

wndclass.lpszMenuName

= NULL;

wndclass.lpszClassName

= szAppName;

wndclass.hIconSm

= LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&wndclass);

hwnd = CreateWindow(szAppName, "File Head", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, iCmdShow);

UpdateWindow(hwnd);

while(GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

 

static BOOL

bValidFile;

static char

sReadBuffer[MAXREAD], szFile[MAXPATH];

static HWND

hwndList, hwndText;

static OFSTRUCT

ofs;

static RECT

rect;

char

szBuffer[MAXPATH + 1];

HDC

hdc;

int

iHandle, i;

PAINTSTRUCT

ps;

TEXTMETRIC

tm;

switch(iMsg)

{

case WM_CREATE :

hdc = GetDC(hwnd);

SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

GetTextMetrics(hdc, &tm);

ReleaseDC(hwnd, hdc);

rect.left = 20 * tm.tmAveCharWidth; rect.top = 3 * tm.tmHeight;

hwndList = CreateWindow("listbox", NULL,

WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD, tm.tmAveCharWidth, tm.tmHeight * 3, tm.tmAveCharWidth * 13 +

GetSystemMetrics(SM_CXVSCROLL), tm.tmHeight * 10,

hwnd,(HMENU) 1,

291

(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),

NULL);

hwndText = CreateWindow("static", getcwd(szBuffer, MAXPATH), WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT, tm.tmAveCharWidth, tm.tmHeight, tm.tmAveCharWidth * MAXPATH, tm.tmHeight, hwnd,(HMENU) 2,

(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),

NULL);

fnOldList =(WNDPROC) SetWindowLong(hwndList, GWL_WNDPROC, (LPARAM) ListProc);

SendMessage(hwndList, LB_DIR, 0x37,(LPARAM) "*.*"); return 0;

case WM_SIZE :

rect.right = LOWORD(lParam); rect.bottom = HIWORD(lParam); return 0;

case WM_SETFOCUS : SetFocus(hwndList); return 0;

case WM_COMMAND :

if(LOWORD(wParam) == 1 && HIWORD(wParam) == LBN_DBLCLK)

{

if(LB_ERR ==(i = SendMessage(hwndList,

LB_GETCURSEL, 0, 0L)))

break;

SendMessage(hwndList, LB_GETTEXT, i,(LPARAM) szBuffer);

if(-1 != OpenFile(szBuffer, &ofs, OF_EXIST | OF_READ))

{

bValidFile = TRUE; strcpy(szFile, szBuffer); getcwd(szBuffer, MAXPATH);

if(szBuffer [strlen(szBuffer) - 1] != '\\') strcat(szBuffer, "\\");

SetWindowText(hwndText, strcat(szBuffer, szFile));

}

else

{

bValidFile = FALSE;

szBuffer [strlen(szBuffer) - 1] = '\0'; chdir(szBuffer + 1);

getcwd(szBuffer, MAXPATH); SetWindowText(hwndText, szBuffer); SendMessage(hwndList, LB_RESETCONTENT, 0, 0L); SendMessage(hwndList, LB_DIR, 0x37,(LONG) "*.*");

}

InvalidateRect(hwnd, NULL, TRUE);

}

return 0;

case WM_PAINT :

hdc = BeginPaint(hwnd, &ps);

SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));

SetBkColor (hdc, GetSysColor(COLOR_BTNFACE));

292

if(bValidFile && -1 !=(iHandle =

OpenFile(szFile, &ofs, OF_REOPEN | OF_READ)))

{

i = _lread(iHandle, sReadBuffer, MAXREAD); _lclose(iHandle);

DrawText(hdc, sReadBuffer, i, &rect, DT_WORDBREAK |

DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX);

}

else

bValidFile = FALSE;

EndPaint(hwnd, &ps); return 0;

case WM_DESTROY : PostQuitMessage(0); return 0;

}

return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

LRESULT CALLBACK ListProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

if(iMsg == WM_KEYDOWN && wParam == VK_RETURN)

SendMessage(GetParent(hwnd), WM_COMMAND, 1,

MAKELONG(hwnd, LBN_DBLCLK));

return CallWindowProc(fnOldList, hwnd, iMsg, wParam, lParam);

}

Рис. 8.9 Программа HEAD

Впрограмме ENVIRON, когда мы выбирали переменную окружения — либо с помощью щелчка мыши, либо с помощью клавиатуры — программа выводила на экран соответствующую строку. Однако, если бы мы использовали аналогичный прием в программе HEAD, программа была бы слишком медленной, поскольку ей пришлось бы долго открывать и закрывать каждый выбранный файл по мере перемещения вашей выборки по списку. Вместо этого в программе HEAD необходим двойной щелчок мыши на имени файла или подкаталога. Это несколько затрудняет задачу, поскольку управляющее окно списка не имеет встроенного интерфейса клавиатуры, который бы соответствовал двойному щелчку мыши. А, как известно, необходимо обеспечивать интерфейс клавиатуры там, где это возможно.

Вчем же состоит решение? Конечно, во введении дополнительной оконной процедуры. Новая оконная функция класса списка в программе HEAD называется ListProc. Она просто отслеживает сообщение WM_KEYDOWN с параметром wParam, равным VK_RETURN, и посылает сообщение WM_COMMAND с кодом уведомления LBN_DBLCLK обратно родительскому окну. При обработке в WndProc сообщения WM_COMMAND, для контроля выбранного пункта, используется функция Windows OpenFile. Если функция OpenFile возвращает ошибку, то значит выбран не файл, а, возможно, подкаталог. Затем для смены подкаталога в программе HEAD используется функция chdir. Программа посылает окну списка сообщение LB_RESETCONTEXT для обновления контекста и сообщение LB_DIR для заполнения окна списка перечнем файлов нового подкаталога.

При обработке сообщения WM_PAINT в оконной процедуре открывается файл с использованием функции Windows OpenFile. Возвращаемым значением функции является описатель файла MS-DOS, который может быть передан функциям Windows _lread и _lclose. Содержимое файла выводится на экран с помощью функции

DrawText.

Часть III

Использование

ресурсов

Соседние файлы в предмете Операционные системы