Таблица 1 Не все так радужно, как может показаться на первый взгляд. В соответствии с тем, что Visual Basic .NET не поддерживает некоторых устаревших технологий, либо предоставляет несколько иную их поддержку, Upgrade Wizard для нескольких типов проектов не может провести миграцию кода в полном объеме. Проблемы возникают при попытке обновления проектов следующих типов:
Начинаем работу с Upgrade WizardПример всегда воздействует сильнее, чем проповедь. Для большей наглядности, создадим небольшое приложение на Visual Basic 6.0, над которым в дальнейшем и будем работать с помощью Upgrade Wizard. Пример будет достаточно прост и предназначен лишь для того, чтобы показать возможность Upgrade Wizard. 'frmParent Private Sub cColor_Click() frmColor.BackColor = CLng(cColor.Text) End Sub Private Sub cmdShow_Click() ShowForm CLng(cColor.Text), txtCaption.Text End Sub Private Sub Form_Load() cColor.Clear cColor.AddItem CStr(vbRed) cColor.AddItem CStr(vbGreen) cColor.AddItem CStr(vbBlue) cColor.AddItem CStr(vbYellow) cColor.AddItem CStr(vbMagenta) cColor.AddItem CStr(vbBlack) cColor.ListIndex = 0 End Sub Private Sub Form_Unload(Cancel As Integer) End End Sub 'modMain Public Sub ShowForm(mColor As Long, mCaption As String) Dim obj As frmChild Set obj = New frmChild obj.BackColor = mColor obj.Caption = mCaption obj.Show End SubРасположив на форме все необходимые элементы управления и установив все необходимые свойства мы получим следующую форму, приведенную на Рис. 1. Теперь, сохранив проект, либо загрузив с сайта журнала архив исходного кода, мы можем перейти к непосредственной работе с Upgrade Wizard. Для этого запустите Microsoft Visual Studio .NET3 и откройте проект. При этом отобразиться окно мастера Upgrade Wizard. Воспользуйтесь настройками по умолчанию. В результате мастер создаст новый проект Visual Basic .NET, содержащий измененный код. Прежде, чем приступить к изучению кода, обратимся к созданному мастером отчету о проделанной работе, где мы сможем обнаружить множество полезной информации. Отчет для нашего проекта приведен на Рис. 2. Что же приведено в отчете? Прежде всего здесь представлены сведения о всех файлах, для которых проводилась операция обновления и для каждого приведена подробная информация по обнаруженным проблемам при переносе кода. В Таблице 2 приведены возможные ошибки и предупреждения, которые обнаруживает Upgrade Wizard.
Таблица 2
Public Shared Property DefInstance() As frmParent Get If m_vb6FormDefInstance Is Nothing OrElse m_vb6FormDefInstance.IsDisposed Then m_InitializingDefInstance = True m_vb6FormDefInstance = New frmParent() m_InitializingDefInstance = False End If DefInstance = m_vb6FormDefInstance End Get Set m_vb6FormDefInstance = Value End Set End PropertyПоявление подобного свойства для главной формы в VB .NET связанно с тем, что в нем нет экземпляра класса по умолчанию, для обратной совместимости создается свойство указывающее на объект – «главная форма», создаваемый при запуске приложения. Следующим предупреждением является уведомление о том, что событие SelectedIndexChanged для списка cColor может вызываться автоматически при запуске приложения4. В нашем случае это не играет роли. Стоит обратить внимание, каким образом производиться преобразование текста в объект Color. 'UPGRADE_WARNING: Event cColor.SelectedIndexChanged may fire when form is intialized. Private Sub cColor_SelectedIndexChanged(ByVal eventSender As System.Object, ByVal eventArgs _ As System.EventArgs) Handles cColor.SelectedIndexChanged frmColor.BackColor = System.Drawing.ColorTranslator.FromOle(CInt(cColor.Text)) End SubАналогичные преобразования производятся и при добавлении различных значений цвета в список. 'UPGRADE_WARNING: Form event frmParent.Unload has a new behavior. Private Sub frmParent_Closed(ByVal eventSender As System.Object, ByVal eventArgs _ As System.EventArgs) Handles MyBase.Closed End End SubUpgrade Wizard сообщает о том, что события Unload для форм больше не существует и оно заменено на событие Closed, при этом воспользовавшись созданной мастером ссылкой5, вы можете узнать о новых «свойствах» события Closed. При возникновении события Unload была возможность остановить выгрузку формы, установив свойство Cancel в True, теперь же подобная возможность предусмотрена только для события Closing. Рассмотрим код функции в modMain: Public Sub ShowForm(ByRef mColor As Integer, ByRef mCaption As String) Dim obj As frmChild obj = New frmChild obj.BackColor = System.Drawing.ColorTranslator.FromOle(mColor) obj.Text = mCaption obj.Show() End SubUpgrade Wizard выполнил необходимые действия – добавил к вызову метода Show необходимые скобки, преобразование цвета, а также исправил значение типа переменной mColor в соответствии с типами .NET6. Как мы смогли убедиться, почти не понадобилось нашего вмешательства, чтобы привести проект в надлежащий вид. Конечно же, это слишком простой пример для обновления, но целью была лишь попытка показать работу мастера Upgrade Wizard. От рассмотрения примера перейдем к работе Upgrade Wizard в общем случае. Обновление файлов проектаОбновление проекта начинается с загрузки его в Upgrade Wizard. Соответственно, сам файл проекта с расширением .vbp является отправной точкой для мастера. Несмотря на то, что файлы проектов VB6.0 и VB.NET значительно отличаются по своему формату, но содержат ту же базовую информацию – название и версию проекта, список исходных файлов, информацию о разработчике, используемых компонентах. Помимо этого в проекте VB .NET также содержится информация о импортируемых пространствах имен и установках компилятора (по умолчанию для Debug и Release версий). В этом легко убедится, открыв файлы .vbp и .vbproj в текстовом редактореA href="#7>7.
Таблица 3
Обновление форм VB 6.0VB .NET использует принципиально новую технологию по работе с формами. Этой теме будет посвящена отдельная статья цикла, здесь же будут приведены лишь основные сведения по создаваемому Upgrade Wizard коду. ... Me.frmColor.Name = "frmColor" Me.cmdShow.Cursor = System.Windows.Forms.Cursors.Default Me.cmdShow.RightToLeft = System.Windows.Forms.RightToLeft.No Me.cmdShow.TabStop = True ... Me.cColor.CausesValidation = True ... Me.txtCaption.Size = New System.Drawing.Size(181, 20) Me.txtCaption.Location = New System.Drawing.Point(80, 43) ...Такой подход позволяет разработчику непосредственно «участвовать» в процессе создания и инициализации формы, что дает больше возможностей непосредственного управления процессом, окутанном туманом в VB 6.0. Если для контролов на форме существуют эквиваленты .NET, то они будут сопоставлены с сохранением всех свойств (за редким исключением) в соответствии с Таблицей 4. При отсутствии эквивалента, например в случае, с графическими контролами VB – Shape, разработчику придется вручную писать код, реализующий необходимую функциональность. При использовании ActiveX контролов ссылки на них будут сохранены и они будут использованы в .NET приложении также8, как и в приложении VB 6.0. За небольшим, но приятным исключением – SSTab контрол будет автоматически преобразован в TabControl с сохранением всех страниц и дочерних элементов.
Таблица 4 Обновление модулей и классовВсе модули и классы проекта будут автоматически обновлены до соответствующих в VB .NET, при функции, методы и свойства будут сохранены без изменений. При этом атрибуты классов будут сопоставлены следующим образом: Private будет изменен на Friend, а все остальные возможные на Public. Обновление кодаВот мы и дошли до момента, который больше всего интересует разработчиков – что же случится с моим кодом? Как мы могли убедиться на приведенном выше примере, несмотря на изменения, код по-прежнему можно узнать без особых усилий. В следующих статьях цикла будут рассмотрены непосредственно новый синтаксис и новые возможности языка, здесь же приведены основные изменения кода, которые происходят при миграции с использованием Upgrade Wizard. Поддержка обратной совместимостиНе всегда можно быстро и просто найти необходимый эквивалент элементам Visual Basic 6.0 в Visual Basic .NET. Порой такого эквивалента найти нельзя. Чтобы сократить затраты на переписывание кода, разработчики Майкрософт включили специальную библиотеку для поддержки совместимости с VB 6.0, которая находится в пространстве имен Microsoft.VisualBasic.Compatibility.VB6. При обнаружении подобных ситуаций Upgrade Wizard вставит код использующий объекты этого пространства имен. Но, не стоит злоупотреблять этой возможностью. При создании нового проекта или расширении существующего необходимо отказаться от использования содержимого Microsoft.VisualBasic.Compatibility.VB6. Предопределенные функцииПрежде всего, Upgrade Wizard сохраняет синтаксис там, где это возможно. Все языковые конструкции, поддерживаемые VB 6.0 и VB .NET одновременно остаются неизменными10, для элементов языка сопоставляются эквиваленты. Например: 'VB6 a = Cos(f) a = Sin(f) a = Sqrt(f) 'VB .NET a = System.Math.Cos(f) a = System.Math.Sin(f) a = System.Math.Sqrt(f) Объявление переменныхВо время обновления кода, Upgrade Wizard автоматически добавляет директиву OptionExplicit On, при этом мастер автоматически добавляет декларации всех используемых переменных. Если переменные были объявлены без указания типа, например Dim SomeVar, что для VB 6.0 аналогично Dim SomeVar As Variant, то при обновлении Upgrade Wizard объявит переменную как Object: Dim SomeVar As Object. DefInt a-z 'VB6 Dim a Dim b Dim c 'VB.NET Dim a As Short Dim b As Short Dim c As Short Строки ограниченной длиныОбъявление строковых переменных с фиксированной длиной в VB .NET является ошибкой. Для реализации подобной функциональности есть два пути – с использованием библиотеки VB6: Dim mString As Microsoft.VisualBasic.Compatibility.VB6 mString = Microsoft.VisualBasic.Compatibility.VB6.FixedLengthsString(4)Либо с использованием «натурального .NET кода» - объявлением массива символов: Dim mString(4) As Char Объявления массивовК огромному огорчению большого числа разработчиков на VB 6.0, VB .NET не поддерживает стандартных массивов с ненулевой нижней границей. При этом нельзя задать не только отрицательную, но и положительную границу отличную от нуля. Директива OptionBase N не поддерживается компилятором VB .NET. Upgrade Wizard оставит предупреждение об отсутствии поддержки подобных массивов: Dim a(-5 To 5) As Integer Dim b(5 To 10) As LongДанную проблему можно решить благодаря возможности объявлять переменную-массив как System.Array, при этом разработчик получает возможность создать массив с любыми верхним и нижним пределом. Dim mArray As System.Array Dim lenghts(0) As Integer ‘ Длины создаваемых массивов Dim lowerBounds(0) As Integer‘ Массив нижних границ lenghts(0) = 10 lowerBounds(0) = -5 mArray = System.Array.CreateInstance(GetType(Integer), lenghts, lowerBounds)Таким образом, можно сразу же создавать многомерный массив с любой длиной и любым нижним (соответственно и верхним) пределом. Для этого необходимо задать соразмерные массивы длин и нижних пределов. Dim lengths() As Integer = {3, 5} Dim lowerBounds() As Integer = {2, 3} Dim myArray As Array = Array.CreateInstance(GetType(Integer), _ lengths, lowerBounds) Объявления функцийНазвания и порядок передаваемых параметров остаются теми же, но, в соответствии с требованиями VB .NET добавляются указание на то, каким образом передаются параметры функции – по ссылке (ByRef) или по значению (ByVal). Так как в VB 6.0, по умолчанию параметры передаются по ссылке, мастер, везде, где это не указано явно, добавляет ByRef. Также везде при вызовах функции в коде, мастер добавит круглые скобки (там, где они отсутствуют), согласно требованиям нового синтаксиса VB .NET. 'VB6 Private Function SayHello(msg As _ String) As Boolean MsgBox msg SayHello = True End Function SayHello “Hi!” 'VB.NET Private Function SayHello(ByRef msg As String) As Boolean MsgBox(msg) SayHello = True End Function SayHello("Hi!") Область видимости переменныхОдной из неприятных проблем, которые обычно не возникают при хорошем стиле программирования в VB 6.0, но встречается достаточно часто – объявление переменных внутри конструкций If…Then…Else или For…Next, при этом в VB 6.0 эти переменные видны в пределах функции, а в VB .NET только в пределах соответствующих конструкций, что вызывает ошибки при попытке компиляции подобного кода. Чтобы избежать подобных неприятностей достаточно вынести все объявления из этих конструкций. СобытияVB .NET не сопоставляет события и обработчики по имени функции-обработчика, поэтому при обновления кода к объявлению каждой функции-обработчика события добавляется необходимая директива Handles, указывающая на то, обработчиком для какого события служит конкретная функция. Также, VB .NET передает всем обработчикам одинаковое количество параметров – объект, вызвавший данное событие, и объект, содержащий все аргументы этого события, таким образом, все функции-обработчики имеют идентичные объявления. Например: Private Sub Command1_Click() End Sub Private Sub Form1_Load(ByVal _ eventSender As System.Object, ByVal _ eventArgs As System.EventArgs) _ Handles MyBase.Load End Sub Заключение
Статья заключает собой своеобразное введение в обновление проектов VB6.0 до .NET11. В статье приведены основные моменты, с которыми сталкивается разработчик при использовании мастера автоматизированной миграции кода Upgrade Wizard. В следующих статьях цикла будут подробнее рассмотрены этапы обновления специфических технологий VB 6.0, обновление форм до Windows Forms, работа с ActiveX контролами и многое другое, что необходимо знать программисту, начавшему обновление проектов до VB .NET. 1 Для названий и методов, также как и для названий событий могут быть и исключения, когда Upgrade Wizard в некоторой степени изменит названия, при этом он выполнит эту операцию везде, где они встречаются, что не помешает работоспособности кода. В следующих статьях будут рассмотрены ситуации, когда Upgrade Wizard «вынужден» это сделать. 2 Visual Studio .NET предоставляет потрясающие возможности по отладке многокомпонентных приложений, включающих проекты VB 6.0 и VB .NET. Совместная отладка будет рассмотрена в следующих статьях. 3 Автор использует Microsoft Visual Studio .NET 2002 и .NET Framework 1.0, но все то же распространяется на Microsoft Visual Studio .NET 2003 и .NET Framework 1.1. 4 В некоторых случаях подобное поведение элементов форм VB .NET может иметь негативный эффект, что, возможно, потребует введения специальной переменной для отслеживания состояния приложения (была ли загружена главная форма или это событие вызвано до события Load главной формы). Более эффективный метод будет рассмотрен в статья посвященной Windows Forms. 5 Ссылки, создаваемые мастером, не приводятся в листинге с целью экономии места. 6 Integer – 32 битное число, Long – 64 битное. 7 Желательно ознакомиться с внутренним устройством файла проекта, в дальнейшем это может пригодиться в ситуациях, когда проще отредактировать проект вручную, как текстовый файл. 8 На самом деле поведение ActiveX контролов на .NET форме существенно отличается от такового на форме VB 6.0, но эта разница скрыта от разработчика внутренними механизмами .NET, которые будут рассмотрены в следующих статьях. 9 Глобальные объекты VB 6.0, такие как App, Clipboard, Printer и Screen отсутствуют в VB .NET, при этом некоторые методы этих объектов, не обладающие большой специфичностью, могут быть обновлены с использованием функций .NET или специального класса VB6. Реализация функций этих объектов будет рассмотрена в следующих статьях. 10 Существует исключение – ключевое слово Set, необходимое для присвоения значений объектным переменным, в VB .NET все переменные являются объектами, поэтому необходимость в этом слове исчезает и Upgrade Wizard удаляет его, встречая в коде. 11 Первой, вводной статьей была “Введение”, опубликованная ранее. 12 Строго говоря, элементы Label и Image также не имеют точных эквивалентов в VB .NET, так как являются графическими контролами. Приводимые в соответствие им Label и Picture представляют собой оконные элементы управления, соответственно с этим и связано отсутствие возможности задавать прозрачность. |