oldi

Советы тем, кто программирует на VB & VBA

Андрей Колесов, Ольга Павлова

Совет 298. Быстрый своппинг строковых переменных

Совет 299. Динамическое управление меню

Совет 300. Используйте каталог Template

Совет 301. Используйте Microsoft Forms 2.0 Form (когда это нужно)

Совет 302. Используйте элемент управления IE Timer

Совет 303. Как погрузить приложение в «глубокий сон»

Совет 304. Управление расстоянием между столбцами в ListBox

Совет 305. Где хранятся настройки панелей инструментов MS Office

     Word

     Excel и PowerPoint

     Outlook и FrontPage

     Access

Совет 306. Управление порядком перемещения по элементам управления

Совет 307. Как удалить каталог

Совет 308. Как удалить непустой каталог

Совет 298. Быстрый своппинг строковых переменных

Для обмена данными между двумя строковыми переменными можно использовать такую простую процедуру:

Sub SwapString (String1$, String2$)
    Dim Save$
    Save = String1$ ' запись в промежуточную переменную
    String1$ = String2$
    String2$ = Save$
End If

Однако мы уже неоднократно подчеркивали, что операции присвоения строковых переменных требуют довольно много времени, так как это связано с динамическим перерезервированием оперативной памяти. Кроме того, время их выполнения напрямую зависит от длины строк.

Мы предлагаем «хитрый» вариант взаимного обмена содержимого двух строк, который выполняется очень быстро и не зависит от числа байтов в строке. Он основан на использовании API-функции для копирования областей памяти и применении реально существующих, но не описанных в документации функций VB (так называемые недокументированные функции):

Declare Sub CopyMemory Lib "kernel32" Alias _
     "RtlMoveMemory" (Destination As Any, _
     Source As Any, ByVal Length As Long)
    
Public Sub SwapSrting(String1$, String2$)
    Dim Save As Long
    'Своппинг двух строковых переменных
    Save = StrPtr(String1)
    Call CopyMemory(ByVal VarPtr(String1), ByVal VarPtr(String2), 4)
    Call CopyMemory(ByVal VarPtr(String2), Save, 4)
End Sub

Как известно, в VB строковые переменные имеют описатель (дескриптор) и собственно содержимое строки. В данном случае мы выполняем своппирование не содержимого строк, а содержимого описателей. Для этого используются две недокументированные VB-функции:

StrPrt — возвращает четырехбайтовый адрес содержимого строки;

VarPrt — возвращает четырехбайтовый адрес дескриптора.

Здесь нужно отметить два момента:

  1. Такой прием можно использовать только для своппинга — операцию присвоения строковой переменной таким образом делать нельзя (недопустимо, чтобы одна и та же строка данных использовалась в двух разных дескрипторах).
  2. В VB описатель строки содержит только адрес ее содержимого. Число байтов строки находится в четырех байтах, которые хранятся непосредственно перед этим содержимым, то есть функция LenB(MyString$) может быть реализована в виде такой конструкции:
Dim LenBmy&
Call CopyMemory(LenBmy$, ByVal StrPtr(MyString$) - 4, 4)

Тем, кто еще пользуется QuickBasic для DOS, напомним, что здесь длина строки хранится в ее описателе вместе с адресом. Но нужно иметь в виду, что адресация строк в QB 4.x и PDS 7.x различается, и соответственно различаются описатели строк. Адрес дескриптора можно получить командами VARSEG (адрес сегмента) и VARPRT (смещение внутри сегмента); копирование областей памяти производится командами PEEK (чтение байта) и POKE (запись байта).

В начало

В начало

Совет 299. Динамическое управление меню

Многие программисты порой забывают о том, что меню, создаваемое с помощью Menu Editor, состоит из компонентов, которые работают так же, как и все остальные элементы управления. Это, в частности, позволяет непосредственно в процессе работы приложения управлять пользовательским интерфейсом. Так, можно изменять название команды меню (свойство Caption), делать ее недоступной для выполнения (Enable) или невидимой (Visible). Если же вы создали массив меню, назначив данному компоненту индекс (свойство Index), динамически создавать или удалять элементы такого массива, можно, например, следующим образом:

i% = mnuFileArray.Ubound + 1  ' следующий номер индекса после самого большого уже существующего
Load mnuFileArray(i%)  ' создание нового элемента массива меню
mnuFileArray(i%).Caption = "NewArray" & i%  '  название команды
...
Unload mnuFileArray(1)        ' удалить элемент с индексом 1

Совет 300. Используйте каталог Template

Если у вас есть VB-проект, который вы хотите хотя бы иногда использовать в качестве шаблона при создании новых проектов, поместите его в каталог ...\VisualStudio\VB98\Template\Projects\ или другой каталог, который вы указали при установке VB 6.0. (Для VB 5.0 этот каталог называется VB5\Template\Projects\.)

Тогда ваш шаблон будет автоматически появляться в окне New Project при создании нового проекта.

Такой вариант создания нового проекта на основе шаблона лучше, чем простая загрузка существующего проекта командой Open, ибо в последнем случае есть опасность забыть, что необходимо обязательно сразу же сохранить проект и все его компоненты командой Save As, иначе все изменения проекта будут записываться в исходный шаблон.

Точно так же вы можете записать шаблоны для отдельных компонентов проекта, которые хранятся в подкаталоге Template:

 

Template/Подкаталог

При выполнении команды Project/Add компонент

FORMS

Form

MDIForms

MDI Form

MODULES

Modules

CLASSES

Class Modules

USERCTLS

User Control

PROPPAGE

Property Page

USERDOCS

User Document

В начало

В начало

Совет 301. Используйте Microsoft Forms 2.0 Form (когда это нужно)

Если вы хотите создавать программные компоненты формы (модули формы), которые можно использовать как в VB, так и в Office/VBA, то вам нужно пользоваться конструктором MS Forms 2.0. В среде VBA он вызывается командой Insert|UserForm, в среде VB — Project|Add Microsoft Forms 2.0 Form (если такая команда отсутствует в среде VB, то конструктор нужно подключить с помощью команды Project|Components|Designers).

Напомним, что формы UserForms в VBA – это не то же самое, что VB-формы (Ruby Forms). VBA UserForms являются экземплярами ActiveX-конструктора Microsoft Forms 2.0 (FM20.dll), который входит в состав как VB, так и VBA. Более того, все элементы управления, представленные в нем по умолчанию, являются не встроенными, а ActiveX-компонентами (то есть при желании их можно подключить и к VB-форме). Чтобы убедиться в этом, откройте окно Tools|Additional Controls.

К сожалению, эти два вида форм различаются не только форматом их модулей. Каждая из них использует свой собственный набор встроенных элементов управления. Проблема же заключается в том, что эти наборы не только не совпадают функционально, но даже для одинаковых по значению элементов управления используются разные наименования свойств, событий и методов. MS Forms 2.0 не поддерживают ряд очень полезных встроенных элементов управления VB (Timer, FileListBox, PictureBox, DriveListBox, DirListBox, Menu, Shape и Line), но при этом включают другие полезные компоненты (TabStrip, MultiPage) и команды проектирования формы (TabOrder).

В начало

В начало

Совет 302. Используйте элемент управления IE Timer

Отсутствие встроенных элементов управления (на что мы сетовали в предыдущем совете) можно компенсировать возможностью использования дополнительных элементов управления ActiveX. Если у вас имеется VB 5.0 или 6.0, то вы можете самостоятельно сделать, например, на основе встроенного элемента Timer собственный ActiveX-компонент для реализации функции таймера. Такой OCX можно было бы использовать в конструкторе MS Forms 2.0 (VBA-формы). Но прежде чем делать свои компоненты, стоит посмотреть, нет ли уже готового подходящего элемента на Web-сайтах с VB-ресурсами и разными Freeware & Shareware.

Так, очень нужный порой компонент Timer в виде файла IETimer.OCX можно найти по адресу www.visual.2000.ru/develop/vb/source/.

Но здесь мы хотели бы отметить некоторые различия в процедурах подключения OCX к среде VB и VBA.

  1. Обычно OCX-компоненты помещаются в системный каталог Windows/System/. Однако мы рекомендуем размещать такие дополнительные файлы в каком-нибудь специально созданном для этого пользовательском подкаталоге. Это упростит процедуры «чистки мусора» и обновления версий компонентов, так как можно будет четко следить за тем, что вы записали сами, а что автоматически прописали в System операционная система и программы установок разных приложений.
  2. Далее необходимо зарегистрировать OCX-файл. Лучше всего это сделать с помощью утилиты RegSvr32.exe, которая входит в состав VB и Office (проще всего скопировать ее в подкаталог с вашими OCX):

    RegSvr32.exe Your.OCX

  3. Подключение к панели Toolbox для VB- и VBA-форм несколько различается.
    1. для VB-форм (в среде VB) выберите команду Project|Components, а потом во вкладке Controls установите флажок IE Timer (в данном случае зарегистрировать OCX можно, подключив нужный файл с помощью кнопки Browse);
    2. в среде Office/VBA также имеется команда (и диалоговое окно) Insert|Components|Controls, но зачем она здесь присутствует, куда подключаются выделенные элементы управления, — этого мы не поняли.

    Для подключения дополнительного элемента управления в среде VBA выберите команду Tools|Additional Controls. К ней можно также обратиться с помощью контекстного меню, которое появляется после щелчка правой кнопкой мыши панели Toolbox (только так и можно сделать, работая с MS Forms 2.0 в среде VB). Но проблема в данном случае заключается в том, что имя искомого компонента будет другим — Timer Object.

  4. Не менее интересна процедура отключения дополнительного компонента. Для VB-форм нужно войти в окно Components|Controls и убрать в нем флажок. Для VBA-форм эту же операцию можно сделать в окне Additional Controls. Только проще — щелкнуть правой кнопкой мыши на изображении компонента на панели Toolbox и выбрать команду Delete. Кстати, с помощью этого же меню в данном случае можно изменить название и изображение пиктограммы элемента управления (рис. 1).
  5. ще один вопрос — как убрать имя ненужного компонента из списков в окнах Components|Controls и Additional Controls. Отменить регистрацию OCX (вернее, любого ActiveX-компонента) можно с помощью той же утилиты RegSvr32:

    RegSvr32.exe /u Your.OCX

Но иногда оказывается, что этого недостаточно, и приходится вручную просматривать (искать заданный файл) и чистить Реестр.

В начало

В начало

Совет 303. Как погрузить приложение в «глубокий сон»

Мы уже приводили несколько советов, как можно приостановить выполнение приложения на некоторое время. В частности, это можно сделать с помощью элемента управления Timer или путем опроса текущего времени (обращения к функции Timer) в цикле программы. Однако оба варианта имеют некоторые ограничения. Например, элемент управления Timer позволяет делать задержку в диапазоне от 1 секунды до 1 минуты, а функция Timer имеет минимальную дискретность в 1 секунду. При использовании соответствующей API-функции этих ограничений нет:

' описание функции
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
' обращение к ней (аргумент задается в миллисекундах)
Sleep 150010 ' ожидание 150,01 секунды

Но при использовании этой конструкции есть другая проблема — «глубокий сон» приложения не удастся прервать до истечения заданного интервала времени.

В начало

В начало

Совет 304. Управление расстоянием между столбцами в ListBox

С помощью API-функции SendMessage вы можете управлять позициями табулятора в элементе управления ListBox. Это может быть полезно, если каждая строка списка состоит из полей, разделенных символом Tab (код ASCII = 9), то есть если список выводится в виде таблицы, содержащей несколько колонок. Для этого в программный модуль запишите такое объявление и подпрограмму:

Private Declare Function SendMessage Lib _
    "user32" Alias "SendMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, lParam As Any) As Long
Private Const LB_SETTABSTOPS = &H192
Public Sub SetListTabStops(MyListBox As ListBox, _
                     ParamArray ParmList() As Variant)
        'Коррекция позиции Tabs в списке ListBox
        '
        ' Для передачи переменного числа однородных параметров
        ' используется конструкция ParamArray
        ' ВНИМАНИЕ! Нижний индекс ParmList равен 0
        ' даже при Option Base 1!!!
        ' Позиция табулятора определяется в специальных величинах
        ' окна, которая в среднем равна 1/4 символа
        
        Dim i As Long
        Dim NumColumns As Long
        '
        ' формирование массива для установки табуляторов
        ReDim ListTabs(0 To UBound(ParmList)) As Long
        For i = 0 To UBound(ParmList)
    
                ListTabs(i) = ParmList(i)
        Next i
        NumColumns = UBound(ParmList) + 1
        '
        ' установка новых значений позиций табулятора
        Call SendMessage(MyListBox.hWnd, LB_SETTABSTOPS, _
         NumColumns, ListTabs(0))
        ' вывести новое изображение списка
        lstMyListBox.Refresh
End Sub

Чтобы протестировать эту конструкцию, создайте форму, на которой разместите элемент списка lstMyListBox и две командные кнопки Command1 и Command2. Далее запишите такой программный код для этих компонентов:

Private Sub Form_Load()
     ' Начальное формирование списка
     ' с тремя колонками, разделенными символом vbTab = Chr$(9)
     lstMyListBox.AddItem "Колонка11" & vbTab & "Колонка12" _
            & vbTab & "Колонка13"
     lstMyListBox.AddItem "C21" & vbTab & "C22" _
            &  vbTab & "C23"
End Sub
Private Sub Command1_Click()
    ' одинаковое расстояние в 52 позиции (13 символов)
    Call SetListTabStops(lstMyListBox, 52)
End Sub
Private Sub Command2_Click()
    ' переменное расстояние (10 и 30 символов)
    Call SetListTabStops(lstMyListBox, 40, 120)
End Sub

Запустите на выполнение созданный проект, и вы увидите такое изображение списка (рис. 2)

Щелкните кнопку Command1 — список примет следующий вид (рис. 3)

Щелкните Command2, и получится другое изображение (рис. 4)

В начало

В начало

Совет 305. Где хранятся настройки панелей инструментов MS Office

Как известно, пользователь MS Office 97/2000 может выполнять различные операции по настройке меню и панелей инструментов среды — модифицировать, удалять и добавлять команды и панели. Это можно делать как с помощью команды Настройка (Customize), так и программным образом (VBA). Но где хранятся эти настройки, как они связаны с обрабатываемыми документами? Это полезно знать, особенно если вы хотите перенести эти настройки на другой компьютер. Тем более что реализация механизма сохранения настроек для всех офисных приложений различная (это к вопросу о том, что MS Office представляет собой как бы единое семейство продуктов).

Word

Это приложение обладает наиболее удобной и гибкой системой настроек. Как известно, VBA-проекты хранятся в документах или шаблонах Word. В них же хранятся и настройки панелей инструментов, и пользователь может сам выбирать, в каком именно файле они будут записаны.

Таким образом можно реализовать самые разнообразные варианты подключения расширений пользовательской среды. Если записать эти настройки в глобальный шаблон (например, в Normal.dot), то данные команды будут доступны при работе со всеми документами в данной сессии. При сохранении установок в конкретный документ они будут применяться только в нем. Если же настройки включены в присоединенный шаблон, они будут появляться во всех документах, которые его используют.

Excel и PowerPoint

В этих двух приложениях макрокод хранится в документах (рабочих книгах и презентациях), а сами настройки панелей инструментов — в фиксированных файлах. Для версии 97 это соответственно файлы <username>.xlb и <username>.pcb в каталоге Windows, для версии 2000 — файлы Excel\Excel.xlb и PowerPoint\ppt.pcb, которые находятся в каталоге Windows\Application Data\Microsoft\. Таким образом, получается, что пользователь может работать только с одним фиксированным вариантом настроек панелей инструментов.

Но в этих приложения механизм работы команд несколько различается. Для примера напишите такую макрокоманду:

Sub Hello
    MsgBox "Hello!"
End Sub

которую запишите в книгу Hello.xls и презентацию Hello.ppt. Соответственно в Excel и PowerPoint сделайте кнопку на панели инструментов для обращения к этим макрокомандам. Затем перезагрузите Excel: на панели инструментов будет видна ваша кнопка, хотя программный код для нее не загружен. Нажмите кнопку — произойдет загрузка Hello.xls и выполнится макрокоманда. Теперь повторите те же действия для PowerPoint — макрокоманда выполнится, но презентация не загрузится в среду приложения.

В Excel можно скопировать созданные пользователем панели инструментов в рабочую книгу (со встроенными это проделать нельзя!). Это делается с помощью диалогового окна Attach Toolbars (вызывается командой Attach на вкладке ToolBars окна Customize) — программным образом с применением VBA это сделать нельзя.

После копирования можно удалить пользовательские панели из среды самого Excel с помощью команды Delete окна Customize или метода Delete коллекции CommandBars. Удалить панель из рабочей книги можно только с помощью диалогового окна.

Важное замечание. Когда вы открываете рабочую книгу, производится автоматическое копирование пользовательских панелей из книги в среду Excel (но только в том случае, если панелей с такими именами не было в самом приложении!). При этом следует иметь в виду, что при закрытии рабочей книги эти панели остаются в Excel. Поэтому, если вы хотите, чтобы подобные компоненты появлялись только в сеансе работы с данной рабочей книгой, вы можете программным образом сделать удаление панели при закрытии книги. Если же вы не удалите пользовательскую панель из Excel и будете корректировать ее, то в последующих сеансах вы будете работать именно с ней (копирование из рабочей книги не будет выполняться).

Outlook и FrontPage

В этих двух приложениях все сделано еще проще: программный код хранится в строго фиксированных проектах — Outlook\VbaProject.OTM и FrontPage\Macros\Microsoft FrontPage.fpm, а настройки среды — в столь же фиксированных Outlook\outcmd.dat и FrontPage\State\cmpUI.prt. Все это, в свою очередь, находится в подкаталоге Windows\Application Data\Microsoft\.

Примечание. Для приложений Excel, PowerPoint, Outlook и FrontPage каталог Windows\Application Data\Microsoft\ используется только в случае однопользовательского режима. Если же в операционной системе установлен многопользовательский режим с использованием различных профилей, то в этом случае используется каталог Windows\Profiles\Username\Application Data\Microsoft\.

Access

В документах Microsoft пользовательские настройки встроенных панелей инструментов среды Access хранятся в «специальной базе данных». Наши исследования показали, что эта база — Реестр Windows, хранящийся по адресу: HKCU\Software\Microsoft\Office\9.0\Access\Settings\Commandbars\. Но что и как туда пишется — нам разобраться не удалось. Панели же инструментов, создаваемые с помощью Access, хранятся в файлах этой базы данных.

В начало

В начало

Совет 306. Управление порядком перемещения по элементам управления

Как известно, перемещение фокуса от одного элемента управления к другому можно выполнять с помощью клавиатуры: Tab (вперед) или Shift+Tab (назад). Порядок передвижения определяется значением свойства TabIndex элементов управления, который начинается с нуля и для каждого размещаемого на форме элемента управления увеличивается на единицу. Свойство TabIndex, конечно же, имеется только у видимых компонентов (у Timer его нет). Пассивные визуальные компоненты типа Label имеют свойство TabIndex, но фактически не используют его — при перемещении по форме такие элементы автоматически пропускаются.

Для изменения последовательности обхода визуальных компонентов (она редко совпадает с тем порядком, в котором мы создавали диалоговый интерфейс) нужно менять свойства TabIndex. Это можно делать вручную, напрямую корректируя параметры в окне Properties. Обратите внимание, что ошибка использования одного и того же значения TabOrder для разных компонентов здесь исключена за счет автоматической перенумерации.

Пусть, например, у вас имеются четыре компонента с номерами 0, 1, 2, 3. Для последнего вы решили установить TabOrder=1. В этом случае автоматически изменятся значения свойств TabOrder для двух элементов управления: 1->2, 2->3.

Однако гораздо удобнее использовать специальные визуальные средства управления перемещения по элементам формы. Как мы отмечали в совете 301, конструктор MS Forms 2.0 (в среде VB и VBA) для этого использует специальную встроенную команду TabOrder. Чтобы воспользоваться ею, щелкните правой кнопкой мыши форму и в появившемся контекстом меню выберите команду Tab Order. В появившемся одноименном диалоговом окне выделите нужные компоненты и с помощью кнопок Move Up и Move Down передвиньте их в нужную позицию списка, который определяет порядок перемещения (рис. 306-1).

Для обычных VB-форм такой встроенной команды нет, и по этому поводу мы уже выказывали свое недовольство в адрес разработчиков из Microsoft. Однако мы были не правы — такие визуальные средства имеются в VB 5 и VB 6 в виде автономного дополнения TabOrder (исходный код этого проекта находится в подкаталоге ...\MSDN98\98VS\1033\Samples\VB98\TabOrder\ для VB6 или в ...\Samples\CompTool\AddIns\TabOrder\).

Чтобы сделать Add-In (на примере VB 6.0), загрузите проект TabOrder.VBP и

выполните команду File|Make TabOrder.DLL. В результате вы не только создадите исполняемый модуль, но и зарегистрируете новое дополнение, которое появится под названием Tab Order Sample Addin в окне Add-Ins|Add-In Manager среды Visual Basic. Для работы с TabOrder необходимо обычным образом установить режим загрузки в этом окне, и тогда на панели инструментов VB появится кнопка TabOrder Window для запуска этого дополнения (рис. 306-2).

Примечание. При работе в VB 5 для включения TabOrder (созданного в этой же среде!) в окно Add-In Manager необходимо добавить в секцию [Add-Ins32] файла VBADDIN.INI строку TabOrder.Connect=0.

Теперь создайте в VB какой-нибудь тестовый пример с формой, на которой разместите несколько разных элементов управления, и щелкните кнопку TabOrder Window. В появившемся окне (рис. 306-3) можно корректировать последовательность перемещения по элементам управления формы. Однако здесь имеются дополнительные функции, которых нет в аналогичной утилите MS Forms 2.0. Обратите внимание, что на нашей тестовой форме все элементы управления расположены на разных расстояниях от верхней и правой границ формы. С помощью соответствующих кнопок на панели инструментов можно упорядочить список по вертикальному (рис. 306-4) или горизонтальному (рис. 306-5) расположению визуальных компонентов. Кроме того, программист без перезагрузки этой утилиты может восстановить исходную последовательность списка.

Вообще, мы рекомендуем внимательно изучить проект TabOrder, так как он представляет собой интересный пример создания Add-In, использования User-документов и ресурсных файлов.

Но один вопрос все же остается — зачем нужно было делать для VB-форм и MS Forms 2.0 две похожие, но тем не менее разные утилиты?

В начало

В начало

Совет 307. Как удалить каталог

VB содержит довольно много встроенных функций и операторов для управления файлами и каталогов. Совершенно очевидно, что эти средства работают через Win API, и понятно, что последние обладают более широкими возможностями. Чаще всего встроенные функции VB реализуют усеченный вариант соответствующей API-функции (например, оператор MkDir представляет собой частный случай функции CreatDirectory). Многие же возможности API вообще не представлены в виде VB-операторов. В частности, это относится к операции удаления каталогов, которая может быть выполнена таким образом:

Private Declare Function RemoveDirectory& Lib "kernel32" Alias  _
        "RemoveDirectoryA" (ByVal lpPathName As String)
    
    ' Удаление каталога (пустого!)
    PathName$ = "D:\t\"    ' в конце имени "\" необязательна
    '
    code& = RemoveDirectory(PathName)
    If code& = 0 Then
        ' операция удаления не была выполнена
    Else
        ' каталог удален
    End If

Здесь нужно обратить внимание на несколько моментов:

  1. Удаляемый каталог должен быть пустым.
  2. Имя каталога не обязательно должно заканчиваться на "\" — операция будет успешно выполнена с именем "D:\t".
  3. Почему-то при наличии ошибки обращение к функции GetLastError выдает исключительно 0 (то есть нельзя уточнить характер ошибки).
В начало

В начало

Совет 308. Как удалить непустой каталог

Но как удалить каталог, если в нем находятся файлы и вложенные подкаталоги? Для этого потребуется написать процедуру DeleteDir, которая будет перед удалением каталога просматривать и удалять его содержимое. Обращение к ней может выглядеть следующим образом:

Dim DirCount%, FileCount% ' число удаленных каталогов и файлов
    '
    DirName$ = "d:\t\"
    '
    DirCount = 0: FileCount = 0    ' начальная установка
    Result& = DeleteDir&(DirName$, DirCount%, FileCount%)
    ' Result = 0 - удален

А сама процедура будет содержать такой код:

Public Function DeleteDir&(DirName$, DirCount%, FileCount%)
    '
    ' Удаление каталога со всем его внутренним содержанием
    
    ' ВХОД:
    '     DirName$ -- имя удаляемого каталога
    ' ВЫХОД:
    '    DeleteDir - код завершения (0 - удален, <>0 - не удален
    '    DirCount, FileCount -- текущее число удаленных каталогов и файлов
    '    (перед первым обращении эти переменные должны быть обнулены)
    '
    Dim Result&
    '
    ' 1. Удалить все внутри каталога
    Call DeleteDirAll(DirName$, DirCount%, FileCount%, Result&)
    If Result = 0 Then ' без ошибок
        ' 2. удалить сам каталог
        Result = RemoveDirectory(DirName$)
        If Result = 0 Then
            Result = -1
Else: Result = 0: DirCount = DirCount + 1
        End If
    End If
    DeleteDir = Result ' код завершения
End Function

Но очевидно, что ключевой задачей здесь является написание процедуры DeleteDirAll, которая будет удалять внутреннее содержание каталога — файлы и подкаталоги. Тут не обойтись без использования рекурсии, и поэтому полезно вспомнить наши советы 229-231. Более того, нам понадобится готовый код подпрограммы CurrentDirCounter («как есть»), а также продпрограмма FileNameCase, которую можно использовать в качестве заготовки и создать DeleteDirAll:

Public Sub DeleteDirAll(DirName$, DirCount%, FileCount%, Result&)
    '
    ' Удаление всех файлов и подкаталогов заданного каталога
    '
    ReDim arrFile$(100) ' для имен элементов оглавления
    Dim CountFile%, NewPathName$, i%
    '
    On Error GoTo ErrorDeleteFile
    ' формируем список файлов каталога
    Call CurrentDirCounter(DirName$, "*.*", CountFile%, arrFile$(), 0)
        ' удаление файлов
    If CountFile > 0 Then    ' есть файлы в подкаталоге
        For i = 1 To CountFile
            Kill DirName$ & arrFile$(i) ' удалить файл
            FileCount = FileCount + 1 ' счетчик удаленных файлов
        Next
    End If
    'формирование списка подкаталогов
    Call CurrentDirCounter(DirName$, "", CountFile%, arrFile$(), vbDirectory)
    If CountFile > 0 Then    ' есть подкаталоги
        For i = 1 To CountFile
            ' формирование имени вложенного подкаталога
            NewPathName$ = DirName$ + arrFile$(i) + "\"
            '!! рекурсивное обращение к функции удаления каталога
            ' с новым именем, но старыми значениями счетчиков
            Result = DeleteDir&(NewPathName$, DirCount%, FileCount%)
            If Result <> 0 Then Exit Sub ' была ошибка
        Next
    End If
Exit Sub
ErrorDeleteFile:
    Result = Err ' ошибка при удалении файла
End Sub

КомпьютерПресс 8'2000