// ---------------------------------------- // Использование органа управления // класса "listbox" для просмотра // содержимого каталога // ----------------------------------------
// ===================================== // Функция WinMain // ===================================== #pragma argsused
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения
// Двойной щелчок по имени файла, каталога // или диска else if(HIWORD(lParam) == LBN_DBLCLK) { // Имитируем приход сообщения от кнопки SendMessage(hwnd, WM_COMMAND, ID_BUTTON, 0L); return 0; }
// Если пользователь изменил выделенную // строку, выводим в окно новую // выделенную строку else if(HIWORD(lParam) == LBN_SELCHANGE) { int uSelectedItem, nSize; char Buffer[256]; HDC hdc;
// Определяем номер новой выделенной строки uSelectedItem = (int)SendMessage(hListBox, LB_GETCURSEL, 0, 0L);
// Если выбрали имя каталога или диска, // пытаемся изменить сначала текущий // каталог, а затем текущий диск if(Buffer[0] == '[') { // Выделяем в выбранной строке имя каталога Buffer[lstrlen(Buffer) - 1] = '\0';
// Пытаемся изменить каталог if(chdir(&Buffer[1]) != 0) { // Если не удалось, значит выбрали имя // диска. В этом случае выделяем букву // имени диска и добавляем строку ":\\: Buffer[3] = '\0'; lstrcat(Buffer, ":\\");
// Заполняем список информацией о файлах // и каталогах в текущем каталоге, а также // вносим туда имена дисков SendMessage(hListBox, LB_DIR, DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM | DDL_DIRECTORY | DDL_DRIVES | DDL_ARCHIVE, (LPARAM)(LPSTR)"*.*"); }
// Если выбрали файл, выводим его имя на экран else { MessageBox(hwnd, Buffer, szWindowTitle, MB_OK); } } } return 0; }
// Это сообщение поступает от списка, если он // имеет фокус ввода и пользователь работает // с клавиатурой case WM_VKEYTOITEM: { // Если пользователь нажал клавишу <Enter> , // посылаем в окно сообщение WM_COMMAND с // параметром wParam, равным идентификатору // кнопки if(wParam == VK_RETURN) { SendMessage(hwnd, WM_COMMAND, ID_BUTTON, 0L); } return -1; }
case WM_PAINT: { HDC hdc; PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 30, 10, "Выберите файл, каталог или диск", 31);
Функция WinMain приложения LISTDIR почти ничем не отличается от аналогичной функции предыдущего приложения. Она создает главное окно приложения и запускает цикл обработки сообщений.
Функция главного окна при обработке сообщения WM_CREATE создает одноколоночный список:
Параметр wParam этого сообщения представляет собой набор флагов, влияющих на содержимое списка после заполнения. Приведем список этих флагов и соответствующих им имен объектов, включаемых в список.
Флаг
Описание
DDL_ARCHIVE
Файлы, для которых в байте атрибутов установлен бит архивирования
DDL_DIRECTORY
Каталоги
DDL_DRIVES
Дисковые устройства
DDL_EXCLUSIVE
В список не будут включены имена обычных файлов
DDL_HIDDEN
Скрытые файлы
DDL_READONLY
Только читаемые файлы
DDL_READWRITE
Файлы, над которыми можно выполнять операции чтения/записи, не имеющие дополнительных атрибутов
DDL_SYSTEM
Системные файлы
<
Параметр lParam сообщения LB_DIR должен содержать указатель на текстовую строку, используемую в качестве шаблона имени. В нашем случае используется шаблон "*.*", поэтому в список попадают имена всех файлов.
Когда в функцию главного окна приложения приходит сообщение WM_COMMAND с извещением LBN_DBLCLK о двойном щелчке по строке списка, функция окна посылает сама себе сообщение WM_COMMAND с параметром wParam, равным идентификатору кнопки "OK", созданной приложением в главном окне справа от списка.
Извещение LBN_SELCHANGE обрабатывается таким же образом, что и в предыдущем приложении.
Обработчик сообщения от кнопки определяет номер выделенной строки и копирует эту строку в свой буфер, посылая в список последовательно сообщения LB_GETCURSEL и LB_GETTEXT. Далее выполняется анализ полученной строки.
Если строка начинается с символа "[", то это может быть либо имя каталога (например, "[dos]"), либо имя диска (например, "[-c-]"). Вначале обработчик предполагает, что получено имя каталога (для простоты мы считаем что каталоги с экзотическими именами "-c-" и т. п. не используются). Закрывающая квадратная скобка заменяется на двоичный ноль, вслед за чем вызывается функция chdir (из стандартной библиотеки компилятора), предназначенная для смены текущего каталога.
Если функция chdir вернула ненулевое значение, текущий каталог не содержит подкаталога с указанным именем. В этом случае обработчик сообщения считает, что полученная строка содержит имя диска, состоящее из буквы в обрамлении квадратных скобок и символов "-". Буква имени диска выделяется и к ней дописывается строка ":\\", вслед за чем выполняется повторная попытка изменения текущего каталога на корневой нового диска. Для изменения текущего диска вызывается функция setdisk из стандартной библиотеки компилятора.
Обратите внимание на способ, которым мы преобразуем букву обозначения диска:
AnsiLowerBuff(&Buffer[2], 1);
Мы использовали функцию AnsiLowerBuff, которая выполняет преобразование из заглавной буквы в прописную (маленькую) с учетом используемого национального алфавита.
После изменения текущего диска или каталога содержимое списка сбрасывается, вслед за чем список вновь наполняется именами файлов и каталогов: