Category Archives: MSDN Forum Resonses

Creating a skinnable application

I posted this to the forum for someone asking questions who was acting very arrogant, so I decided to delete my posts from that thread’ I felt like this code still offers someone else the opportunity to learn, so I moved to this blog.

Here is an example of making a custom program skinnable, but be informed that every little detail needs to be addressed. If you need to make for the skin writer(end user) to be able to specify drag areas of the form, then you need to create that logic. Every single little detail that you wish to be customized, needs to be added to the library, and also the logic to: Serialize, deserialize, validate, and apply it.

This is an extreme amount of work to allow for skinnable applications, so I hope your application is worth skinning.

Example Configuration File(Created with the SimpleSkin.ToXMLFile method)
*Note if you would like to add more fields, you need to modify the library(listed further down)

<?xml version="1.0" encoding="utf-16"?>
<SimpleSkin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FormSkinPath>C:\Users\et3ishak\Desktop\myFormSkin.png</FormSkinPath>
  <Button1SkinPath>C:\Users\et3ishak\Desktop\skinnedButton.png</Button1SkinPath>
  <Button1MouseDownSkinPath>C:\Users\et3ishak\Desktop\skinnedButtonMouseDown.png</Button1MouseDownSkinPath>
  <Button1Location>
    <X>100</X>
    <Y>100</Y>
  </Button1Location>
</SimpleSkin>

Example Usage:

Option Strict On
Option Explicit On
Option Infer Off
Imports System.IO
Public Class Form1
    Private FormSkinPath As String = Nothing 'My.Computer.FileSystem.SpecialDirectories.Desktop & "\myFormSkin.png"
    Private Button1SkinPath As String = Nothing 'My.Computer.FileSystem.SpecialDirectories.Desktop & "\skinnedButton.png"
    Private Button1MouseDownSkinPath As String = Nothing 'My.Computer.FileSystem.SpecialDirectories.Desktop & "\skinnedButtonMouseDown.png"
    Private Button1Location As Point = New Point(100, 100)
    Private SimpleSkin1 As New CustomSkinningLibrary.SimpleSkin
    WithEvents skinnedForm As CustomSkinningLibrary.SkinnableForm
    Private Sub btnShowSkinnedForm_Click(sender As Object, e As EventArgs) Handles btnShowSkinnedForm.Click
        With SimpleSkin1
            .FormSkinPath = Me.FormSkinPath
            .Button1SkinPath = Me.Button1SkinPath
            .Button1MouseDownSkinPath = Me.Button1MouseDownSkinPath
            .Button1Location = Me.Button1Location
        End With
        Try
            skinnedForm = CustomSkinningLibrary.SkinnableForm.Create(SimpleSkin1)
            skinnedForm.Show()
        Catch ex As CustomSkinningLibrary.SkinIncompleteException
            For Each s As String In ex.Errors
                MsgBox(s)
            Next
        End Try
    End Sub
    Private Sub btnSetFormSkinPath_Click(sender As Object, e As EventArgs) Handles btnSetFormSkinPath.Click
        Dim ofd As New OpenFileDialog With {.Title = "Select Form Skin Image"}
        ofd.Filter = "JPEG files (*.jpg)|*.jpg|GIF files (*.gif)|*.gif|All files (*.*)|*.*"
        ofd.Multiselect = False
        If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
            Me.FormSkinPath = ofd.FileName
        End If
    End Sub
    Private Sub btnSetButton1SkinPath_Click(sender As Object, e As EventArgs) Handles btnSetButton1SkinPath.Click
        Dim ofd As New OpenFileDialog With {.Title = "Select Button Skin Image"}
        ofd.Filter = "JPEG files (*.jpg)|*.jpg|GIF files (*.gif)|*.gif|All files (*.*)|*.*"
        ofd.Multiselect = False
        If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
            Me.Button1SkinPath = ofd.FileName
        End If
    End Sub
    Private Sub btnSetButton1MouseDownSkinPath_Click(sender As Object, e As EventArgs) Handles btnSetButton1MouseDownSkinPath.Click
        Dim ofd As New OpenFileDialog With {.Title = "Select Button MouseDown Skin Image"}
        ofd.Filter = "JPEG files (*.jpg)|*.jpg|GIF files (*.gif)|*.gif|All files (*.*)|*.*"
        ofd.Multiselect = False
        If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
            Me.Button1MouseDownSkinPath = ofd.FileName
        End If
    End Sub
    Private Sub btnSaveSkinDataToXml_Click(sender As Object, e As EventArgs) Handles btnSaveSkinDataToXml.Click
        MsgBox("Make sure you set all your properties!")
        Dim sfd As New SaveFileDialog With {.Title = "Export Skin To XML"}
        sfd.Filter = "Xml files (*.xml|*.xml"
        If sfd.ShowDialog = Windows.Forms.DialogResult.OK Then
            With SimpleSkin1
                .FormSkinPath = Me.FormSkinPath
                .Button1SkinPath = Me.Button1SkinPath
                .Button1MouseDownSkinPath = Me.Button1MouseDownSkinPath
                .Button1Location = Me.Button1Location
            End With
            SimpleSkin1.ToXMLFile(sfd.FileName)
        End If
    End Sub
    Private Sub btnLoadSkinFromXml_Click(sender As Object, e As EventArgs) Handles btnLoadSkinFromXml.Click
        Dim skin As CustomSkinningLibrary.SimpleSkin = Nothing
        Dim ofd As New OpenFileDialog With {.Title = "Import Skin From XML"}
        ofd.Filter = "Xml files (*.xml|*.xml"
        If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
            skin = SimpleSkin1.FromXMLFile(ofd.FileName)
        Else
            Exit Sub
        End If
        Dim form As CustomSkinningLibrary.SkinnableForm = CustomSkinningLibrary.SkinnableForm.Create(skin)
        form.Show()
    End Sub
End Class

Example Skin Library:

Namespace CustomSkinningLibrary
    <Serializable>
    Public Class SimpleSkin
        Public Property FormSkinPath As String = Nothing
        Public Property Button1SkinPath As String = Nothing
        Public Property Button1MouseDownSkinPath As String = Nothing
        Public Property Button1Location As Point = Nothing
        Public ReadOnly Property Complete As Boolean
            Get
                If FormSkinPath Is Nothing Then Return False
                If Button1SkinPath Is Nothing Then Return False
                If Button1MouseDownSkinPath Is Nothing Then Return False
                If Button1Location = Nothing Then Return False
                If Not System.IO.File.Exists(Me.FormSkinPath) Then Return False
                If Not System.IO.File.Exists(Me.Button1SkinPath) Then Return False
                If Not System.IO.File.Exists(Me.Button1MouseDownSkinPath) Then Return False
                Return True
            End Get
        End Property
        Public Sub ToXMLFile(Path As String)
            Dim serializer As New Xml.Serialization.XmlSerializer(GetType(SimpleSkin))
            Dim sb As New System.Text.StringBuilder
            Using s As New StringWriter(sb)
                serializer.Serialize(s, Me)
            End Using
            My.Computer.FileSystem.WriteAllText(Path, sb.ToString, False)
        End Sub
        Public Function FromXMLFile(Path As String) As SimpleSkin
            Dim serializer As New Xml.Serialization.XmlSerializer(GetType(SimpleSkin))
            Dim a As New StreamReader(Path)
            Dim obj As Object
            obj = serializer.Deserialize(a)
            Return DirectCast(obj, SimpleSkin)
        End Function
    End Class
    Public Class SkinnableForm
        Inherits Form
        Public WithEvents Button1 As SkinnableButton
        Private MySkin As Bitmap
        Protected Sub New()
        End Sub
        Protected Sub SetSkin(bmp As Bitmap)
            Dim g As Graphics = Me.CreateGraphics
            g.DrawImage(bmp, Me.ClientRectangle)
        End Sub
        Protected Overrides Sub OnPaint(pevent As PaintEventArgs)
            SetSkin(MySkin)
            Exit Sub
        End Sub
        Private Sub button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            MsgBox("hello world!")
        End Sub
        Public Shared Function Create(skin As SimpleSkin) As SkinnableForm
            If skin.Complete Then
                Dim createdForm As New SkinnableForm
                Dim formImage As Image = Image.FromFile(skin.FormSkinPath)
                createdForm.Button1 = SkinnableButton.Create(skin)
                createdForm.Button1.Parent = createdForm
                createdForm.MySkin = CType(formImage, Bitmap)
                createdForm.Size = formImage.Size
                createdForm.SetSkin(createdForm.MySkin)
                createdForm.FormBorderStyle = Windows.Forms.FormBorderStyle.None
                Return createdForm
            Else
                Dim errors As New List(Of String)
                If skin.FormSkinPath Is Nothing Then errors.Add("Property 'SimpleSkin.FormBitmapPath' Is Nothing")
                If skin.Button1SkinPath Is Nothing Then errors.Add("Property 'SimpleSkin.Button1BitmapPath' Is Nothing")
                If skin.Button1MouseDownSkinPath Is Nothing Then errors.Add("Property 'SimpleSkin.Button1MouseDownBitmapPath' Is Nothing")
                If skin.Button1Location = Nothing Then errors.Add("Property 'SimpleSkin.Button1Location' Is Nothing")
                If Not System.IO.File.Exists(skin.FormSkinPath) Then errors.Add("Property 'SimpleSkin.Button1Location' Specified File Does Not Exist")
                If Not System.IO.File.Exists(skin.Button1SkinPath) Then errors.Add("Property 'SimpleSkin.Button1Location' Specified File Does Not Exist")
                If Not System.IO.File.Exists(skin.Button1MouseDownSkinPath) Then errors.Add("Property 'SimpleSkin.Button1Location' Specified File Does Not Exist")
                Throw New SkinIncompleteException(errors)
            End If
        End Function
    End Class
    Public Class SkinIncompleteException
        Inherits Exception
        Public Property Errors As List(Of String)
        Sub New(errors As List(Of String))
            Me.Errors = errors
        End Sub
    End Class
    Public Class SkinnableButton
        Inherits Button
        Private MySkin As Bitmap
        Private MouseDownSkin As Bitmap
        Private MouseIsDown As Boolean = False
        Protected Sub New()
            Me.SetStyle(ControlStyles.UserPaint, True)
        End Sub
        Protected Overrides Sub OnPaintBackground(pevent As PaintEventArgs)
            MyBase.OnPaintBackground(pevent)
        End Sub
        Protected Sub SetSkin(bmp As Bitmap, g As Graphics)
            Dim r As New Rectangle(New Point(0, 0), New Size(Me.Width, Me.Height))
            g.DrawImage(bmp, r)
        End Sub
        Protected Overrides Sub OnPaint(pevent As PaintEventArgs)
            Dim mouserect As New Rectangle(Me.PointToClient(MousePosition), New Size(1, 1))
            If MouseIsDown Then
                SetSkin(MouseDownSkin, pevent.Graphics)
            Else
                SetSkin(MySkin, pevent.Graphics)
            End If
            Exit Sub
        End Sub
        Protected Overrides Sub OnMouseDown(mevent As MouseEventArgs)
            Me.MouseIsDown = True
            MyBase.OnMouseDown(mevent)
        End Sub
        Protected Overrides Sub OnMouseUp(mevent As MouseEventArgs)
            Me.MouseIsDown = False
            MyBase.OnMouseUp(mevent)
        End Sub
        Public Shared Function Create(skin As SimpleSkin) As SkinnableButton
            Dim skBtn As New SkinnableButton()
            skBtn.Location = skin.Button1Location
            skBtn.MySkin = CType(Image.FromFile(skin.Button1SkinPath), Bitmap)
            skBtn.Size = skBtn.MySkin.Size
            skBtn.MouseDownSkin = CType(Image.FromFile(skin.Button1MouseDownSkinPath), Bitmap)
            Return skBtn
        End Function
    End Class
End Namespace
Advertisements

Background Worker Illegal crossthread operation

A user of the MSDN forums asked the following question:(in this thread)

Hi, I want to thank everyone in advance for any help you can offer. I am an amateur programmer and I have been able to turn to this forum repeatedly for help with my problems — and this is deeply appreciated by me! Thank you!

I want to load a .csv file into a datagridview. The .csv file has 10 columns and at least 70,000 to 100,000 rows. When the program loads the file, the whole program freezes for several minutes. I eventually figured out that I could use a background worker to do things. However, when I tried to have the background worker add rows to the datagridview, I got an error message saying that it couldn’t because the datagridview was created on another thread than its own. …. I am wondering how I can solve this issue? Here is the program:

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        BackgroundWorker1.RunWorkerAsync()
    End Sub
    Private Sub bw() Handles BackgroundWorker1.DoWork
        get_main_catalog_of_items()
    End Sub
    Private Sub get_main_catalog_of_items()
        Datagridview1.Rows.Clear()
        Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("c:\catalogs\catalog_main.csv")
            MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
            MyReader.Delimiters = New String() {vbTab}
            Dim currentRow As Strng()
            While Not MyReader.EndOfData
                Try
                    currentRow = MyReader.ReadFields()
                    DataGridView1.Rows.Add(currentRow)
                Catch ex As Exception
                End Try
            End While
        End Using
    End Sub
End Class

Basically, what is happening is that when you access an object on one thread from another thread, this creates an unstable system environment. The way for getting around this is to check and see if an invoke is required for that object, and basically, if it is, you invoke a new delegate sub on the same thread of the datagridview, hence avoiding access across threads, because the delegate sub exists on the same thread as the datagridview. See example

Example

Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
    Dim bgw As New System.ComponentModel.BackgroundWorker
    Private Delegate Sub addDGVRow(dgv As DataGridView, row As DataGridViewRow)
    Sub doRowAdd(dgv As DataGridView, row As DataGridViewRow)
        If dgv.InvokeRequired Then
            dgv.Invoke(New addDGVRow(AddressOf doRowAdd), dgv, row)
        Else
            dgv.Rows.Add(row)
        End If
    End Sub
    Sub work(sender As Object, e As EventArgs)
        For i As Integer = 0 To 1000
            Dim row As New DataGridViewRow
            row.Cells.Add(New DataGridViewTextBoxCell With {.Value = i.ToString})
            row.Cells.Add(New DataGridViewTextBoxCell With {.Value = (i + 1).ToString})
            doRowAdd(DataGridView1, row)
        Next
    End Sub
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        DataGridView1.ColumnCount = 2
        AddHandler bgw.DoWork, AddressOf work
        bgw.RunWorkerAsync()
    End Sub
End Class

Here is the solution applied to your code:

Option Strict On
Option Explicit On
Option Infer Off
Imports System.ComponentModel
Public Class Form1
    Private Delegate Sub addDGVRow(dgv As DataGridView, row As String())
    Sub doRowAdd(dgv As DataGridView, row As String())
        If dgv.InvokeRequired Then
            dgv.Invoke(New addDGVRow(AddressOf doRowAdd), dgv, row)
        Else
            dgv.Rows.Add(row)
        End If
    End Sub
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        BackgroundWorker1.RunWorkerAsync()
    End Sub
    Private Sub bw() Handles BackgroundWorker1.DoWork
        get_main_catalog_of_items()
    End Sub
    Private Sub get_main_catalog_of_items()
        Datagridview1.Rows.Clear()
        Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("c:\catalogs\catalog_main.csv")
            MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
            MyReader.Delimiters = New String() {vbTab}
            Dim currentRow As String()
            While Not MyReader.EndOfData
                currentRow = MyReader.ReadFields()
                doRowAdd(DataGridView1, currentRow)
            End While
        End Using
    End Sub
End Class

Create function from Code

In the following StackOverFlow Question

I have been asked to edit this code…..

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If DateTime.Now.Hour >= 6 And DateTime.Now.Hour < 12 Then
        Message.Text = "Good Morning"
    End If

    If DateTime.Now.Hour >= 12 And DateTime.Now.Hour <= 17 Then
        Message.Text = "Good Afternoon"
    End If

    If DateTime.Now.Hour > 17 Or DateTime.Now.Hour < 6 Then
        Message.Text = "Good Evening"
    End If
End Sub

and change it into a function. the original code basically displays one of the messages on a webpage when opened depending what time of day it is. I was looking for some help on how or what i need to change to turn it into a function.

The code below i have edit but only slightly so anything that looks completely wrong will be because i have only edited a small part of it so the ByVal in the function i have to not tried to implement into the function as i am a bit stuck.

Private Function Greetings(goodMorning as string, goodAfternoon as String, goodEvening as String) as String

Dim outPut As String

If DateTime.Now.Hour >= 6 And DateTime.Now.Hour < 12 Then
            Message.Text = "Good Morning."
    ElseIf
        DateTime.Now.Hour >= 12 And DateTime.Now.Hour <= 17 Then
        Message.Text = "Good Afternoon."
    ElseIf 
        DateTime.Now.Hour >= 12 And DateTime.Now.Hour <= 17 Then
        Message.Text = "Good Afternoon."

    Return outPut
  End Function

When you write a Method, you need to take the following into consideration:

1.) Access Level
2.) Method Type(Function? or Sub?)
*A function will return a value, a sub will perform an operation without returning a value.

3.) Method Naming. Example, a function that returns someones age could be named “GetAge”
4.) Any parameters you may wish to pass.
5.) If you create a function, you need to declare the function “As” it’s expected return type
example:

A function that will return a string may be created like this:

Public Function GetString(param As String) As String
    Return "Hello" & param
End Function

The usage of that function may look like this:

Me.Text = GetString(" World!")

So inside your function that you are expected to create, instead of directly modifying an object’s text property, you will return the message using the “Return” keyword. When that function is used later, you will set the object’s text property with the direct output of your function.

You should create a function similar to this:

    Private Function GetGreeting() As String
        If DateTime.Now.Hour >= 6 And DateTime.Now.Hour < 12 Then
            Return "Good Morning"
        ElseIf DateTime.Now.Hour >= 12 And DateTime.Now.Hour <= 17 Then
            Return "Good Afternoon"
        Else
            Return "Good Evening"
        End If
    End Function

List Files in a folder

A user in the MSDN forums asked the following question in the following thread:

Hello, I am very new to programming and would like some help. I need a program that will search in a supplied folder and list all PDF type of file in a text box, and then have the operator select the file to open.

Can someone show me the code to do this?

Here is how I would.

    ''' <summary>
    ''' Returns the path to a pdf file that the user selected. Returns a blank if the user cancelled.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function OpenPDF() As String
        Dim OFD As New OpenFileDialog
        OFD.Filter = "Pdf Files|*.pdf"
        If OFD.ShowDialog = DialogResult.OK Then
            Return OFD.FileName
        End If
        Return ""
    End Function

Calculate Button Twice

In response to the following MSDN Forum Thread(Calculate Button Twice)

The original poster asked the following question:

Hello,

I’m having trouble with a simple code in vb. For some reason I’m having to push my calculate button twice to get the result I need with this simple calculator. Anyone see where I may have made a mistake?

Here is the code:

    Public Class Form1
        Dim Number1 As Decimal
        Dim Number2 As Decimal
        Dim Answer As Decimal
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            CheckBox1.Checked = True
            CheckBox2.Checked = False
            CheckBox3.Checked = False
            CheckBox4.Checked = False
        End Sub
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Number1 = Val(TextBox1.Text)
            Number2 = Val(TextBox2.Text)
            Label4.Text = Answer

            If TextBox1.Text = "" OrElse TextBox2.Text = "" Then MsgBox("No Number(s) is given", MsgBoxStyle.Critical, "Error")

            If CheckBox1.Checked = True Then Answer = Number1 + Number2
            If CheckBox2.Checked = True Then Answer = Number1 - Number2
            If CheckBox3.Checked = True Then Answer = Number1 * Number2
            If CheckBox4.Checked = True Then Answer = Number1 / Number2

            If CheckBox1.Checked = False And CheckBox2.Checked = False And CheckBox3.Checked = False And CheckBox4.Checked = False Then MsgBox("No Operators is Checked!", MsgBoxStyle.Critical, "Error")
            If CheckBox1.Checked = True And CheckBox2.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
            If CheckBox1.Checked = True And CheckBox3.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
            If CheckBox1.Checked = True And CheckBox4.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")

            If CheckBox2.Checked = True And CheckBox3.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
            If CheckBox2.Checked = True And CheckBox4.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")

            If CheckBox3.Checked = True And CheckBox4.Checked = True Then MsgBox("You can not have more than one item checked", MsgBoxStyle.Critical, "Error")
        End Sub
    End Class

When you are expecting to display a result after calculating it, it is important to write code that executes in that order.

Since you are only displaying your result after it is calculated, I also suggest using variables in a block scope verses using variables in a class scope.

I also suggest making the following changes to your code:

Option Strict On
Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        rbSubtraction.Checked = True
        rbAddition.Checked = False
        rbDivision.Checked = False
        rbMultiplication.Checked = False
    End Sub
    Private Sub btnCalculate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalculate.Click
        Dim Number1 As Decimal = 0D
        Dim Number2 As Decimal = 0D
        Dim Answer As Decimal = 0D
        Decimal.TryParse(tbNumber1.Text, Number1)
        Decimal.TryParse(tbNumber2.Text, Number2)
        Dim msg As String() = {"You must provide a Number {0}"}
        Select Case True
            Case tbNumber1.Text = String.Empty : lblResult.Text = String.Format(msg(0), "1") : Exit Sub
            Case tbNumber2.Text = String.Empty : lblResult.Text = String.Format(msg(0), "2") : Exit Sub
            Case rbSubtraction.Checked : Answer = Number1 - Number2
            Case rbAddition.Checked : Answer = Number1 + Number2
            Case rbMultiplication.Checked : Answer = Number1 * Number2
            Case rbDivision.Checked : Answer = Number1 / Number2
        End Select
        lblResult.Text = Answer.ToString
    End Sub
    Private Sub tbNumber1_KeyDown(sender As Object, e As KeyEventArgs) Handles tbNumber2.KeyDown, tbNumber1.KeyDown
        Dim count As Integer = (From c As Char In DirectCast(sender, TextBox).Text Where c = "."c Select c).Count
        Select Case True
            Case {8, 46, 37, 38, 39, 40}.ToList.IndexOf(e.KeyCode) > -1 : Exit Sub
            Case e.KeyCode = Keys.Decimal OrElse e.KeyCode = Keys.OemPeriod
                If tbNumber1.SelectionStart = 0 Then Exit Select
                If count > 0 Then Exit Select Else Exit Sub
            Case Char.IsDigit(ChrW(e.KeyCode)) : Exit Sub
        End Select
        e.SuppressKeyPress = True
        e.Handled = True
    End Sub
End Class

 

 

Don’t use a for next loop if you are not utilizing the iteration object.

A brief summary of what this means is that if you are using a for-next loop, you would only want to use the object that is iterated. You could call a for-next loop an object iteration loop. Where-as a Do-While loop is a condition-iteration loop.

Object Iteration Loop:
In the following loop, a collection(list of string) is iterated.

        Dim items As New List(Of String) From {"a", "b", "c"}
        For Each item As String In items
            MsgBox(item) '<-- utilizing the iteration object
        Next

Condition Iteration Loop:
In the following loop, a collection is not iterated through, instead a value is modified, and the loop ends when a certain condition becomes true.

        Dim i As Integer = 0
        Do
            i += 1
        Loop Until i = 100 '<-- evaluating a condition

How to get state abbreviations quickly with a small amount of code

On the MSDN forums, I suspect the person in this post is attempting to get a state abbreviation.

If I were trying to get a state abbreviation, I would do it like this:

Option Strict On
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        MsgBox(GetStateAbbrevation(TextBox1.Text))
    End Sub
    Public Function GetStateAbbrevation(ByVal stateName As String) As Object
        Dim States As New List(Of String) From {"ALabama", "AlasKa", "AriZona", "ARkansas", "CAlifornia", "COlorado", _
                                                "ConnecTicut", "DElaware", "FLorida", "GeorgiA", "HawaiI", _
                                                "IDaho", "ILlinois", "INdiana", "IowA", "KansaS", "KentuckY", _
                                                "LousianaA", "MainE", "MarylandD", "MAssachusetts", "MIchigan", _
                                                "MiNnesota", "MiSsissippi", "MissOuri", "MonTana", "NEbraska", _
                                                "NeVada", "NewHampshire", "NewJersey", "NewMexico", "NewYork", _
                                                "NorthCarolina", "NorthDakota", "OHio", "OKlahoma", "ORegon", _
                                                "PennsylvAnia", "RhodeIsland", "SouthCarolina", "SouthDakota", _
                                                "TenNessee", "TeXas", "UTah", "VermonT", "VirginiA", "WAshington", _
                                                "WestVirginia", "WIconsin", "WYoming"}
        stateName = stateName.Replace(" ", "").ToLower
        Dim result As String = String.Empty
        For Each state As String In States
            If state.ToLower = stateName.ToLower Then
                For Each c As Char In state
                    If Char.IsUpper(c) Then result = result & c
                Next
            End If
        Next
        Return result
    End Function
End Class