Business Website Links
Website Design, PR, and Surveys
Your One-Stop Shop for the
Internet & Beyond

Home Company Info Pricing Contact Client Directory Computer Tips News Testimonials

Computer Tips

Visual Basic









Visit us often.  Computer tips updated daily.  Click here to--> "Tell a friend" so they can get updated computer tips, too.  Please visit our clients, as they support the computer tips page.

If you would like to submit a tip send us an email with your tip to

Call a SQL User Defined Function from ADO.NET with ExecuteScalar (VB 2003)

  • A SQL Server User Defined Function (UDF) is an excellent tool for encapsulating business logic in a central area. Just like a stored procedure, UDFís can be a safe and efficient way to retrieve data.
  • If you want to use a UDF in your .NET application, you can retrieve the data using the ExecuteScalar function of a Command object.
  • To execute a UDF using ExecuteScalar:
    • 1. Create a SQLConnection object.
    • 2. Build a SQL Select statement that selects the UDF with a comma-delimited list of the parameters in parenthesis.
    • 3. Use the Connection object and SQL string to create a Command object.
    • 4. Add items to the Parameters collection of the Command object.
    • 5. Call the ExecuteScalar() function.
  • The following code snippet demonstrates these steps:
    • Imports System.Data.SqlClient

      Sub queryUDF()
      Dim cn As SqlConnection = New _

      '(@Param1) or (@Param1,@Parm2,...)
      Dim strSQL = "SELECT dbo.udf_myUDF" & "(@Param1)"

      Dim cmd As SqlCommand = New SqlCommand(strSQL, cn)

      cmd.Parameters.Add(New SqlParameter("@Param1", _
      SqlDbType.Text)).Value = "Hello"

      Dim val As String = cmd.ExecuteScalar()
      MsgBox("Value is: " & val)
      End Sub
  • This method is nice because itís light on code and it doesnít require special measures to retrieve the result.

Fully qualify the Application object to avoid a runtime error (VB 2005)

  • In VB .NET 2003, you could retrieve the file location of the current application using Application.StartupPath. In VB 2005, you can use this property just as it appears here without issue. However, when you execute the code, you'll receive the error:
    • 'StartupPath' is not a member of 'MyApplication'.
  • By default, VB 2005 looks to the My.Application namespace for this type of information. To get around this, you can fully qualify the StartupPath property, like so:
    • System.Windows.Forms.Application.StartupPath
  • Alternatively, you could also import the System.Windows.Forms namespace at the start your code. Of course, since VB 2005 is looking at the My.Application namespace, you could also use that as well. The following code illustrates:
    • My.Application.Info.DirectoryPath
  • One important thing you should keep in mind: in VB .NET 2003 the StartupPath property points to the Bin folder. In VS 2005, both StartupPath ad DirectoryPath point to the Debug folder by default.

Force ADO.NET to correctly start AutoIncrement fields for Access (ADO.NET 1.1)

  • If you create an empty DataSet with an automatically incrementing field and add a new record to it, ADO.NET will initially set this field to 0 for the first record you add. Although you wonít receive an error when you attempt to add the new data to an Access table, Access will change the 0 AutoIncrement field to 1, throwing off all rows that follow it.
  • This, unfortunately, creates a discrepancy between your application data and the Access data. However, you can prevent this by forcing ADO.NET to start AutoIncrement fields with 1 instead of 0. Consider the following code:
    • For Each tb As DataTable In ds.Tables
      For Each dc As DataColumn In tb.Columns
      If dc.AutoIncrement Then
      dc.AutoIncrementSeed= 1
      End If
  • This code loops through all tables in a DataSet named ds. Then it checks each field to see if itís an AutoIncrement field. If it is, then it sets the AutoIncrementSeed value to 1, so the first ecord you add will have this value instead of 0.

Conduct precise string comparisons in a DataView with the CaseSensitive property (VB .NET)

  • In ADO.NET, you can create custom views of a DataTable object with the DataView class. Methods like Find(), FindRows(), and RowFilter() make it easy for you to get just the data you need. By default, .NET doesnít consider case when you search a DataView for a specific string value. For example, suppose a DataView has one row where its second column contains the string value: December. The next set of code would return a value of 1 even though the search string uses a lowercase d:
    • Dim dv As New DataView(myDataTable)
      dv.Sort = dv.Table.Columns(1).ColumnName
      Dim dr() As DataRowView = dv.FindRows("december")
  • However, if you want .NET to consider only those rows that exactly match your search string, you should set the CaseSensitive property of the parent DataSet or DataTable to True. Referring back to the earlier code, if we insert this line:
    • dv.Table.CaseSensitive = True
    • above the cal to the FindRows() method, the code would return 0 instead of 1.
  • There are three important things you should keep in mind when using the CaseSensitive property:
    • --If you set the CaseSensitive property to True for a DataSet, it applies to all tables in the DataSet.
    • --Setting the CaseSensitive property to True for a DataTable overrides the DataSet setting.
    • --If you have two DataTable objects in a DataSet linked by a DataRelation, you canít change the CaseSensitive for just one of the DataTable objects.

The two logical operators that could save you a lot of headaches (VB .NET)

  • Hereís a simple programming mistake that occurs quite frequently - a developer inadvertently uses a single conditional statement to check that an item conforms to a particular type and that the item has a specific typed value. Whatís the problem? Consider the following code:
    • If IsNumeric(TextBox1.Text) _
      And Cdbl(TextBox1.Text) > 9999999 Then
      MsgBox("Wow! What a big" & " number")
      MsgBox("You entered " & _
      TextBox1.Text & ".")
      End If
  • In this code, if the text box value is a valid number then the subroutine works just fine. However, if the text box contains something that can't be converted to a Double, then the code causes a fatal exception. This happens because the compiler attempts to evaluate the second part of the condition even though the first part fails.
  • However, you can avoid a fatal error if you use AndAlso instead of And in the conditional sttement, like so:
    • If IsNumeric(TextBox1.Text) _
      AndAlso Cdbl(TextBox1.Text) _
  • Doing this short circuits the condition so that the Else portion of the conditional block executes as soon as the IsNumeric() function fails. In addition to AndAlso, .NET supports OrElse. So, if you had the following code:
    • If myFunc1() OrElse myFunc2() _
      OrElse myFunc3() _
      OrElse myFunc4() Then ...
  • and myFunc1() evaluates to True, then .NET wouldn't execute the last three functions, which would be a good thing if one of those functions contained code that fails when myFunc1() is True. With the Or operator, on the other hand, .NET would always execute all four functions.

The free and easy solution for exporting DataTable data to a PDF file

  • In past versions of Visual Basic .NET, you had to use Crystal Reports, Reporting Services, or purchase some other third party application to create PDF files with your code. However, if you've upgraded to Office 2007, creating PDFs is just a little automation away.
  • To create PDF's the Office way, we'll:
    • Show you how to reference the Word 2007 object model and open a Word document.
    • Create a sample application that copies data from a DataTable to a Word document.
    • Reveal the code you'll need to save the contents of the Word document to a PDF format.
    • Read More About This Tip Click Here > Visual Basic Tips

Add professional polish to the TabControl with GDI+

  • The TabControl allows you to present multiple pages of information in a compact space, but their standard appearance can leave your form looking bland. We'll provide four ways to spice it up with a little GDI+.
  • So that you can create extraordinary tab pages, we'll:
    • Ditch the standard system colors and modify backgrounds with a color blend.
    • Show you how to make the TabControl tabs match the background color of the pages.
    • Add color to the TabControl container for a more complete look.
    • Shape up the TabControl tabs for an extra special touch.
    • Read More About This Tip Click Here > Visual Basic Tips

A few simple techniques to change the appearance of tabs in a TabControl (VB 2003)

  • By default, .NET positions TabControl tabs at the top of the control and labels them with plain text. Unfortunately, you canít easily change the back color of the tab or the font of its text. However, that doesnít mean you have to settle for bland, boring tabs. Three simple adjustments you can make to TabControl tabs without writing a single line of code include: adding images to each tab, changing the position of the tabs, and stacking multiple tabs for easier viewing.
  • To add images to tabs:
    • 1. Add an ImageList to your project and select it.
    • 2. In the Properties window, use the Images property to add images to the ImageList collection.
    • 3. Add a TabControl to your form and select it.
    • 4. In the Properties window, use the dropdown list in the ImageList property to select the name of the ImageList you just created.
    • 5. Locate the TabPages property and click the ellipses in the field.
    • 6. Click the Add button to add a new TabPage and then use the dropdown list in the ImageIndex property to select the desired tab image.
    • 7. Repeat step 6 as needed.
  • To change the tab position:
    • 1. In the Properties window, locate the Alignment property for the TabControl.
    • 2. Change the value to Right, Bottom, or Left to reposition the group of tabs.
  • To remove the tab scrollbar:
    • 1. In the Properties window, locate the Multiline property for the TabControl and change the value to True.
  • One thing to keep in mind: Top and Bottom aligned tabs can be layered or scrolled, but Left and Right aligned tabs can only be layered.

Process data the moment it arrives with two .NET classes

  • If you're using a scheduler to import data into your database from a file, you not only have to worry about the import failing, you have to hope the file is where it should be when the scheduler kicks off the import process. We'll show you how to remove the timing element from the equation with a ServiceBase derived class and a FileSystemWatcher object.
  • To import data the moment it arrives, we'll:
    • Create a FileSystemWatcher object to keep an eye out for the import file.
    • Build a Windows service application that will make sure the watchful eye of the FileSystemWatcher never closes.
    • Code, implement, and install a basic file system watching service.
    • Read More About This Tip Click Here > Visual Basic Tips

Properly handle proper names with the strConv() function (VB 2003)

  • The UCase and LCase functions allow you to convert the contents of string variables into all upper- and all lower-case, respectively. However, what if you want to convert a string into proper case, that is, where each word begins with a capital letter? For that, you can use the often overlooked StrConv() function. For example, the following code:
    • Dim strName
      strName = "lucy b. lucky"
      strName = StrConv(strName, vbProperCase)
    • returns Lucy B. Lucky.
  • For consistency, you can even use StrConv() instead of UCase and LCase. Just use the vbLowerCase and vbUpperCase parameters in place of vbProperCase.

Ensure proper updates with multiple tables using transactions

  • ADO.NET has no problem adding and modifying multiple records in multiple tables, but there could be big problems if those tables are linked in some way and one update succeeds while the other one fails. We'll show you how transactions can help with updates to multiple, related tables.
  • To prevent mass updates from causing massive headaches, we'll:
    • Explain how ADO.NET commits all DataSet changes to the database.
    • Show you how to create and use transaction objects.
    • Provide the necessary code to wrap parent/child table updates in a transaction.
    • Read More About This Tip Click Here > Visual Basic Tips

Tip: Allow users to view ListView columns their way with the AllowColumnReorder property (VB 2003)

  • With most list controls, if the user wants to view the data columns in a different order, youíd either have to give him the ability to clear out the control and reload the data or modify the code to display the data in the preferred manner.
  • However, if youíre displaying the data in a ListView control, you can actually put the order of the columns in the userís hands with the AllowColumnReorder property. When you set this property to True, the user can click and hold the left mouse button on a column header and just drag it to a new position in the ListView.

Tip: Cycle through clipped text with this helpful hotkey sequence (VS .NET)

  • While editing your code in Visual Studio .NET, youíll find all the text youíve deleted in the Clipboard Ring of the Toolbox. Although you can open the Toolbox, manually scroll through this list, and double-click on the text you want to re-insert into your code, you can perform the same task without even going near the Toolbox using the key sequence: [Ctrl][Shift]V.
  • First, place your cursor in your code where you want to insert the deleted text. Next, hold down the [Ctrl] and [Shift] keys. To cycle through the Clipboard Ring entries, repeatedly press the V key. As you do this, VS .NET inserts text from the Clipboard Ring at the cursor point and selects it. Keep pressing the V key until .NET inserts the code you want to restore.

Tip: Avoid manual ListView column adjustments with special Width values (VB .NET)

  • When VB.NET displays a ListView control, it uses default column width values. Unfortunately, it does this whether your ListView contains five columns or just one. Thankfully, you can override this behavior with the Width property.
  • Normally, when you use the Width property, you assign it a value representing the exact pixel width you want for the column. However, the ListView also supports two values that automatically adjust the column widths at runtime to fit the data: -1 and -2. These special values save users from having to manually adjust the columns and they save you from having to change the widths every time the data outgrows the columns. You'll use these values like so:
    • ListView1.Columns(0).Width = -1
    • ListView1.Columns(1).Width = -2
  • The first line of code would stretch the first column out to the longest column text, without changing the header length. The second line of code adjusts both the header and column data for the second column to the longest text value. You could also use -2 on the last column of your ListView so that it completely fills the ListView window.

Tip: Load ListBox controls faster with BeginUpdate and EndUpdate (VB .NET)

  • Although ListBox controls arenít well suited for large amounts of data, there may be times when you have to use them to hold more than a handful of records. If this is the case, you should call BeginUpdate() before you start loading the ListBox and EndUpdate() after adding the last record. When you do this, the control wonít refresh each time you add a new record. Instead, it waits until youíve added the last record. This not only diminishes the flicker effect (or blank control effect) that occurs while loading a large number of records into the control, but it also significantly speeds up the amount of time it takes to load the list box.
  • "How much faster," you ask? Well, we placed two ListBox controls on a form. We loaded 5000 records into the first list box using BeginUpdate() and EndUpdate(). We loaded the second list box with the same number of records, but we didn't use the two methods. It took four seconds for .NET to add all the records to the second list box. However, it took only one second for the first list box.

Tip: The spring forward happens a bit sooner this yearóis your system ready?

  • In the United States, Daylight Saving Time (DST) will be extended by approximately four weeks this year. As a result, DST will start three weeks earlier on March 11, 2007, and end one week later on November 4, 2007. If your system is currently set to automatically adjust for DST or you have applications that calculate elapsed time, then you should take action now. Microsoft has compiled a list of its products that will be affected by this change. They include
    • Microsoft Windows
    • Microsoft Windows SharePoint Services
    • Microsoft Exchange Server
    • Microsoft Office Outlook
    • Microsoft SQL Server Notification Services
  • For a complete list of all affected products and what you will have to do to make sure your systems respond appropriately, point your browser to

Tip: Load new processes in your VB .NET window with the SetParent() API (VB .NET)

  • If you ever need to load one .NET window inside another, you can do so just by adding the new window to Controls collection of the current window, like so:
    • Dim frm As New frmClass
  • However, if the window you want to load in your application's window is from a separate process, you'll need to use the SetParent() API.
  • To start a new process, you use the Start method of the System.Diagnostics.Process class. This method returns a Process object that supports a property called MainWindowHandle. This single property allows you to retrieve the handle of the new process' window which you can use to load it into your current window. Try the following test:
  • Create a new VB .NET Windows Application and add a Button, and Panel to the default form. Then, open the code window and add the following code:
    • Declare Auto Function SetParent _
      Lib "user32" (ByVal hWndChild As _
      Integer, ByVal hWndNewParent As _
      Integer) As Boolean
      Private Sub Button1_Click(ByVal _
      sender As Object, ByVal e As _
      System.EventArgs) Handles Button1.Click
      Dim pid As Process
      pid = Process.Start( _
      SetParent( _
      pid.MainWindowHandle.ToInt32, _
      End Sub
  • This code references the calc.exe application at C:\windows\system32. Be sure to update the location information if this isn't the case for your system. To test the code, press [F5] and when the form loads, click the button. You should see the calculator window inside your VB .NET window.

Tip: Two methods to easily copy DataSet data and/or its structure to a new object (ADO.NET)

  • Occasionally, you may need to make a copy of a DataSet or its structure. Although you can't just assign the DataSet to a new DataSet object, you can use one of two ADO.NET methods to accomplish this task.
  • If you want an exact copy of your DataSet data (schema, columns, and rows), you can use the DataSet Copy() method. The following code loads an XML file into a DataSet object and then creates an exact copy of it:
    • Dim ds As New DataSet
    • ds.ReadXml("C:\products.xml")
    • Dim ds1 As New DataSet
    • ds1 = ds.Copy
  • If your DataSet contains multiple tables and you only need a copy of one of them, the DataTable object also supports the Copy() method. The following code copies the first DataTable in the DataSet to a new table object:
    • Dim dt1 As New DataTable
    • dt1 = ds.Tables(0).Copy
  • In addition to the Copy() method, both DataSet and DataTable objects support the Clone() method. Although this method sounds like it should perform the same task as Copy, it doesnít. The Clone method creates an exact copy of table schemas only. So, the next line adds the table and column names to the new Dataset, but no data:
    • Dim ds2 As New DataSet
    • ds2 = ds.Clone

Tip: Sort DataSet records using a DataView object (VB .NET)

  • In .NET, you can easily sort DataSet records using a DataView. First, create a new DataSet and load it. Then, create a new DataView object using a DataTable in the DataSet. Finally, identify the column or columns you want to sort. The following code snippet illustrates the process:
    • Dim objDv as New DataView(objDataSet.Tables(0))
    • objDv.Sort = "Column1"
  • This code creates a DataView object using the first table in the DataSet and sorts the view on the column named Column1. To sort on multiple columns, use a comma-delimited list, like so:
    • objDv.Sort = "Column1, Column3"
  • If the unsorted DataSet is bound to a control, such as a DataGrid, you'll need to bind the DataView to that object in order to see the newly sorted data. You can use code similar to the following:
    • DataGrid1.DataSource = objDv

Tip: Let .NET set your key values for you so you aren't caught seeing double (ADO.NET)

  • Although you can manually assign a primary key to a DataSet, there's always the possibility that you'll forget or you'll use the wrong fields while creating the key. Luckily, you can also automatically using a DataAdapter.
  • To automatically set a primary key:
    • 1.Create a new DataAdapter object.
    • 2.Set the MissingSchemaAction property of the DataAdapter to MissingSchemaAction.AddWithKey.
  • If you're using a DataAdapter to load a DataSet, the MissingSchmaAction.AddWithKey option allows you to pull the primary key information directly from the original data source. The following code snippet demonstrates these steps using a SQL DataAdapter:
    • Dim strCn As String
    • Dim cn As New SqlConnection(strCn)
    • Dim da As New SqlDataAdapter( _
    • "Select * from myTable", cn)
    • da.MissingSchemaAction = _
    • MissingSchemaAction. _
    • AddWithKey

Tip: Manually define a primary key to avoid problems associated with duplicates (ADO .NET)

  • Itís never a good thing to have duplicate records in a DataSet. One way to prevent duplicates is to define a primary key for your recordset.
  • To manually set a primary key:
    • 1.Create an array of DataColumn elements.
    • 2.For each index of the DataColumn array, assign one of the DataSet columns that represents an element of the primary key.
    • 3.Assign the entire DataColumn array to the PrimaryKey property of the DataSet.
  • Since a DataTable can have a multi-column primary key, you must use an array of DataColumn objects to manually set a primary key, even if youíre only designating one column as a key. The following code creates a primary key of one column:
    • Dim dSet as New DataSet
    • Dim dc(1) As DataColumn
    • dc(0) = dSet.Tables(0).Columns(0)
    • dSet.Tables(0).PrimaryKey = dc
  • For a multi-column primary key, simply increase the array size or use array initializers to create a variable length primary key. In the next set of code, weíve identified the first and fourth columns of a DataSet as the primary key:
    • Dim dSet as New DataSet
    • Dim dc() As DataColumn =
    • {dset.Tables(0).Columns(0), _
    • dset.Tables(0).Columns(3)}
    • dSet.Tables(0).PrimaryKey = dc

Tip: Keep text box selections visible after the user moves to a new field (VB .NET 2003)

  • The TextBox control allows you to select all or portions of the text it contains. However, when you set focus to a new control, the default behavior of the TextBox is to remove the selection box that highlights the selected text. You can change this behavior by setting the HideSelection property of the TextBox to False. When you set this property to False, you can leave the field and continue to see the text youíve selected.

Tip: Turn to the Paint() event for non-tiled background images (VB .NET)

  • VBís default behavior is to tile a background image to fill a form. Although it may seem logical to have the ability to toggle the tiling behavior, this isnít the case. However, you can display a single image on a form, if you use the Paint() event instead.
  • To try it out, place the following code your formís Paint() event (be sure to replace our filename with one valid on your system):
    • Dim bmp As Image = Image.FromFile( _
    • "C:\myImage.jpg")
    • e.Graphics.DrawImage(bmp, e.ClipRectangle)
  • When you build and load the form, you should see a single image on the window. The downside of this technique is that you will face some interesting repainting issues when resizing the form or removing the focus from the form. To correct resize issues, open the formís Resize() event and place the following call in the subroutine:
    • Me.Invalidate()
  • This code forces a call to the Paint() event any time you change the size of the form, so .NET can redraw the form. The easiest way to correct the focus issue is to also place a call to Me.Invalidate() inside the Formís Activate() event. This event fires each time the form regains focus, making it the ideal place to refresh the picture.

Tip: Two ways to assign a primary key to a DataSet object (VB .NET)

  • In VB .NET, you can associate a primary key with a DataSet manually, using the PrimaryKey property of a DataTable or automatically using a Data Adapter. To manually set a primary key you can use code similar to the following:
    • Dim dc(1) As DataColumn
    • dc(0) = dSet.Tables(0).Columns(0)
    • dSet.Tables(0).PrimaryKey = dc
  • This code identifies the first column of the first table in a DataSet as the primary key. Since a DataTable can have multi-column primary key, you must use an array of Datacolumn objects to manually set a primary key, even if you're only designating one column as a key.
  • If you're using a Data Adapter to load a DataSet, you can automatically bring in the primary key information with the MissingSchemaAction property. The following code snippet retrieves the primary key information using a SQLDataAdapter:
    • Dim strConnection As String = _
    • "server=sv1;uid=uid1;pwd=pw1;database=db1"
    • Dim cn As System.Data.SqlClient.SqlConnection = New _
    • System.Data.SqlClient.SqlConnection(strConnection)
      Dim da As New _
    • System.Data.sqlclient.SqlDataAdapter( _
      "Select * from myTable", cn)
    • da.MissingSchemaAction = MissingSchemaAction.AddWithKey

Tip: Bring two separate DataSets together with the Merge method (VB .NET)

  • In many organizations, it isn't uncommnon to have several people working on the same set of data at one time. If those individuals are using disconnected recordsets, you can bring their work together with the Merge method. The Merge method conforms to the following syntax:
    • objDset.Merge(objDtbl)
    • where objDSet is a DataSet with a DataTable and objDtbl is a separate DataTable. The following code merges two separate data tables into one DataSet.
    • Dim ds1 As DataSet = New DataSet("Animals")
    • Dim dt1 As New DataTable("AnimalCodes")
      dt1.Columns.AddRange(New DataColumn() _
      {New DataColumn("ID"), New DataColumn("NAME")})
      dt1.Rows.Add(New String() {"CAT", "Cat"})
      dt1.Rows.Add(New String() {"DOG", "Dog"})
    • Dim dt2 As New DataTable("AnimalCodes")
      dt2.Columns.AddRange(New DataColumn() _
      {New DataColumn("ID"), New DataColumn("NAME")})
      dt2.Rows.Add(New String() {"BRD", "Bird"})
    • ds1.Merge(dt2)
      For Each dr As DataRow In ds1.Tables("AnimalCodes").Rows
  • There are a couple of things you need to keep in mind with the Merge method: the table and column names in the two tables must match exactly and, if there's a possibility that the separate users will add or modify the same rows, you'll have to take extra steps to handle the conflicts.

Tip: Import the Visual Basic namespace to access some legacy features (VB .NET)

  • In a recent tip, we reported that you can no longer access the Left and Right string functions in Visual Basic .NET. As many of our subscribers pointed out, that isn't entirely true. While these functions aren't a part of .NET's String class, you can still access them by importing the Visual Basic namespace.
  • To do so, place:
    • Imports Microsoft.VisualBasic, at the top of your class and then you can use code similar to the following to use the legacy functions:
      • Dim myString As String = "Visual Basic"
      • MsgBox(Strings.Left(myString, 6))
      • MsgBox(Strings.Right(myString, 6))

Tip: Stretch DataGrid columns in code with the TableStyles property (VB .NET)

  • Occasionally, the DataGrid loads with a column that's too small to show all the data in a field. Now, this may not be a big deal if your grid only contains a couple of columns. However, it can be very frustrating for a user if the grid contains several columns and he has to manually expand each one to see its entire contents. Luckily, you can automatically expand a DataGrid column's width using the DataGridTableStyle object.
    To try it out, add a DataGrid control to a Windows form in .NET. Then, inside a module or event subroutine, create a new DataGridTableStyle object and set its MappingName property to your current table's names. Finally, add the DataGridTableStyle object to the grids TableStyles collection and use it to set the width of a specific column on the grid. The following code illustrates this process:
    • Dim ts As New DataGridTableStyle
    • ts.MappingName = "Your table name"
    • DataGrid1.TableStyles.Clear()
    • DataGrid1.TableStyles.Add(ts)
    • DataGrid1.TableStyles("Your table name"). _
    • GridColumnStyles("Table Column").Width = 100
  • The names you use for the MappingName and for the GridColumnStyles column name must match the exact table and column names you used to create the DataGrid.

Tip: Create shapely Button controls through GDI+ (VB .NET)

  • Perhaps you're aware that you can shape Microsoft Windows Forms into circles or other shapes using the Form's Region property and a GraphicsPath object. However, did you know that the Button control also has a Region property that you can use to shape the buttons on your form? To test it out, drop a Button onto a Windows Form and add the following code to the Click() event of the Button.
    • If Button1.Tag <> "clicked" Then
    • Button1.Size = New Size(114,90)
    • Dim gPath As GraphicsPath = New GraphicsPath
    • gPath.AddLines(New Point() _
    • {New Point(55, 0), New Point(125, 150), _
    • New Point(-15, 150)})
    • gPath.CloseFigure()
    • Button1.BackColor = Color.MediumBlue
    • Button1.ForeColor = Color.White
    • Button1.Region = New Region(gPath)
    • Button1.Tag = "clicked"
    • Else
    • MsgBox("I'm not square!")
    • End If
  • This code uses GDI+ to transform the button when you click it the first time and returns a message when you click it the second time. Be sure to Import the System.Drawing.Drawing2D Namespace or include it in the gPath declaration.

Tip: PrevInstance is no longer available to prevent multiple instances of your VB program (VB .NET)

  • In VB 6, you can prevent multiple instances of your application from running on the same computer using the PrevInstance property of the App object. This property returns True if another instance of the application is running on the machine, and it returns False if not. Consider the following code:
    • Private Sub Form_Load()
    • If App.PrevInstance Then
    • Unload Me
    • Exit Sub
    • End If
    • End Sub
  • Unfortunately, this property doesn't exist in VB .NET. However, you can simulate it using the System.Diagnostics.Process class. This class contains a function called GetProcessesByName that you can use to determine if your application is currently running. Given this, you can use the following code to simulate the VB 6 functionality:
    • Private Sub Form1_Load(ByVal sender As Object, _
      ByVal e As System.EventArgs) Handles MyBase.Load
    • If UBound(Diagnostics.Process.GetProcessesByName _
      (Diagnostics.Process.GetCurrentProcess.ProcessName)) _
      > 0 Then
    • Me.Close()
    • Exit Sub
    • End if
    • End Sub

Tip: The Unload function doesn't exist in the next generation of VB (VB .NET)

  • When you need to unload a form in VB 6, you use code similar to the following:
    • Unload Me
  • Well, the Unload function is no longer valid in VB .NET. However, you can use one of the following methods to close an open form:
    • Me.Close
    • or
    • Me.Dispose

Tip: Easily incorporate code from other files into your application (VS .NET)

  • Typically, when you need to borrow code from another application and rework it for your own purposes, you open the source file, cut the code from the file, and paste it into your application file. However, with Visual Studio .NET, you can pull the entire contents of the file into your application without cutting and pasting. To see what we mean, use the Project | Add Class menu option to add a new class to your .NET project. Next, delete the default class code and select Edit | Insert File As Text from the main menu. Use the resulting dialog box to choose an existing class file and click the Open button. When you do this, .NET loads the entire contents of the file into the class code window.

Tip: Drag objects on your form to a new position at runtime using a Timer and Mouse events (VB .NET)

  • Would you like to drag an object on your form to a new position at runtime? Well, you can do so easily with Timer and Mouse events. Essentially, youíll use the MouseDown() and MouseUp() events to start and stop the Timer and the Timer to change the location of the object on your form. To try this out, open your Toolbox and add a Timer and TextBox control to your Windows form. Use the Property window to set the Interval property of the Timer to 50. Next, switch to code view and locate the MouseDown() event of the Button. Enter the following code in the event subroutine to enable the Timer when you click the TextBox on your form:
    • Timer1.Enabled = True
  • Then, place the next line of code MouseUp() event of the TextBox to disable the Timer when you release the mouse button:
    • Timer1.Enabled = False
  • Finally, place the next set of code in the Tick() event of the Timer to change the location of the TextBox as you hold down your mouse button:
    • TextBox1.Location = Me.PointToClient(New Point( _
      Me.MousePosition.X, Me.MousePosition.Y))
  • When you execute the code, click the text box on your screen and hold the mouse button. Move the object around your form and then release the mouse button to place the text box in its final position.

Tip: Retrieve the index of a clicked ListBox item with the IndexFromPoint() function (VB .NET)

  • After the MouseDown() event of a ListBox fires, .NET updates the ListBox object to reflect the currently selected item. Of course, this doesnít help you if you need to complete a task inside the MouseDown() event, such as starting a drag/drop operation. In this case, you should use the IndexFromPoint() function. This overloaded function takes as arguments either two integer values or a drawing point object representing the position of the mouse pointer on the ListBox when the user clicked the mouse. It returns the ListBox index of the item the user clicked. To make things really easy, the MouseDown() event supplies the necessary values to execute this function in its argument. If placed in the MouseDown() event of a ListBox named ListBox1, the following line of code would display a message box containing the index of the item the user clicked:
    • MsgBox(ListBox1.IndexFromPoint(e.X, e.Y))
  • If a ListBox is empty, the IndexFromPoint() function returns -1.

Tip: Combine projects and assemblies in one solution to better manage them (VB .NET)

  • The most common type of DLL .NET developers create is a private assembly. Private assemblies are considered private because they exist in the same folder as the program that references them. Although you can store the assembly source anywhere you want, to make your life easier you should create a solution that contains both the assembly and the client project. This serves two purposes.
  • First, it'll make it easier for you to see what private assemblies your project uses. When you add an assembly project to a solution, VS .NET separates it from other assemblies by placing it on the Projects tab of the References dialog window.
  • Second, you wonít have to worry if the client has the latest version of the assembly because .NET will make sure this is the case every time you build the solution.
  • To create the combined solution, you can simply launch Visual Studio .NET and select File | New | Blank Solution from the menu. After you select a name and location for the solution, use the File | Add Project | Existing Project menu option to add your application project and assembly project to the solution.

Tip: Create more flexible applications with class libraries (VB .NET)

  • A .NET class library, or component, is a collection of one or more classes compiled together as a unit. Class libraries allow you to create "pluggable" applications where you can debug, enhance, replace, and modify components individually without having to rebuild the entire application. You can use a class library for your business logic, common formatting functions, and more. To create a class library:
    • 1) Create a new project in Visual Studio .NET
    • 2) Select class Library from the New Project dialog box
    • 3) Choose a name and location for your library and click the OK button
  • By default, .NET starts you off with one class but, you can add as many classes to the library as you like. When you're done, select Build | Build Solution from the menu to save the class library file (DLL) in the bin folder of your class' location.
  • You can deploy a class library to any client machine that has the .NET Framework installed. To do so, simply copy the DLL files to the client machine. Unlike COM applications of old, you don't have to register class libraries to use them.

Tip: Allow users to select colors without a dialog window (VB .NET)

  • As you may know, VB .NET offers a ColorDialog component that you can load to help users pick colors at runtime. However, you don't need a separate window for this task. The .NET Framework consists of 167 system-defined colors. The Color object exposes the FromKnownColor() function, which allows you to access these colors, by index, using the following syntax:
    • Color.FromKnownColor(idx)
  • For the standard system colors, you can pass this function any value from 1 to 167. Although, you may want to skip the first 28 colors, since they're just your basic control colors, like ActiveBorder and ControlText. The following code uses the FromKnownColor() function to dump the system-defined color names out to a ListBox.
    • Dim clr As Color
    • Dim enumClr As KnownColor
    • For enumClr = 28 To KnownColor.YellowGreen
    • clr = Color.FromKnownColor(enumClr)
    • ListBox1.Items.Add(clr.ToKnownColor.ToString)
    • Next
Tip: Write fewer lines of code when adding dynamic controls to a form using the AddRange() method (VB .NET)
  • Typically, when you add multiple controls to a form dynamically, you add each control one by one, like so:
    • Dim button1 As new System.Windows.Forms.Button
    • Dim button2 As new System.Windows.Forms.Button
    • Dim button3 As new System.Windows.Forms.Button
    • Me.Controls.Add(button1)
    • Me.Controls.Add(button2
    • Me.Controls.Add(button3)
  • However, in VB .NET, you can save a few keystrokes by suing the AddRange() method.  This method allows you to add an array of controls to the collection instead of just one control at a time.  The syntax for the AddRange() method is as follows:
    • AddRange(ObjectArrary())
  • where the ObjectArray() argument holds an array of Control objects.  When you use this method, you can add the same three Button objects to the Controls collection using the following line of code:
    • Me.Controls.AddRange(New Control() {button1, button2, button3})

Tip: Restrict TextBox entries using the KeyPress() event (VB 6)

  • If your ever need to restrict a TextBox to only numeric or only alphanumeric entries, you can do so using the KeyPress() event of the TextBox.  This event subroutine has a single integaer argument called KeyAscii.  The KeyAscii value identifies the key that the user just pressed.  For example, the values 48-57 represent the numbers 0-9 and values 65-90 represent the capital letters A-Z.
  • To cancel a key press, you'll want to set the KeyAscii value to 0.  Therefore, to restrict a TextBox to only capital letters, you could use the following code:
    • If KeyAscii < 65 Or KeyAscii > 90 Then KeyAscii = 0
  • Some values have VB constants that can be used in place of the integer values.  For example, the next set of code accepts only numbers in the TextBox field:
    • If KeyAscii < vbKey0 Or KeyAscii > VbKey9 Then KeyAscii = 0
  • For a full a list of valid ASCII values and their character equivalents, visit the MSDN Web site at

Tip: For elegant error handling, Try code statements and Catch the errors (VB .NET)

  • Like all .NET languages, VB .NET, uses structured exception handling. This structure avoids the On Error Goto statement's ugliness by using a modern block structure, like so:
    • Try
    •         DoSomethingDangerous()
    • Catch
    •         ' Handle error here.
    • Finally
    •         ' Perform final cleanup.
    • End Try
  • As you can see, a structured exception-handling block consists of three parts:
    • --The Try block encapsulates the code that might generate an error.
    • --The Catch block contains the actual error handling code.
    • --The optional Finally block includes code that executes when the Try and Catch blocks conclude. The Finally code always executes, even if an unrecoverable error occurs that requires your program to end immediately.
  • When an error occurs, VB .NET throws a special Exception object, which your application, or VB, catches. This object contains information about the problem. VB derives every Exception from the base System.Exception class. In addition to this class, VB .NET also defines several broad category Exception objects, also based on the System.Exception object. Once you're familiar with the exception classes, you can take charge of exception handling and write error handlers targeted at specific types of problems. To do so, you specify the error class explicitly in the Catch statement. The following simple example illustrates how to handle exceptions:
    • Public Sub SwapNumbers(ByRef BigNumber As Integer,
    •         _ ByRef SmallNumber As Int16)
    •            Dim TempNumber As Integer = BigNumber
    •            ' The widening conversion always succeeds.
    •            BigNumber = SmallNumber
    • Try
    •                         ' This is more risky.
    •                         SmallNumber = TempNumber
    •          Catch ErrorObj As OverflowException
    •                      ' Handle an overflow here.
    •          Catch ErrorObj As DivideByZero
    •                     ' Handle a division by zero here.
    •                     ' (Not possible in this code.)
    •          Catch ErrorObj As NullReferenceException
    •                     ' Handle an error caused by trying to
    •                     ' use an unitialized object.
    •                     ' (Not possible in this code.)
    •          End Try
    • Sub

Tip: Easily access the days of the week with the dayofWeek Enumeration (VB .NET)

  • Working with the days of the week in VB .NET is a simple task.  That's because the Framework has a built-in Enumeration type for the days of the week called DayOfWeek.  To interate this Enum and return all the week names, you can then call the GetNames method of the Enum type, like so:
    • Dim WeekDay As String
    • For Each WeekDay In [Enum].GetNames(GetType(DayOfWeek))
    • MsgBox(WeekDay)
    • Next
  • If you just need to return the day of the week for a specific date, you can use code similar to the following:
    • Dim dt As New DateTime(2004, 6, 20)
    • MsgBox(dt.DayOfWeek.ToString)

Tip: Beware of Clnt; use CDbl instead (VB 6.0)

  • If you have any program that converts string values to numbers, you'll want to steer clear of the Clnt function and use CDbl instead.  The problem with Clnt is that it only accepts numbers up to 32767.  You might say today, "My number will never get that large."  However, later on down the line, it might.  Unfortunately, by that time, your code may be riddled with hundreds of Clnt time bombs waiting to blow up, displaying the dreaded Overflow error.  Using the CDbl function is no different from using Clnt.  The syntax is:
    • CDBl(numbericstring)
  • CDbl returns the same value as Clnt and it accepts num-bers up to 1.7976931348623158E+308.

Tip: For maximum performance, execute SQL stored procedures with a DataReader (VB .NET)

  • SQL stored procedures are designed to be more efficient than outside queries. However, any performance boost you gain from using a stored procedure may be lost when you load the whole stored procedure result set into a DataSet. Instead, you should use the SQLDataReader to retrieve the data one row at a time. Luckily, pairing the two together is really quite simple. Consider the following code:
    • Dim cn As SqlConnection = New SqlConnection( _
    •             "server=svr1;uid=uid1;pwd=pw1;database=yoursqldb")
    • Dim myCMD As SqlCommand =New SqlCommand( _
    •             storedprocedurename, cn)
    • myCMD.CommandType = CommandType.StoredProcedure
    • cn.Open
    • Dim myReader As SqlDataReader = _
    •             myCMD.ExecuteReader(CommandBehavior.CloseConnection)
  • If the stored procedure has parameters, you'll need to create a parameter object, supplying the name of the parameter and its SQL data type. For example, you'd use code similar to the following to create an object that accepts an Integer value for input:
    • Dim param As SqlParameter = myCMD.Parameters.Add( _
    •             parametername, SqlDbType.Int)
    • param.Direction = ParameterDirection.Input
  • If your stored procedure returns more than one result set, the DataReader allows you to retrieve the result sets one at a time using the NextResult() method, like so:
    • myReader.NextResult()

Tip: Locate a variable in your project with the Definition menu option (VB IDE/Visual Studio .NET)

  • Have you ever been debugging an application and came across an unfamiliar variable?  Well, you can easily find out where you declared the variable by using the Definition menu option.  To use this option, select a variable in your code and right-click on it.  Then, select Definition from the shortcut menu.  VB will jump to the area in your code where you declared the variable.  To return to the line in your code where you selected the variable, right-click in the declaration area and select Last Position from the shortcut menu.  If VB can't find the variable, it will display an error:  Identifier under cursor is not recognized.
  • You can also use this technique in Visual Studio .NET.  However, it doesn't offer the Last Position menu option to help you get back to the spot you left and it won't display an error if the variable declaration doesn't exist.

Tip: For data retrieval with low overhead, give the DataReader a try (VB. NET)

  • The DataSet is probably the most common tool for handling data in .NET. However, if you only need to retrieve small amounts of data for the purpose of displaying it, all the overhead of the DataSet to support two-way communication between the database and your .NET program is unnecessary. With the .NET DataReader, you can retrieve a read-only, forward-only stream of data and dump it out one row at a time.
  • The first few steps for creating a DataReader should sound familiar. You start with a Connection, pass it a ConnectionString, create a Command object, and open the Connection. From this point, to retrieve the data, you just need to call the ExecuteReader command. The following lines of code illustrates the process if you were working with a SQL database:
    • Dim cn As SqlConnection =New SqlConnection("server=svr1;" _
    •             "uid=uid1;pwd=pw1;database=yoursqldb")
    • Dim myCMD As SqlCommand = _
    •             New SqlCommand("SELECT * FROM SomeTable", cn)
    • myCMD.CommandType = CommandType.Text
    • cn.Open
    • Dim myReader As SqlDataReader = _
    •             myCMD.ExecuteReader(CommandBehavior.CloseConnection)
  • Once you create the SQLDataReader, you'll treat it just like you would a Recordset in classic ADO. You repeatedly call the Read() method until the DataReader retrieves all the rows. A While loop, similar to the one in the next set of code, works wonderfully:
    • Do While myReader.Read()
    •            'get data
    • Loop

Tip: The Val() function bug that won't go away (VB 6/.NET)

  • Many programmers use VB's Val() function to convert user inputted strings into numbers.  this useful function returns zero (0) for strings that are meaningless as numeric input Unfortunately, Val() has a bug in its routines.  Notably, Val("6%") returns 6, Val("6.%") returns 6, Val("6.0%") returns 6, but Val("6.1%") generates a Type Mismatch error!
  • Believe it or not, this is still an issue in VB .NET.  Except now both of the following lines will fail:
    • Val("6.0%")
    • Val("6.1%")
  • To avoid this error, try a routine that replaces the offending percentage sign with some other character, like this:
    • TheString = "15.7%"
    • Mid(TheString, Instr(TheString, "%"),1) = "$"
    • Debug.Print Val(TheString)
  • For .NET developers, the following line of code will do the trick:
    • Debug.WriteLine(Val(Replace(TheString,"%","$")))

Tip: Access DataSet tables through DataRelation objects in ADO.NET (Visual Basic .NET)

  • Once you've created ADO.NET Relations in your DataSet, you can access the DataSet's Table objects without using the Tables collection. Instead, you can use the ChildTable or ParentTable properties of the DataRelation. You query the ChildTable property using the following syntax:
    • objDataSet.Relations(RelationName|RelationIndex).ChildTable
  • This code returns a DataTable object when you reference a specific DataRelation by string name or index. So, if you want to see all the rows in the child table of a DataRelation, you can call this property and bind the results to a Windows list control (such as a DataGrid), like so:
    • DataGrid1.DataSource = objDataSet.Relations("RelationName"). _ ChildTable.DefaultView
  • The same syntax applies when requesting a parent table. You just use the ParentTable property instead of the ChildTable property.

Tip: Easily access Microsoft Excel data with ADO.NET (Visual Basic .NET)

  • You're probably very familiar with using the JET OleDb provider to access a Microsoft Access database in Visual Basic .NET. What you may not know is that you can also use it to interact with a Microsoft Excel spreadsheet!
  • When you use the JET provider, you need to tell it the type of data file you want to access. You'll do this with the Extended Properties keyword of the connection string. The extended property for accessing XLS files is Excel 8.0. Specifically, this value is valid for accessing Excel 97 (8.0), Excel 2000 (9.0), and Excel XP (10.0) files.
  • To access an Excel spreadsheet, you should create a connection string that uses the Excel 8.0 Extended Property, the Microsoft.Jet.OLEDB.4.0 provider, and identifies the name and location of XLS file. To retrieve the data from the spreadsheet, you create an OleDbDataAdapter object using a SQL Select statement and the connection string. Then, you simply load a dataset with the results. The following code demonstrates this process:
    • Dim strConn As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    •            "Data Source=c:\MySpreadsheet.xls;" & _
    • "Extended Properties=Excel 8.0;"
    • Dim myData As New OleDbDataAdapter ("SELECT * FROM [Sheet1$]", strConn)
    • Dim myDataset As New DataSet
    • myData.Fill(myDataset)
  • Notice that when you specify the worksheet name, you append a dollar sign ($) to the end and enclose the entire string in brackets ([]). You should also Import the System.Data.OleDb namespace.

Tip: Use the Val() function to strip unwanted characters from the end of numeric strings (VB 6/.NET)

  • If you have a numeric string with some trailing characters, strip out the characters in a single call with the Val() function.  Val() evaluates a string function to see if it can convert it into a number.  For example, the following statement would return the string "123456":
    • MsgBox(CStr(Val("123456smd")))
  • Notice that we specifically stated that the characters must be on the end of the string.  If the characters are at the beginning of the string (e.g., "smd123456"), then the Val() function will assume that the string can't be converted to a number and will return 0.

Tip: Put your VB application into deep sleep (VB 6/.Net)

  • There may be occasions when you want an application to wait for a specified period of time without performing activity or wait loops.  The Timer control can help, but only up to 60 seconds.  The Sleep Windows API function lets you put the application to sleep.  Enter the following declaration into a standard module:
    • Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
  • Then simply call the function from your code, as in:
    • Sleep 5000
  • In this case, the 5000 milliseconds put the application to bed for 5 seconds.  You can specify your own period of time, as necessary.

Tip: How to ignore textbox keystrokes in VB 6 and VB .NET (VB 6/.NET)

  • Do you need to ignore a textbox keystroke?  If so, you can easily accomplish this task in both VB and VB .NET.  In VB, place the following code in the KeyPress() event of the text box:
    • KeyAscii = 0
  • In VB 6, KeyAscii is a parameter of the KeyPress() event and it contains the Ascii value of the key the user just pressed.  Setting the value to 0 in the KeyPress() event nullifies the entry.
  • In VB .NET, there isn't a KeyAscii event argument.  So, to cancel the current keystroke, you'll need to use the Handled property of the e event argument, like so:
    • e.Handled = True
  • The Handled property tracks which events have been handled and which have not.  VB .NET will only pass on events that haven't been handled.  Hence, when you set the handled property to True in the KeyPress() event, you're essentially telling .NET that the event has been handled and to ignore it.

Tip: Retrieve binary data from SQL Server via ADO's Stream object (Visual Basic 6/ADO)

  • ADO's Stream object offers a great way to send and retrieve binary data into and from SQL Server. It's kind of like a programmatic pipeline. The data can consist of text or true binary information. The Stream object exposes several different methods and properties for use with each data type; however, the members have similar purposes. For instance, to read text, you use the ReadText method; for binary data, you use Read.
  • To open a Stream, you execute the Open method. When you do, the Stream object sits ready and waiting for data to convey. The following code snippet illustrates how you might prepare a Stream object for XML data:
    • Dim strm As ADODB.Stream
    • Set strm = New ADODB.Stream
    • With strm
    •             .LineSeparator = adCRLF
    •             .Mode = adModeRead
    •             .Type = adTypeText
    •             .Open
    • End With
  • The ADO Command object offers one way to plug data into a Stream object. The SQLOLEDB provider implements, among others, two new special properties for the Command object that help you achieve this end. The first property is Output Stream. This property indicates which Stream object the Command should fill with data. For XML extraction, the XML Root property tells ADO what to use as the name of the resulting XML document's root node. Note, that these are provider-specific extended properties. So, to set them, you must access the Command object's Properties collection, like so:
    • cmd.Properties("Output Stream").Value = strm
    • cmd.Properties("XML Root").Value = "data"
  • After setting these properties, along with the standard Command properties such as CommandType and CommandText, you execute the Command. Set the Options parameter to adExecuteStream to tell ADO to use the pipeline. When you do, ADO fills the supplied Stream object with the requested XML data.
  • At this point, however, the text is still technically considered binary data. To transform it into a string, you use the Stream object's ReadText method. This method takes an optional argument that indicates how much of the text you want to extract. Valid values include: adReadAll, adReadLine or the actual number of characters you want to retrieve.
  • When you read individual lines or characters from the file, you can test for the end of the file with the EOS property (End Of Stream), like this:
    • Do Until strm.EOS
    •           strXML = strXML & strm.ReadText(1000)
    • Loop
  • As you can see, ADO automatically iterates through the file on each successive call to the ReadText method. If the method reaches the end and doesn't find the specified number of characters, it returns the remainder.

Tip: Making SQL Server primary key NEWID() default values work with a Visual Basic .NET DataSet (Visual Basic .NET/SQL 2000)

  • Designing a SQL Server table to use the uniqueidentifier datatype for its primary key column and then giving it a default with the NEWID() function is a great way to manage your data; however, there can be a slight snag if you use ADO.NET's DataSet in Visual Basic .NET with such a table. In this scenario, adding records in a DataGrid in Visual Basic .NET will cause an error. The primary key field doesn't allow NULL values. We know that the key field will be defaulted on the SQL Server side, but Visual Basic .NET enforces the NULL before the data is pushed to SQL Server. The solution is easy, since we have access to the dataset XML. First, we can delete the key from the dataset table by right-clicking on the table and selecting the Delete Key. The field isn't deleted, just the key indicator for the field. Now the field won't require a unique value, but we still need to allow the value to be NULL. This is done by adding minOccurs="0" to the <xs:element> code for this field, as in the example below:
    • <xs:element
    •             name="KeyFieldName"
    •             msdata:DataType="System.Guid, mscorlib, version=1.0.3300.0,
    • Culture=neutral, PublicKeyToken=b77a5c561934e089"
    •                       type="xs:string"
    •                       minOccurs="0" />
  • Now records can be added to the grid without raising any errors, and SQL Server will use the NEWID() default for primary key column values once the table is updated.

Tip: Use the TypeOf function to quickly clear all controls from a form (VB 6)

  • By using the following code, you can quickly clear all the text boxes on your form:
    • Dim vControl as variant
    • For Each vControl In Me.Controls
    •   If TypeOf vControl Is TextBox Then vControl.Text = ""
    • Next
  • This code also works in VB .NET, but now you can take advantage of the TextBox Clear property, like so:
    • Dim vControl as Object
    • For Each vControl In Me.Controls
    •    If TypeOf vControl Is TextBox Then vControl.Clear()
    • Next

Tip: Lock ProgressBar controls to your form using a StatusBar control (Visual Basic .NET)

  • Visual Basic .NET makes it easy to add a progress bar to a form with its built-in ProgressBar control. And for the most part, locking a ProgressBar control on a form works well. Until, of course, you resize the form. If you make the form too small, you'll end up clipping the progress bar and hiding portions of it from view. One way to prevent this problem is to place the progress bar inside an object that can grow and shrink with the form, such as a status bar.
  • To see what we mean, create a new Visual Basic .NET Windows Application and add a ProgressBar and a StatusBar control to the form. Right away you should notice that the StatusBar automatically fills the form and anchors itself to the bottom of the form. On the other hand, the ProgressBar will be only as large as you draw it. Now, right-click on the design page and select View Code from the shortcut menu. Then, add the following two lines of code to the form's Load() event:
    • ProgressBar1.Parent = StatusBar1
    • ProgressBar1.Dock = DockStyle.Fill
  • The first line makes the StatusBar control the parent of the ProgressBar control. The second line locks the progress bar inside the status bar and tells .NET to devote the entire status bar to the progress bar. Now, when you run the program and resize the form, the progress bar shrinks and grows with it.

Tip: Visual Studio .NET gives you the power to collapse portions of your code in the code designer (VB.NET)

  • When working with code in VB .NET, you'll notice small plus and minus signs in the margin next to the code.  These icons allow you to expand and collapse various sections of the VB .NET system code.  However, VB .NET didn't keep this little feature to itself.  It allows you to place your custom code in collapsible regions as well.  To do so, use your mouse to select a portion of your VB code.  Then, place the mouse cursor over the selected region and click the right mouse button.  Finally, select Outlining | Hide Selection from the resulting pop-up menu.  Visual Studio will place the code in a collapsible region.  You can re-expand the region by clicking on the plus icon.  To keep track of what's in the region, place a comment on the line next to the plus or minus icon.

Tip: Finding Application information in .NET (Visual Basic .NET)

  • Have you been looking in the Visual Basic .NET project properties for the application information (version, company name, product, etc.)? Visual Basic 6 exposes this information on the Make tab of the Project Properties window, you won't find it there in .NET. Visual Basic .NET stores the application information in the AssemblyInfo.vb file it generates with each project. The following is an excerpt from this file:
    •  <Assembly: AssemblyTitle("")>
    • <Assembly: AssemblyDescription("")>
    • <Assembly: AssemblyCompany("")>
    • <Assembly: AssemblyProduct("")>
    • <Assembly: AssemblyCopyright("")>
    • <Assembly: AssemblyTrademark("")>
    • <Assembly: CLSCompliant(True)>
  • To set a value, insert the desired text into the quotes: AssemblyProduct("Time and Attendance System"). To retrieve the information from your program, use the .NET Application class, like so:
    • Debug.WriteLine (Application.ProductName)

Tip: Provide instant help to users with ToolTips (Visual Basic .NET)

  • Visual Basic 6 developers are probably very familiar with ToolTips, since almost every control has a ToolTipText property built in. However, to provide ToolTips in Visual Basic .NET, you need to use the ToolTip control. Once you've added the ToolTip control to a form, click on any other control on the form and locate its ToolTip property in the Properties list (the actual property name includes the word "on" and the control name). Then, enter a tip string. One of the advantages Visual Basic .NET's ToolTips have over those in Visual Basic 6 is the ability to produce multi-line tip strings. To create a multi-line ToolTip, use the SetToolTip() method of the ToolTip control, like so:
    • ToolTip1.SetToolTip(TextBox2, _ "Enter the phone" & vbCrLf & _ "number in the format:" & vbCrLf & _ "(555)555-5555")

Tip: The Deactivate event seems a little trigger-happy in VB .NET (VB .NET)

  • Be very careful of the type of code you place in the Deactivate event of a Form in VB .NET.  In VB 6, this event really only fires when you navigate to another VB form.  In VB .NET, it fires when you do just about anything.  For example, minimizing the form, launching a MsgBox, and navigating to Visual Studio .NET code all triggered the Form Deactivate event.

Tip: Create new event handlers to process control events (Visual Basic .NET)

  • Visual Basic .NET allows you to modify the default event handlers for a control to process any number of events from any control on the form. However, if you prefer, you can leave the default event handlers alone and create your own event handlers to process the events along with, or in lieu of, the original event handler. To illustrate a simple event handler, we added two buttons to a default Windows Application form. We then used the following code to create a new event handler:
    • Private Sub HandleAllClicks(ByVal sender As System.Object,
  • ByVal e As _
    • System.EventArgs) Handles Button1.Click, Button2.Click
    •             MsgBox("You Clicked " & CType(sender, Control).Name)
    • End Sub
  • This code creates a HandleAllClicks() event to process the Click() event for each button. It then displays the name of the control you clicked. It does so without affecting the existing Click() event subroutines for the buttons. If you wish, you can also place code in the default Click() events for the buttons and process the event twice. However, you'll have no control over which event code .NET executes first.

Tip: Save time and improve efficiency with the String Builder object (VB .NET)

  • If you have intensive concatenation operations, you should consider using the StringBuilder object instead of just a concatenating the strings.  The StringBuilder object is more efficient because it allows you to work directly with the string instead of building, destroying, and re-building it, which is what happens with regular string concatenations.  However, it also saves you a few keystrokes because you won't have to assign a new value to the string.  Take a look at the following code snippet:
    • Dim strName1 As String = "Visual"
    • strName1 = strName1 & "Basic"
    • MsgBox(strName1)
    • Dim strName2 As System.Text.StringBuilder = New System.Text.StringBuilder
    • strName2.Append("Visual")
    • strName2.Append("Basic")
    • MsgBox(strName2.ToString)
  • Obviously, this isn't a particularly sexy example, but for concatenation inside lengthy loops and other such intensive scenarios, the StringBuilder can be up to 50 time faster than concatenation.

Tip: Make a real statement with your forms using the AddString method (Visual Basic .NET)

  • You're probably aware that you can shape Windows forms into circles, triangles, or any other shape using a GraphicsPath object. However, did you know that you can also shape a form into a string of text? To do so, place the following code in the Load() event of a Windows application:
    • Dim gPath As System.Drawing.Drawing2D. _
    • GraphicsPath = New System.Drawing. _
    • Drawing2D.GraphicsPath
    • Me.BackColor = Color.Blue
    • gPath.AddString("This is" & vbCrLf & _
    • "WAY COOL!", _
    • New FontFamily("Arial Black"), _
    • FontStyle.Bold, 60, _
    • New Point(5, 10), _
    • StringFormat.GenericDefault)
    • ' Constrain the form to the region.
    • Me.Region = New Region(gPath)
  • The AddString method creates a GraphicsPath object using the string "This is WAY COOL." Then, you just need to assign the new path to the Form's Region property. You an even use carriage returns in the string, as we've done in the sample code.

Tip: Create circle-shaped forms with just a few APIs (Visual Basic 6)

  • If you're tired of bland, square forms, you're in luck. You can take the edge off your forms literally, with the CreateRoundRectRgn() and SetWindowRgn() API functions. The CreateRoundRectRgn() function generates a shaped area for the form. The SetWindowRgn() function uses the shaped area to clip the form. You'll declare these two functions in the global declarations section of a new Windows application using the following code:
    • Private Declare Function CreateRoundRectRgn _ Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, _ ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As _ Long, ByVal Y3 As Long) As Long
    • Private Declare Function SetWindowRgn Lib "user32" _ (ByVal hwnd As Long, ByVal hRgn As Long, _ ByVal bRedraw As Long) As Long
  • Then, set the form's ScaleMode property to Pixel and place the next set of code in the form's Paint() event:
    • Dim hRegion As Long
    • Me.Cls
    • hRegion = CreateRoundRectRgn(0, 0, Me.ScaleWidth, _
    •            Me.ScaleHeight, Me.ScaleWidth, Me.ScaleHeight)
    • Me.DrawWidth = 5
    • SetWindowRgn Me.hwnd, hRegion, True
  • When you execute the program, Visual Basic displays the form in the shape of a circle.

Tip: Prevent users from closing a form (VB .NET)

  • There are a number of different ways a user can unload a form. Click the Exit button or menu item; click on the X in the upper-right corner of the form; select Close from the form window's pop-up menu in the upper-left corner; even cancel the program from the Task Manager. However he closes the form, you can stop it in the Closing() event of the form, like so:
    •  e.Cancel = True
  • Unfortunately, .NET did away with the UnloadMode structure. So, unlike VB 6, you won't know how the form is closing, you'll just know that it is.  

Tip: To improve efficiency, don't call Array method in For...Next loop (VB 6/.NET)

  • In a recent tip, "Define your own loop criteria using the Array method (VB 6), "we offered the following code:
    • Dim x As Variant
    • For Each x In Array("Monday","Tuesday","Wednesday","Thursday", "Friday")
    •     MsgBox (x)
    •   Next
  • Well, many readers contacted us to say this method of looping isn't very efficient because it calls the Array method with each iteration.  You suggested the following change:
    • Dim x As Variant
    • Dim myarray As Variant
    • myarray = Array("Monday","Tuesday","Wednesday","Thursday", "Friday")
    • For Each x In myarray
    •    MsgBox (x)
    • Next
  • VB NET solution that shows you no longer need the Array method at all:
    • Dim DaysOfTheWeek() As String = {"Monday","Tuesday","Wednesday","Thursday", "Friday"}
    • Dim WeekDay As String
    • For Each WeekDay In DaysOfTheWeek
    •    MsgBox(WeekDay)
    • Next

Tip: The Timer Interval property behaves differently in VB .NET (VB .NET)

  • In VB 6, you could turn the Timer control on by setting the Interval property value to a number greater than 0 and you could turn it off by setting the value to 0, like so:
    • Timer1.Interval = 60
    • Timer1.Interval = 0
  • VB .NET will throw and exception if you set the Interval property to a value less than 1.  To turn the Timer component on and off, you must use the Enabled property as shown below:
    • Timer1.Enabled = True
    • Timer1.Enabled = False
  • One other small note about the Timer Interval property, the maximum value is no longer 65,535 milliseconds.  The .NET Timer can tick for more than 2.1 billion milliseconds (the maximum integer value).  So if you have some reason for an application to wait a few weeks, the new .NET Timer should suit your needs just fine.

Tip: Save a reference to opened processes so you can destroy them later (VB .NET)

  • To start a process in Visual Basic .NET, you use the Start method of the System.Diagnostics.Process class, like so:
    • System.Diagnostics.Process.Start("someapp")
  • However, when you start a process in this manner, it's up to the user to shut it down when he's done. If you'd like to control the life of the application, declare a global process object and save a reference to the new process when you execute it, like so:
    • Public myProcess As New System.Diagnostics.Process
  • Private Sub Button1_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click myProcess = System.Diagnostics.Process.Start _ ("notepad.exe") End Sub
  • This code launches the Notepad application when the user clicks a button and it saves a reference to the opened process in the global myProcess object. Now we can use the Kill method of the Process object to close the Notepad at any time, like so:
    • myProcess.Kill()

Tip: The Timer control changes in VB .NET (VB .NET)

  • In VB .NET, the Timer control is now the Timer component.  You'll still find it in the ToolBox, but you won't be able to draw it on your form.  Instead, when you double-click on it, .NET will place it in the component tray of the Visual Studio development environment.  (The component tray is a special rectangular area at the bottom of the Visual Studio development environment.  It won't be visible until you actually add a component to your project.)  Since the Timer is a component in .NET, it no longer supports the Name, Left, Tag, and Top properties of its VB 6 predecessor.  VB .NET also renamed the Timer event to the Tick event.

Tip: Easily create and execute Web links with the LinkLabel control (VB .NET)

  • Visual Basic .NET makes Web links easy with the LinkLabel control. You'll find this control in the standard Visual Basic .NET Toolbox. Simply click on it, draw it on your form, and then set the Text property to your desired URL. Next, to navigate to the link, add the following code to the LinkClicked() event of the LinkLabel:
    • System.Diagnostics.Process.Start _(LinkLabel1.Text)
  • The Start method of the Process class executes the application string that you pass it. If you don't supply an application to the method, the text you pass to it dictates which application the system launches. So, if you just pass it a URL, it opens it using Microsoft Internet Explorer.
  • The LinkLabel control comes equipped with quite a few properties to help you create the perfect Web link. For example, you can enter lines and lines of text into the control's Text property. Then, use the LinkArea property and associated LinkArea Editor to select only the text you want for the link. You can also specify whether the text has a permanent underline, no underline, or an underline visible only when the user hovers over the link using the LinkBehavior property. The valid values for this property are SystemDefault, AlwaysUnderline, HoverUnderline, and NeverUnderline. For additional customization, change the default link color and visited link color using the LinkColor and VisitedLinkColor properties. You can even embed an image right into the link using the Image property.

Tip: Add Bookmark options to the Toolbar for easy access (VB 6 IDE)

  • If you use the Bookmark options often, you may find it helpful to place them right on the VB 6 Toolbar.  To do so, select View | Toolbars | Customize window, click Edit in the Categories list.  Next, scroll down the Commands list until you can see the Bookmark options.  To add a Bookmark option to the VB 6 Toolbar, simply click on it and drag it to the Toolbar.  After you close the customize window, you'll have quick and easy access to the Bookmark options you selected.  If you ever want to remove a Bookmark option, click on it and drag it off the Toolbar.

Tip: Take care when using the TextBox Change() event in VB .NET (VB .NET)

  • If you have code behind a TextBox Change() event that VB .NET is executing before the form even loads, you may want to check to make sure the Text property of to the TextBox doesn't contain a value.  VB .NET triggers the Change() event when it adds the Text value to the TextBox just as if you'd entered it yourself.  In contrast, VB 6 doesn't trigger the Change() event when you use the Text property to initialize a field.

Tip: For truly optional parameters, use a parameterized array (VB 6/ .NET)

  • You can use the ParamArray keyword in the declaration line of a method to create a subroutine or function that accepts an arbitrary number of parameters at runtime. For example, you can create a method that fills a list box with some number of items even if you don't know the number of items you'll send. To try it out for yourself, add the method below to a form:
    • Public Sub FillList(ListControl As _ ListBox,ParamArray Items())
    •                    Dim i As Variant
    •                    '
    •                    With ListControl
    •                               .Clear
    •                               For Each i In Items 
    •                                           .AddItem i
    •                               Next
    •                    End With
    •                    '
    •            End Sub
  • Note that the ParamArray keyword comes before the parameter in the declaration line. Now, add a list box and a command button to your form. Finally, add the code below to the Click() event of the command button.
    • Private Sub Command1_Click()
    •            '
    •            FillList List1, "Go", "Miami","Dolphins!"
    •            '
    • End Sub  

Tip: Use the Optional keyword to identify parameters that the user isn't required to supply (VB 6/.NET)

  • If you'd like to have optional arguments in the argument list of your subroutine or function, you can do so quite easily with the Optional keyword. The syntax for this keyword is:
    • Function myFunctionOpt(Optional ByVal var1 _ As Object = val, Optional ByVal var2 As _ Object = val,...)
  • The Optional keyword should precede any argument the user isn't required to supply. The ByVal/ByRef keyword is required only for VB.NET. If the user omits the argument when calling the function, VB uses the value in val as a default. The default value is also only required for Visual Basic .NET. Optional values must follow any required parameters in the function's parameter list. To call a function or subroutine containing optional parameters, enter a comma for each parameter even if you don't supply a value, like so:
    • myFunctionOpt(,7)  

Tip: VB .NET allows you to remove all form controls with the Remove Method (VB .NET)

  • You may recall that in VB 6 you could loop through the Controls collection and remove form controls a by calling the Controls.Remove method.  However, this method was only valid for controls added using Controls.Add.  If the Coleftion contained static controls that you added using the traditional drag-and-drop method, trying to remove them using Controls.Remove would raise and error.  In contrast, VB .NET treats all controls in the Controls collection equally.  As a result, Controls.Remove will remove all controls whether you added them at design time or runtime.

Tip: Loop through VB's ADOX to obtain a list of all database tables (ADOX)

  • If you need to obtain a list of all the database tables in a database, you can do so easily using Microsoft ActiveX Data Objects Extensions, or ADOX.  To do so, first set a reference to Microsoft ADO Ext.  For DDL and Security.  For schema purposes, Next add a ListBox and CommandButton to your form.  Then, you can use code similar to the following:
    • Dim cat As New ADOX.Catalog
    • Dim tbl As ADOX.Table
    • Dim cn As New ADODB.Connection
    • Dim cnstr As String
    • cnstr = "Provider=Microsoft.Jet.OLEDB.3.51;" _
    • & "Data Source=C:\Program Files\Microsoft Visual Studio\VB98\Biblio.mdb"
    • List1.Clear
    • cn.ConnectionString = cnstr
    • cn.Open
    • cat.ActiveConnection = cn
    • For Each tbl In cat.Tables
    • If tbl.Type = "TABLE" Then List1.AddItem (tbl.Name)
    • Next tbl

Tip: Enabling the Edit and continue flag in Visual Studio .NET doesn't do what you might think (VS .NET)

  • If you've done any debugging in Visual Basic .NET, you probably know by now that you can't modify the code during this process. This was a wonderful feature in VB 6 because you could fix bugs in the code and VB would process the changes and continue running the application.
  • We were overjoyed when we came across a setting in Visual Studio .NET that seemed to return the beloved feature that we thought was lost to us. You'll find the setting we're referring to in the Tools | Options menu's Debugging | Edit And Continue folder.
  • By default, the option Allow Me To Edit VB Files While Debugging is turned off. Unfortunately, even when you turn it on, the debugger won't behave the way the debugger behaved in VB 6. Visual Studio allows you to modify the code, but after that point, your options are to restart the program or ignore the changes. This isn't as helpful as the VB 6 feature.  

Tip: Be on the lookout for those sneaky variant variable (VB 6)

  • As developers we use so many different languages these days, it's sometimes hard to see our programming mistakes.  This is especially true when the job requires us to move between a non-compiled language like VBScript and Visual Basic 6.  One of the most common mistakes that could wreak havoc on an application's performance is in the area of variable declarations.  Too many variant variables can and will weigh down an executable.  Following are two of the more common culprits that can cause unwanted variants to sneak into your application:
    • Dim x, y as integer
    • Dim z
  • In the first statement, x will be typed as an Integer but, y will be a variant.  Likewise, z will be a variant because the Data Type information is absent.

Tip: An easy way to disable a multi-line textbox while still allowing users to scroll (6)

  • If you have a scrollable, multi-line textbox that you want to disable for certain users, you might be tempted to just set its Enabled property to False. Unfortunately, if those users still need to see all the data in the field, they won't be able to use the scroll bars, either. Luckily, there's a quick and simple solution to this problem. In the TextBox control's KeyPress() event, place the following line of code:
    • KeyAscii = 0
  • This line of code prevents the user from entering any additional data in the field, but he'll still be able to view the current data.  


Home | Company Info | Pricing | Contacts | Client Directory | Computer Tips | NewsTestimonials |
Disclaimer | Our Privacy Policy | Terms of Use | Site Map

Business Website Links, LLC ē 8041 Via Hacienda ē Palm Beach Gardens ē Florida ē 33418

Copyright ©2005 all rights reserved by Business Website Links, LLC
Web Host and Design by Business Website Links, LLC