На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual Basic: Общие вопросы
Здесь обсуждаются вопросы по языку Visual Basic 1-6 (а так же по схожим языкам, как, например, PowerBASIC).
Вопросы по Visual Basic .NET (это который входит в состав Visual Studio 2002/2003/2005/2008+, для тех, кто не в курсе) обсуждаются в разделе .NET.

Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что Вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются. Студенты, вам сюда: ПОМОЩЬ СТУДЕНТАМ!
4. Используйте теги [ code=vba ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Формулируйте свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной (и более) давности, без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта user posted image FAQ Раздела user posted image Кладовка user posted image Наши Исходники user posted image API-Guide user posted image Поиск по Разделу user posted image MSDN Library Online user posted image Google

Ваше мнение о модераторах: user posted image SCINER, user posted image B.V.
Модераторы: SCINER, B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Visual Basic. User Defined Types , Статья: Типы данных определяемые пользователем. Создание и использование
    Visual Basic
    User Defined Types

    Типы данных определяемые пользователем
    Создание и использование

      Содержание

    • UDT – создание
    • UDT – объявление переменных
    • UDT – присвоение и получение значений
    • UDT – содержащий массив
    • UDT – аргумент процедуры
    • UDT – содержащий объект
    • UDT – составной
    • UDT – копирование

    UDT – создание

    Кроме базовых типов данных: Integer, Long, String и т.д., Visual Basic поддерживает типы данных, определяемые пользователем – User Defined Types (далее UDT). Комбинируя переменные различных типов, можно создать UDT (известный, в языке программирования Cи, как структура). UDT используется, для создания переменной, содержащей несколько взаимосвязанных частей информации.

    Для создания UDT используется ключевое слово Type:
    ExpandedWrap disabled
      'Синтаксис VB
                    [Private | Public] Type TypeName
                                   Element1 [([Size])] As DataType
                                   [Element2 [([Size])] As DataType]
                    End Type

    Определение общего (Public) UDT, возможно только в секции (General) (Declarations) модуля. В этом случае, тип будет доступен во всех процедурах всех форм, модулей и модулей классов. Для определения UDT в форме или модуле класса, следует использовать ключевое слово Private, поскольку объявление общего типа в данной ситуации не допускается. При этом, область видимости такого типа, будет ограничена контейнером, где он объявлен.
    ExpandedWrap disabled
                    Private Type MyDataType

    или
    ExpandedWrap disabled
                    Public Type MyDataType

    Например, можно создать UDT, содержащий информацию о компьютере:
    ExpandedWrap disabled
      ' Декларация в стандартном модуле
                    Private Type SystemInfo
                                  CPU As Variant
                                  Memory As Long
                                  VideoColors As Integer
                                  Cost As Currency
                                  PurchaseDate As Variant
                    End Type

    UDT – объявление переменных

    Определив UDT, вы можете использовать его для объявления переменных этого типа. Эти переменные могут быть локальными, глобальными или переменными контейнера:
    ExpandedWrap disabled
                    Dim MySystem As SystemInfo
                    Private YourSystem As SystemInfo

    Таблица 1. Контейнеры, где можно объявить UDT и его переменную.
    Процедура (Модуль)UDTПеременная UDT
    ПроцедураНе применяетсяТолько Local
    Стандартный модульPrivate или PublicPrivate или Public
    Модуль формыТолько PrivateТолько Private
    Модуль классаPrivate или PublicPrivate или Public

    Примечание! UDT, объявленный без ключевого слова, по умолчанию считается объявленным, как Public. Если требуется UDT уровня модуля или модуля класса, его следует объявлять, используя ключевое слово Private.

    UDT – присвоение и получение значений

    Доступ к элементам переменной UDT осуществляется, по аналогии с доступом к свойствам, путем указания точки после имени переменной.
    ExpandedWrap disabled
                    MySystem.CPU = "486"
                    If MySystem.PurchaseDate > #1/1/92# Then

    При этом переменные одинакового типа можно присваивать не поэлементно, а напрямую:

    ExpandedWrap disabled
                    YourSystem = MySystem

    UDT – содержащий массив

    UDT, может содержать обычный (фиксированного размера) массив:
    ExpandedWrap disabled
                    Type SystemInfo
                                  CPU As Variant
                                  Memory As Long
                                  DiskDrives(25) As String              ' Фиксированный массив
                                  VideoColors As Integer
                                  Cost As Currency
                                  PurchaseDate As Variant
                    End Type

    А также, может содержать динамический массив.
    ExpandedWrap disabled
                    Type SystemInfo
                                  CPU As Variant
                                  Memory As Long
                                  DiskDrives() As String ' Динамический массив
                                  VideoColors As Integer
                                  Cost As Currency
                                  PurchaseDate As Variant
                    End Type

    Доступ к значениям элементов массива, UDT осуществляется, по аналогии с доступом к свойству объекта.
    ExpandedWrap disabled
                    Dim MySystem As SystemInfo
                    ReDim MySystem.DiskDrives(3)
                    MySystem.DiskDrives(0) = "1.44 MB"

    Также, можно объявить массив UDT:
    ExpandedWrap disabled
                    Dim AllSystems(100) As SystemInfo

    Для доступа к элементам этого типа, следуем тем же правилам.
    ExpandedWrap disabled
                    AllSystems(5).CPU = "386SX"
                    AllSystems(5).DiskDrives(2) = "100M SCSI"

    UDT – аргумент процедуры

    UDT можно использовать, как один из аргументов процедуры.
    ExpandedWrap disabled
                    Sub FillSystem (SomeSystem As SystemInfo)
                                  SomeSystem.CPU = lstCPU.Text
                                  SomeSystem.Memory = txtMemory.Text
                                  SomeSystem.Cost = txtCost.Text
                    SomeSystem.PurchaseDate = Now
                    End Sub

    Примечание! При использовании UDT, в качестве аргумента процедуры в модуле формы, процедура должна быть объявлена, как Private.

    UDT, можно использовать в качестве возвращаемого значения функции, а пользовательскую переменную в качестве одно из аргументов процедуры. UDT всегда передаются по ссылке (ByRef), так что процедура может изменить аргумент и вернуть его в вызываемую функцию.

    Примечание! Поскольку UDT всегда передается по ссылке, все данные, будут переданы и получены без проблем. Для UDT, содержащих большие массивы данных, это может привести к снижению производительности, особенно в архитектуре клиент-серверных приложений, где процедура может быть запущена на удаленной машине. В такой ситуации, лучше, принимать и передавать только необходимые данные полей UDT.

    UDT – содержащий объект

    UDT, может содержать объект.
    ExpandedWrap disabled
                    Private Type AccountPack
                                  frmInput as Form
                                  dbPayRollAccount as Database
                    End Type

    Примечание! Поскольку тип Variant может хранить различные типы данных, массив Variant может быть использован во многих ситуациях, где можно использовать UDT. Массив Variant, на самом деле более гибкий, чем UDT, потому что можно изменить тип данных, хранящихся в каждом его элементе в любое время, и можно сделать массив динамическим, и изменять размер по мере необходимости. Однако, массив Variant, всегда использует больше памяти, чем эквивалентные UDT.

    UDT – составной

    UDT, может быть составным. В этом случае важна последовательность определения UDT. Сначала нужно определить основной UDT, который будет использоваться далее в составных UDT. Если не соблюдать это правило, то после запуска программы появится сообщение об ошибке. Ниже приводится пример использования составных UDT:
    ExpandedWrap disabled
                    Type DriveInfo
                                  Type As String
                                  Size As Long
                    End Type
       
                    Type SystemInfo
                                  CPU As Variant
                                  Memory As Long
                                  DiskDrives(26) As DriveInfo
                                  Cost As Currency
                                  PurchaseDate As Variant
                    End Type
       
                    Dim AllSystems(100) As SystemInfo
                    AllSystems(1).DiskDrives(0).Type = "Floppy"

    UDT, рекомендуется использовать при обработке данных неизменной структуры.

    UDT – копирование

    Рассмотрим оператор Visual Basic – LSet
    ExpandedWrap disabled
      'Синтаксис VB
      LSet StringVariable = StringExpression

    LSet – выравнивает строку по левой стороне, при присваивании ей значения, меньшего по размеру, чем исходная строка. Вместо строк могут использоваться UDT.

    Вспомним базовые типы данных Visual Basic

    Таблица 2. Базовые типы данных Visual Basic
    Имя базового типаЗанимаемая память
    Boolean2 байта
    Byte1 байт
    Integer2 байта
    Long4 байта
    Decimal12 байтов
    Single4 байта
    Double8 байтов
    Currency8 байтов
    String10 байтов +1 байт на символ в обычной кодировке и 2 байта в кодировке Unicode
    Date8 байтов
    Object4 байта
    VariantЗависит от контекста, но не менее 16 байтов

    Определимся со значениями некоторых типов данных.

    • Boolean: может принимать – True или False (в Visual Basic – False, всегда принимает нулевое значение; True – любое значение отличное от нуля)
    • Decimal: не используется.
    • Object: ссылка на объект (указатель)
    • Variant: универсальный тип, значением которого могут быть данные любого из перечисленных выше типов, объекты, значения NULL, Empty и значения ошибок ERROR.

    Рассмотрим следующий пример:
    ExpandedWrap disabled
      'Объявление UDT
                    Private Type TypeExempleOne
                                  Element_1 As Integer
                                  Element_2 As Long
                    End Type
       
                    Private Type TypeExempleTwo
                                  Element_1 As Integer
                                  Element_2 As Long
                    End Type
       
      Private Sub CopyUDT()
      'Объявление переменных UDT
                    Dim teo As TypeExempleOne
                    Dim tet As TypeExempleTwo
       
      'Присваивание значений
                    teo.Element_1 = 11
                    teo.Element_2 = 1111111
       
                    tet.Element_1 = 22
                    tet.Element_2 = 222222
       
      'Выводим на печать присвоенные значения
                    Debug.Print "Значения до копирования"
                    Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
                    Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
       
      'Копируем один UDT в другой
                    LSet tet = teo
       
      'Выводим на печать значения после копирования
                    Debug.Print "Значения после копирования"
                    Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
                    Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
       
      End Sub

    В окне Immediate мы увидим следующие значения:
    Цитата
    Значения до копирования
    teo.Element_1 = 11 teo.Element_2 = 1111111
    tet.Element_1 = 22 tet.Element_2 = 222222
    Значения после копирования
    teo.Element_1 = 11 teo.Element_2 = 1111111
    tet.Element_1 = 11 tet.Element_2 = 1111111

    При копировании UDT надо придерживаться следующих правил:

    • Общий размер структуры и типы данных соответствующих элементов совпадают
    • Общий размер структуры и размер типов соответствующих элементов совпадают

    Немного изменим пример:
    ExpandedWrap disabled
      'Объявление пользовательских типов
                    Private Type TypeExempleOne
                                  Element_1 As Integer
                                  Element_2 As Long
                    End Type
       
                    Private Type TypeExempleTwo
                                  Element_1 As Boolean
                                  Element_2 As Long
                    End Type
       
      Private Sub CopyUDT()
      'Объявление переменных пользовательского типа
                    Dim teo As TypeExempleOne
                    Dim tet As TypeExempleTwo
       
      'Присваивание значений
                    teo.Element_1 = 11
                    teo.Element_2 = 1111111
       
                    tet.Element_1 = False
                    tet.Element_2 = 222222
       
      'Выводим на печать присвоенные значения
      Debug.Print "Значения до копирования"
      Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
      Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
       
      'Копируем один тип данных в другой
      LSet tet = teo
       
      'Выводим на печать значения после копирования
      Debug.Print "Значения после копирования"
      Debug.Print "teo.Element_1 = " & teo.Element_1, "teo.Element_2 = " & teo.Element_2
      Debug.Print "tet.Element_1 = " & tet.Element_1, "tet.Element_2 = " & tet.Element_2
       
      End Sub

    В окне Immediate мы увидим следующие значения:
    Цитата
    Значения до копирования
    teo.Element_1 = 11 teo.Element_2 = 1111111
    tet.Element_1 = False tet.Element_2 = 222222
    Значения после копирования
    teo.Element_1 = 11 teo.Element_2 = 1111111
    tet.Element_1 = True tet.Element_2 = 1111111

    В первом примере, мы копировали полностью идентичные UDT, в изменённом – скопировали в Boolean переменную, значение тип Integer.
    Как видно из таблицы 2, тип Boolean занимает в памяти 2 байта. Тип данных Integer – 2 байта. Тип данных Long занимает в памяти 4 байта. Значит, общий размер каждого UDT, составляет 6 байт, мы не нарушили правил при копировании.

    Соответственно, зная размеры занимаемой памяти, базовых типов Visual Basic, можно легко определиться с копированием пользовательских типов данных.

    Например: Long(4 байта) = двухразрядный массив Integer(4 байт)

    Необходимое послесловие.

    В первоначальной версии, статья заканчивалась описанием базового типа Variant. Но его расширенное описание, вылилось в статью, по размерам превышающую настоящую. Статья о типе Variant находиться в завершающей стадии и скоро будет представлена.

    С уважением Diamock.
    Сообщение отредактировано: Diamock -
      В целом, неплохо. Что не понравилось:
      Упомянут, но не раскрыт тип Variant. Думаю, некоторых бы заинтересовало его внутреннее устройство
      Не затронута тема копирования UDT, посредством LSet, с оговорками о нюансах
        Цитата Diamock @
        Примечание! Пользовательский тип, объявленный с помощью ключевого слова Dim, по умолчанию считается объявленным, как Public. Если требуется пользовательский тип уровня модуля или модуля класса, его следует объявлять, используя ключевое слово Private.
        Всегда считал, что дим на уровне модуля - синоним привата :) Причем, при объявлении типа ты вообще не сможешь подставить слово Dim - это синтаксическая ошибка.

        Видимо, имелось ввиду, что если при объявлении типа не указано, приват он или паблик, то считается пабликом.
          Diamock, можешь учесть мои замечания?
            Цитата B.V. @
            Diamock, можешь учесть мои замечания?

            Конечно, сейчас разбираюсь с LSet и типом Variant. Как всё отложется в голове по полочкам, и примеры будут работать - дополню и исправлю.
              Цитата Diamock @
              Копировать один тип пользовательских данных в другой, можно при условии, что типы соответствующих элементов совпадают.

              Нет, копировать можно всегда. Но адекватный результат будет только при идентичности размеров полей, и общего размера структуры. Идентичность типов полей не обязательна. Так, к примеру, Integer поле прекрасно ляжет на массив из двух байт.

              Цитата Diamock @
              В методе Invoke() стоит предусмотреть проверку корректности типа значения

              Как не знающий про IDispatch интерфейс человек поймет, о чем это ты? Да и такое углубление в COM здесь, по-моему, неуместно
                Цитата B.V. @
                Как не знающий про IDispatch интерфейс человек поймет, о чем это ты? Да и такое углубление в COM здесь, по-моему, неуместно

                Тема типа данных Variant, меня очень заинтересовала, поэтому у меня в планах (в далёких, как только разберусь с сабклассингом, хуками и TLB) - написать расширенную статью о типе Variant.
                Также, продолжу изыскания о применении типа Variant в Visual Basic, и внесу изменения в статью.

                Статью, по поводу копирования, я подправлю, после экспериментов с LSet.
                  Цитата Diamock @
                  Тема типа данных Variant, меня очень заинтересовала

                  Тогда тебя, вероятно, заинтересуют и другие OLE-Automation типы, как SAFEARRAY. На RSDN уже есть подробная статья по этим двум комплексным типам: http://www.rsdn.ru/article/com/varsafearr.xml
                  Только просьба, если вздумаешь писать аналогичную, то не копипасть инфу оттуда, а попытайся изложить от себя
                  Цитата Diamock @
                  и внесу изменения в статью

                  Как внесешь, дай знать. Если ни у меня, и ни у кого-нибудь еще из участников претензий не будет, отправлю в ФАК

                  Давненько у нас такой подробный материал не добавлялся :)
                    B.V. Спасибо. Учту все замечания. :D
                      А мою ремарку ты чего проигнорировал?
                      Цитата Diamock @
                      Примечание! Пользовательский тип, объявленный с помощью ключевого слова Dim, по умолчанию считается объявленным, как Public. Если требуется пользовательский тип уровня модуля или модуля класса, его следует объявлять, используя ключевое слово Private.
                      Ну-ка, покажи, как объявить пользовательских тип с помощью дима?
                        Цитата Артур @
                        А мою ремарку ты чего проигнорировал?
                        Цитата Diamock @
                        Примечание! Пользовательский тип, объявленный с помощью ключевого слова Dim, по умолчанию считается объявленным, как Public. Если требуется пользовательский тип уровня модуля или модуля класса, его следует объявлять, используя ключевое слово Private.
                        Ну-ка, покажи, как объявить пользовательских тип с помощью дима?

                        Уважаемый Артур! Ваше замечание, я конечно не проигнорировал. Объявление с помощью Dim - вызывает ошибку :wall: . Я это проверил, просто не успел исправить, как и несколько других опечаток и неточностей. :'(
                        С уважением...
                          Здравствуйте Уважаемые!
                          Статья, отредактирована и частично переписана с учётом всех пожеланий.
                          С уважением...
                            Цитата Diamock @
                            String 10 байтов +1 байт на символ в обычной кодировке и 2 байта в кодировке Unicode

                            Как бы VB6 всегда использует Unicode и не понял как получилось 10 байт? 4 байта на длину строки + 2 байта на нул-терминэйт строки = 6 байт + по 2 байта на каждый символ. Или только если учитывается указатель на переменную стринг
                              VSHome
                              Цитата VSHome @
                              Как бы VB6 всегда использует Unicode и не понял как получилось 10 байт? 4 байта на длину строки + 2 байта на нул-терминэйт строки = 6 байт + по 2 байта на каждый символ. Или только если учитывается указатель на переменную стринг

                              Не понял вопроса? :-?
                                "как получилось 10 байт?"
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0995 ]   [ 15 queries used ]   [ Generated: 5.07.25, 14:37 GMT ]