VB.NET Faces Off Against Classic VB

‘ve been listening with interest to the reactions that VB programmers have had to the new VB.NET environment and have been surprised to hear so many complain that VB.NET is a lot harder than VB. This is puzzling, because it doesn’t match my experience at all. I’ve found that while .NET is frustrating at first?when you don’t know the class hierarchy, and can’t find an object or a method to perform a common task?after a while you realize that not only is .NET not harder?it’s often easier than performing equivalent tasks in VB.

Because performing VB tasks in the .NET framework is so much more consistent than it was in classic VB, I suspect that the learning curve for beginning programmers will be much shorter than it once was. Nowhere is the improved syntax clearer than with file IO, where to access a file, you can create a File object, immediately check if the file exists, open it, and read its contents (see item 10).

Despite the fact that VB.NET improves ease of use and increases power when working with the System classes, the loss of break, edit, and continue is a serious deficiency. Break-edit-continue is the best RAD tool. Rumor has it that the feature will reappear in Version 2 of VB.NET. I hope so, because, in my opinion, break-edit-continue, not syntax, is the main reason that classic VB has been so attractive to so many programmers for so long. With that said, Visual Studio’s strong typing, syntax error markings, compiler warnings, and fast compile-edit cycle go a long way toward mitigating the loss, because they help prevent many errors before they occur.

This article presents 10 tasks that are either easier, take less code, or are more powerful in VB.NET than in classic VB. There’s no particular theme or hidden agenda behind these examples; they’re simply pulled from my recent experiences with VB.NET and Visual Studio. I can assure you that there are far more than just 10. I have purposely avoided tasks that classic VB doesn’t address intrinsically, such as creating a console application or a Windows service. I’ve also purposely avoided creating any classes so you can see that most common programming tasks don’t require class creation?just as you don’t have to create classes for common tasks in classic VB.

Create a GUID (Globally Unique ID)
GUIDs are an odd-looking series of numbers and characters, such as: {05589FA1-C356-11CE-BF01-00AA0055595A}. You might expect that GUIDs, because they’re how COM distinguishes between objects, would be easy to create in classic VB, which depends on COM. And you might expect that they’d be harder to create in VB.NET, which doesn’t depend on them. So much for expectations.




Classic VB:

   Private Declare Function CoCreateGuid Lib _      “ole32.dll” (buffer As Byte) As Long   Private Declare Function StringFromGUID2 Lib _      “ole32.dll” (buffer As Byte, ByVal lpsz As Long, _      ByVal cbMax As Long) As Long      Private Function getGUID() As String      Dim buffer(15) As Byte      Dim s As String      Dim ret As Long      s = String$(128, 0)      ret = CoCreateGuid(buffer(0))      ret = StringFromGUID2(buffer(0), StrPtr(s), 128)      getGUID = Left$(s, ret – 1)   End Function



VB.NET

   Private Function getGUID() As String      GetGUID = “{” & _         System.Guid.NewGUID().ToString & “}”   End Function

Retrieve a random number within a specified range
This is a common task, but the syntax always seemed awkward in classic VB. It’s been cleaned up considerably in VB.NET. To get a random number, simply call the Next method of the System.Random object. The overloaded version shown below returns a random number between two specified Integer values. The Random object seeds itself automatically using a time-dependent value.




Classic VB:

   Private Function getRandomNumber _      (low As Long, high As Long) As Long      Randomize(Now())      getRandomNumber = CInt((high – low + 1) * _         Rnd + low)   End Function



VB.NET

   Private Function getRandomNumber _      (ByVal low, ByVal high) As Integer      getRandomNumber = New System.Random(). _         Next(low, high)   End Function

Create a control dynamically at run-time
You couldn’t do this at all in classic VB prior to version 6, You could fake it by using a control array, hiding the first control to simulate control creation, but there was a major drawback?all the created controls were bound to the same event procedure code! To determine which control fired the event, you could write Select Case statements based on a control index number passed to the event.

Finally, VB6 added a slightly improved version. By declaring a control in advance you could “create” it at run time. But the control’s events were still bound to pre-determined code. In the classic VB example below, I’ve used the much more prevalent control array method. Fortunately, VB.NET has none of classic VB’s limitations. The first two examples are roughly equivalent?both create a control that uses the same handler as its model. The third example shows how easy it is to create a new control and bind it to any existing method that has a matching signature?for the button example shown, the Click event signature is a subroutine that has no parameters and no return value.




Classic VB:

   Private Sub cmdAddButton_Click(Index As Integer)      Static counter As Integer      counter = counter + 1      If counter < 4 Then         Load cmdAddButton(counter)         With cmdAddButton(counter - 1)            cmdAddButton(counter).Move _               .Left + .Width + _               (10 * Screen.TwipsPerPixelX), .Top         End With         cmdAddButton(counter).Visible = True      End If   End Sub



VB.NET (Version 1)

   Private Sub btnAddButton_Click(ByVal sender As _      System.Object, ByVal e As System.EventArgs) _      Handles btnAddButton.Click         Static counter As Integer = 1      Static lastButton As System.Windows.Forms.Button      counter += 1      If lastButton Is Nothing Then         lastButton = btnAddButton      End If      If counter < 4 Then         Dim b As New System.Windows.Forms.Button()         With lastButton            b.Width = .Width            b.Text = .Text            Controls.Add(b)            b.Left = .Left + .Width + 10            b.Top = .Top            lastButton = b         End With      AddHandler b.Click, AddressOf _         Me.btnAddButton_Click      End If   End Sub



VB.NET ( Version 2)

   Private Sub btnNewAdd_Click(ByVal sender As _      System.Object, ByVal e As System.EventArgs) _      Handles btnNewAdd.Click         Dim b As New System.Windows.Forms.Button()      With sender         b.Width = .width         b.Text = “Click Me!”         Controls.Add(b)         b.Left = .Left + .Width + 10         b.Top = .Top      End With      AddHandler b.Click, AddressOf Me.newButtonClick   End Sub
‘ This is the function called by the newly created button

   Private Sub newButtonClick(ByVal sender As _      System.Object, ByVal e As System.EventArgs)      MsgBox(“A new button was clicked! The index of ” _         ” this button is: ” & Me.Controls.GetChildIndex _         (sender))   End Sub
A few final notes on this topic.

VB.NET doesn’t support classic VB’s control arrays directly. Adding controls takes more code, but also adds considerable flexibility. You’re perfectly free to add controls to an array or collection, which you can then use to simulate the functionality of a control array.

A control’s event procedures no longer have to start with the name of the control, for example, “button1_click;” instead, the procedure may have any name.

You can dynamically change the procedures bound to control events.

Set the tab order of controls on a form
This task has been onerous in classic VB since its inception.




Classic VB:

VB uses a property called TabIndex to determine the order in which the focus moves from control to control as you press the tab key. The best way to set the tab order for multiple controls was to start with the control you wanted to be last in the tab order, and work your way toward the first control, assigning a TabIndex of 0 each time.




VB.NET

In contrast, in VB.NET, you set the tab order by clicking the Tab Order item on the View menu. You see a display like Figure 1. Next, click each of the controls in the preferred tab order. As you click the controls, the tab order numbers change. For example, if you wanted the tab order to move left to right, top to bottom, the form would look like Figure 2 when you finish.

Increment a variable
If you’ve been watching, you’ve seen this already, but it’s such a common operation, and I’m so pleased with the new syntax that it’s worth including here. Of all the possible keystroke-saving improvements, this new syntax and its cousins are the most welcome.




Classic VB

myVariable = myVariable + 1

 




VB.NET

myVariable += 1

Read a registry value
Windows, until .NET, depended heavily on the registry. Therefore, it was irritating that classic VB’s built-in methods for registry access were limited to a single registry location?HKEY_CURRENT_USERSoftwareVB and VBA Program Settingsappnamesectionkey. Of course, you could use the API to read and write other keys, but it was complicated (click here for an example).

In contrast, reading and writing to the registry is extremely simple in VB.NET. For example, the following subroutine creates the subkey HKEY_CURRENT_USERSoftwareVBDotNetDemo, sets the subkey’s name to “VBDotNetDemo” and its value to the String “VB.NET,” and then displays a message box showing the new value.




Classic VB

Example: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=1881




VB.NET

   Private Sub btnWriteRegistry_Click(ByVal sender As _      System.Object, ByVal e As System.EventArgs)       Handles btnWriteRegistry.Click         Dim aKey As RegistryKey      aKey = Registry.CurrentUser.CreateSubKey _        (“SoftwareVBDotNetDemo”)      aKey.SetValue(“VBDotNetDemo”, “VB.NET”)      MessageBox.Show(“The value of the new key ” _         & “‘HKEY_CURRENT_USERSoftware” & _         “VBDotNetDemo’ is: ” _         & aKey.GetValue(“VBDotNetDemo”, _         “Default value”), _         “Key Created Successfully”)   End Sub

Launch another program and wait until it exits
Using the Shell command, it was easy to launch other Windows programs in classic VB, but they ran asynchronously. Pausing your program until the shelled application ended was much more difficult. Here are two examples that launch an instance of Notepad, wait until you close the window, and then display a message box confirming that the window was closed. The classic VB code is too long to include inline, but I borrowed the code from the MSDN Knowledge Base, so you can see a near-duplicate here. Note that there are other ways to accomplish the same result in VB.NET in addition to the method shown, which uses the VB.NET version of the Shell command.




Classic VB ? see MSDN example.




VB.NET

   Private Sub btnLaunch_Click(ByVal sender As _      System.Object, ByVal e As System.EventArgs) _      Handles btnLaunch.Click         Dim sysPath as String      SysPath = System.Environment.GetFolderPath _         (Environment.SpecialFolder.System)      Shell(sysPath & ”
otepad.exe”, _ AppWinStyle.NormalFocus, True) MessageBox.Show(“You just closed Notepad”, _ “Notepad Closed”) End Sub

Populate a ListBox with values from a String array
In classic VB, you can bind controls to data from ADO Recordset objects, Data and RemoteData controls, and classes defined as data sources, but adding a simple list of values required looping through the list using the AddItem method to add each value. In addition, the syntax to create the String array in the first place is wordy. In fairness, an alternate syntax, using a Variant array is much better. In contrast, you can create a string array in VB.NET using the bind a VB.NET ListBox to an array (and notice it’s a strongly typed array) by simply setting the DataSrc property. I’ve shown two examples in classic VB to illustrate the difference between creating a typed String array and a Variant array. The following examples each create a short String array and fill a ListBox with the values.




Classic VB (Variant array)

   Private Sub cmdPopulateList_Click()      Dim listItems(4) As String      Dim anItem As Variant      listItems = Array(“One”, “Two”, _         “Three”, “Four”, “Five”)      List1.Clear      For Each anItem In listItems         List1.AddItem anItem      Next   End Sub



Classic VB (String array)

   Private Sub cmdPopulateList_Click()      Dim listItems(4) As String      Dim i As Integer      listItems(0) = “One”      listItems(1) = “Two”      listItems(2) = “Three”      listItems(3) = “Four”      listItems(4) = “Five”      List1.Clear      For i = 0 To 4         List1.AddItem listItems(i)      Next   End Sub



VB.NET

   Private Sub btnPopulateList_Click(ByVal sender As _      System.Object, ByVal e As System.EventArgs) _      Handles btnPopulateList.Click         Dim listItems() As String = {“One”, “Two”, _         “Three”, “Four”, “Five”}      ListBox1.DataSource = listItems   End Sub

Retrieve multiple selected items from a ListBox
In both classic VB and VB.NET, you can create a ListBox that lets users make multiple selections. There are two types of multiple selection?simple and extended. These examples use extended selection, which lets a user make multiple non-sequential selections by holding the control key down while clicking an item. In classic VB, set the MultiSelect property of the ListBox control to 2 (Extended). In VB.NET set the SelectionMode property to MultiExtended. A button on the form creates an array containing the user’s selections and passes the array to a subroutine that displays the items. The following code shows the Click event for the buttons.




Classic VB

   Private Sub cmdGetListSelections_Click()      Dim i As Integer      Dim sArr() As String      Dim selCount As Integer      For i = 0 To List1.ListCount – 1         If List1.Selected(i) Then            ReDim Preserve sArr(selCount) As String            sArr(selCount) = List1.List(i)            selCount = selCount + 1         End If      Next      Call showStringArray(sArr)   End Sub   Private Sub showStringArray(arr() As String)      Dim s As String      Dim i As Integer      Dim arrCount As Integer      On Error Resume Next      arrCount = UBound(arr) + 1      On Error GoTo 0      If arrCount > 0 Then         For i = 0 To arrCount – 1            s = s & arr(i) & vbCrLf         Next         MsgBox s      End If   End Sub



VB.NET

   Private Sub btnGetListSelections_Click(ByVal sender _      As System.Object, ByVal e As System.EventArgs) _      Handles btnGetListSelections.Click      Dim sArr(ListBox1.SelectedItems.Count – 1) _         As String      Dim anItem As String      Dim i As Integer      For Each anItem In ListBox1.SelectedItems         sArr(i) = anItem         i +=1      Next   End Sub      Private Sub showStringArray(ByVal arr() As String)      MessageBox.Show(Join(arr, _      System.Environment.NewLine))   End Sub   End Class

Read the contents of a text file
File IO has changed considerably in .NET. If you have been using the FileSystemObject to read and write text files, you’ll feel comfortable quickly. If you’ve been using the intrinsic VB commands, such as Open, Get, and Put, file IO may seem strange at first. The example uses the intrinsic VB commands.

Both the VB and VB.NET versions perform the same tasks: retrieve the Windows folder path from the SystemRoot environment variable, ensure that the Win.ini file exists in the Windows folder, then open and read the contents of the file, and assign the resulting string to a multiline TextBox control. You can read the file with a single command in both versions, but the VB.NET version is much more intuitive. For example, it’s obvious what the “File.Exists” does, but not nearly as obvious what the Dir$ command does.




Classic VB

   Private Sub Command1_Click()      Dim fnum As Integer      Dim s As String      Dim fname As String      Dim winPath As String      On error goto ErrReadTextFile      fnum = FreeFile      ‘ get the windows folder name      winPath = Environ$(“SystemRoot”)      If winPath = “” Then         MsgBox “Unable to retrieve the Windows path.”, _            vbInformation, “Error Reading Windows Path”         Exit Sub      End If      ‘ create a file name      fname = winPath & “win.ini”      ‘ ensure the file exists      If Dir$(fname) <> “” Then         ‘ open the file         Open fname For Binary As #fnum         If Err.Number = 0 Then            s = Space$(LOF(fnum))            ‘ read the file            Get #fnum, 1, s            Close #fnum            Text1.Text = s         Else            Text1 = “Unable to read the file ” & _            fname & “.”         End If      Else         Text1 = “The file ” & fname & ” does not exist.”      End If   ExitReadTextFile:      Exit Sub   ErrReadTextFile:      MsgBox Err.Number & “: ” & Err.Description      Exit Sub   End SubEnd Sub



VB.NET

   Private Sub btnReadTextFile_Click(ByVal sender _      As System.Object, ByVal e As System.EventArgs) _      Handles btnReadTextFile.Click   Dim winPath As String   Dim s As String   Dim fname As String   Dim sr As StreamReader   Dim ex As Exception      ‘ get the windows folder name   winPath = System.Environment. _         GetEnvironmentVariable(“SystemRoot”)      If winPath = “” Then         MessageBox.Show(“Unable to retrieve the ” & _        “Windows path.”, “Error Reading Windows Path”, _        MessageBoxButtons.OK, MessageBoxIcon.Information)         Return      End If      fname = winPath & “win.ini”      If File.Exists(fname) Then         Try            sr = File.OpenText(fname)            s = sr.ReadToEnd            sr.Close()            textbox1.text = s         Catch ex            MessageBox.Show(ex.message)            return         End Try      Else         MessageBox.Show(“The file ” & fname & _            ” does not exist.”)         Return      End If   End Sub
You can’t point to just one or two things that make VB.NET easier to work with?it’s the little things that make VB.NET and Visual Studio easier than previous versions. Sometimes, VS.NET requires less code; sometimes the long object names and numerous objects create more code. But after you learn a little about the framework, it almost always creates code that’s easier to understand and maintain.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: