Wednesday, December 19, 2007

Browsing a .SDF file (SQL Server CE database file)

If you are using SQL Server Compact Editition (SQL Server CE) and are producing .sdf files for use with your applicatoins, it is sometimes desireable to browse through a .sdf file's schema and data. Microsoft provides a nice tool for doing this, the SQL Server Management Studio Express. You must get Service Pack 2 or higher to have the SQL Server CE support.

It will let you select "SQL Server Compact Edition" for your Server Type and you can specify a .sdf file:










You can then browse the database's schema:






And you can perform queries on the data:







You can download the tool from Microsoft:

http://www.microsoft.com/downloads/details.aspx?FamilyID=6053c6f8-82c8-479c-b25b-9aca13141c9e&DisplayLang=en

Friday, December 14, 2007

Initialize char Array in C#

If you are used to initializing a char array in C++ like the following:


char mask[]={'a', 'b', 'c'};



There is a slight change when doing this in C#:

char[] mask=new char[] {'a', 'b', 'c'};


More examples:

http://www.java2s.com/Code/CSharp/Collections-Data-Structure/illustrateshowtoinitializearrays.htm

Wednesday, December 12, 2007

Testing to See if a Camera is Available on Windows Mobile Device

If you are trying to support a built in camera in your Windows Mobile Application, it is often useful to be able to test to see if the camera is availalble in the device. It is simple to do, but maybe not very obvious how to get to this property. Also, if you try to use the CameraCaptureDialog when there is no camera present, it can have unexpected results.

Dim cameraPresent As Boolean = _
CBool(Microsoft.WindowsMobile.Status.SystemProperty.CameraPresent)

Sunday, December 2, 2007

Iterating through a Dictionary Object's Items in VB.NET and C#

Iterating through a Dictionary Object's items may be more complicated than you think; however, with a few examples to go by it turns out to be pretty easy:

VB.NET

Dim DictObj As New Dictionary(Of Integer, String)

DictObj.Add(1, "ABC")
DictObj.Add(2, "DEF")
DictObj.Add(3, "GHI")
DictObj.Add(4, "JKL")

For Each kvp As KeyValuePair(Of Integer, String) In DictObj
Dim v1 As Integer = kvp.Key
Dim v2 As String = kvp.Value
Debug.WriteLine("Key: " + v1.ToString _
+ " Value: " + v2)
Next

C#

Dictionary<int, String> DictObj =
new Dictionary<int, String>();

DictObj.Add(1, "ABC");
DictObj.Add(2, "DEF");
DictObj.Add(3, "GHI");
DictObj.Add(4, "JKL");

foreach (KeyValuePair<int,String> kvp in DictObj)
{
int v1 = kvp.Key;
String v2 = kvp.Value;
Debug.WriteLine("Key: " + v1.ToString() +
" Value: " + v2);
}


It should also be pointed out that you can obtain a collection from the Dictionary Object for both Keys and Values using KeyCollection and ValueCollection:

VB.NET

Dim keyCollection As _
Dictionary(Of Integer, String).KeyCollection = _
DictObj.Keys

For Each key As Integer In keyCollection
Debug.WriteLine("Key: " + key.ToString())
Next

Dim valueCollection As _
Dictionary(Of Integer, String).ValueCollection = _
DictObj.Values

For Each value As String In valueCollection
Debug.WriteLine("Value: " + value.ToString())
Next


C#

Dictionary<int,String>.KeyCollection keyCollection=
DictObj.Keys;

foreach (int key in keyCollection)
{
Debug.WriteLine("Key: " + key.ToString());
}

Dictionary<int,String>.ValueCollection valueCollection = DictObj.Values;

foreach (String value in valueCollection)
{
Debug.WriteLine("Value: " + value.ToString());
}


For more examples see:

http://msdn2.microsoft.com/en-us/library/xfhwa508.aspx

Saturday, December 1, 2007

Debug.WriteLine in C#

If you are used to using Debug.WriteLine in VB.NET, it is sometimes a little confusing when you try to do it in C# and it doesn't work. The trick is to say:


using System.Diagnostics;


at the beginning of the C# app, then the Debug.WriteLine will work as you expect.


You can get more detailed information on this subject from:

http://support.microsoft.com/kb/815788

Wednesday, October 24, 2007

Getting a Form to Scroll Down on Smartphone

One problem that I have had with the Compact Framework and Form for Smartphone app (Smartphone 5.0 or Windows Mobile 6 Standard) is that you will get an automatic scroll bar on your form if the form contents go off the screen, but you can't scroll up or down. This problaby is particually a problem if you design a form for one screen size (240x320), but then you run your app on a device like the Motorola Q that has (320x240). The Autoscroll property gets the scroll bar up on the screen, but if there are no tab stop controls, it will not move the form up or down.

The only workaround I have found to solve this problem is to adjust the AutoScrollPosition attribute manually if keys are pressed on the device.


Private Sub Form_GpsInfo_KeyDown(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown

If (e.KeyCode = System.Windows.Forms.Keys.Up) Then
'Up
Me.AutoScrollPosition = New Point(-Me.AutoScrollPosition.X, _

-Me.AutoScrollPosition.Y - 16)
End If


If (e.KeyCode = System.Windows.Forms.Keys.Down) Then
'Down
Me.AutoScrollPosition = New Point(-Me.AutoScrollPosition.X,

-Me.AutoScrollPosition.Y + 16)
End If


End Sub

The amount you scroll up or down can be varied.

I found a similar article on this problems at:

http://blogs.msdn.com/anthonywong/archive/2005/05/12/416907.aspx

Sunday, October 21, 2007

Determine Current Screen Orientation for Windows Mobile

To find the Screen Orientation on a Windows Mobile device, you can easily check the screen orientation property. Sample VB.NET code is shown below (C# code would be similar):

Imports Microsoft.WindowsCE.Forms
.
.
.
Dim orientation As ScreenOrientation = _
SystemSettings.ScreenOrientation


Orientation will be:
  • ScreenOrientation.Angle0
  • ScreenOrientation.Angle90
  • ScreenOrientation.Angle180
  • ScreenOrientation.Angle270

If the Orientation changes while a form is being displayed, the Resize will be fired.

More Info can be found at: http://msdn2.microsoft.com/en-us/library/ms229671.aspx

Friday, October 12, 2007

Getting a List of Storage Card Directories for Smartphone and Windows Mobile

There are lots of example of getting a list of Storage Card directories for Windows Mobile and Smartphone out there. He is one that I have cobbled together from the other example in VB.NET.

Other references that include C# examples are:

http://msdn2.microsoft.com/en-us/library/aa446567.aspx

http://www.opennetcf.org/forums/topic.asp?TOPIC_ID=432

Imports System.IO

Public Function GetStorageCardNames() As String()

Try

Dim attrStorageCard As FileAttributes = FileAttributes.Directory Or FileAttributes.Temporary
Dim scards As New ArrayList()
Dim rootDir As New DirectoryInfo("\")

For Each di As DirectoryInfo In rootDir.GetDirectories()

If (di.Attributes And attrStorageCard) = attrStorageCard Then
scards.Add(di.Name)
End If

Next

Return CType(scards.ToArray(GetType(String)), String())

Catch ex As Exception

Return Nothing

End Try

End Function

Tuesday, October 9, 2007

Sorting Listviews by Column with the .NET Compact Framework

Sorting a listview by column is not overly complicated on the desktop, but with the Compact Framework is not so straightforward. Here is a good artcle from Microsoft that describes how to accomplish the task:

http://msdn2.microsoft.com/en-us/library/ms229643.aspx

Thursday, October 4, 2007

Connecting a Smartphone to a GPS (Window Mobile Smartphone 5.0 and Windows Mobile Standard 6)

It seems to be a little more difficult than it should be to set up a GPS on a Windows Mobile Standard 6 Smartphone. Here is a list of steps that might help:

For Smartphone (Windows Mobile Standard 6):
  • Make sure Bluetooth is set to "On".
  • You may have to press the pairing button on the GPS (if it has one).
  • Start/Settings/Connections/Bluetooth.
  • Pick Bluetooth again.
    Add new Device... (it will then search for Bluetooth devices)
  • Select your GPS device from the list and press Next.
  • The GPS you are trying to use should show up in the list.
  • Select it. Press Next.
  • Enter the passkey for the Bluetooth GPS. For example, 0000 or 0183
  • Next
  • You should get a message box saying "Your Smartphone has connected with XXXX".
  • OK
  • Enter a display name for the device. Enter a name and press Next.
  • Check the "Serial port" checkbox.
  • Done
  • Done
You now have to add a Com Port.
  • Start/Settings/Connections/Bluetooth.
    Pick Bluetooth again.
  • Menu/COM Ports
  • It will say "To add a COM port, select from one of the options under Menu."
  • Press Menu.
  • Select New Outgoing Port.
  • Select the GPS you just added from the list.
  • Pick the Com port you want to use (mine usually givex COM6 and COM7)
  • You should then uncheck Secure Connection (unless you know you GPS will work with it on).
  • Done.
You should now be able to connect to the GPS in an Application that uses a GPS by specifying the Com port you defined.


For Smartphone (Windows Mobile Smartphone 5.0):
from http://blogs.msdn.com/windowsmobile/archive/2006/06/07/620387.aspx
Start/Settings/Connections/Bluetooth.
  • Make sure Bluetooth is set to "On".
  • Menu/Devices
  • Menu/New
  • Select your GPS device from the list and press Next.
  • Enter the passkey for the Bluetooth GPS. For example, 0000 or 0183.
  • Next
  • You should get a message box saying "Your Smartphone has connected".
  • OK
  • Next
  • Check the "Serial port" checkbox.
  • Done
  • Done
  • Menu/COM Ports
  • Select your GPS.
  • Menu/New Outgoing Port.
  • Select your device and press Select.
  • You will see a COM port that has been chosen for your GPS. For example, COM6.
  • Done
  • Done
  • Done
  • Now your GPS is set up on COM6.
  • Start your GPS app and configure it to use COM6.
  • Saturday, September 29, 2007

    Pocket Outlook on Windows Mobile

    The best reference (that I have found) for developing with Pocket Outlook on Windows Mobile can be found here:

    http://msdn2.microsoft.com/en-us/library/aa454890.aspx

    These examples are in C#, but the conversion to VB.NET is pretty easy. Here is an example of some of the code in VB.NET:


    Dim contactPicker As New ChooseContactDialog
    Dim result As DialogResult = contactPicker.ShowDialog

    If result = Windows.Forms.DialogResult.OK Then

    Dim message As EmailMessage = New EmailMessage()
    message.Subject = "GTViewer Photo"
    message.BodyText = "........"


    Dim addressee As Recipient = New Recipient(contactPicker.SelectedContact.Email1Address)
    message.To.Add(addressee)


    Dim picture As Attachment = New Attachment(filename)
    message.Attachments.Add(picture)


    Dim _outlook As OutlookSession = New OutlookSession()
    MessagingApplication.DisplayComposeForm(message)

    _outlook.Dispose()

    End If

    Sleep in VB.NET and C#

    The sleep is sometimes hard to find in .NET. Here is an example for VB.NET and C#:

    VB.NET

    Imports System.Threading
    .
    .
    .

    Dim waitTime as Integer = 300

    Thread.Sleep(waitTime)


    C#

    using System.Threading;
    .
    .
    .
    int waitTime = 300;

    Thread.Sleep(waitTime);


    The Sleep method can be used with both an integer and a TimeSpan parameter. An integer value can be used to specify the wait time in milliseconds, or the wait time can be specified as a TimeSpan like this:

    In VB.NET:

    Dim waitTime As New TimeSpan(0, 0, 0, 0, 300)

    or in C#:

    TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 300);


    There is also a pretty good example at the following web site:

    http://msdn.microsoft.com/en-us/library/system.threading.thread.sleep(VS.71).aspx

    Tuesday, September 4, 2007

    Conditional Compilation in VB.NET

    Like C and C++, you can perform Conditional Compilation in VB.NET:

    #If COMMAND_LINE = True Then
    Dim AxGTCreate1 As GTCREATELib.GTCreate = Nothing
    #Else
    Dim AxGTCreate1 As AxGTCREATELib.AxGTCreate = Nothing
    #End If


    The #if, #else, and #end if can be used.

    In the example above, the variable COMMAND_LINE is used to determine which type to use. The COMMAND_LINE value is set either by using:

    #Const COMMAND_LINE = True

    in the code, or by setting it as a Custom Constant on the Compile table of the Project's property page. Press the Advanced Compile Options button to get to the form to set the Custom Constants.

    Getting Command-Line arguments in a VB.NET Console Application

    It is pretty simple to get a string of the command-line arguments in VB.NET:

    Dim cl As String = Command()

    It is still up to you to parse the string into something usable. Here is a link that show one approach:


    http://www.averagecoder.com/article_detail.asp?query=passing_arguments_to_your_vb_net_console_application

    Friday, August 31, 2007

    Database Connection Strings

    Getting the right connection string syntax can chew up hours of experimentation. Here is a site that can save that time for you: http://www.carlprothman.net/Default.aspx?tabid=81

    Sunday, August 19, 2007

    Finding the Size of a file while Writing when using StreamWriter

    In VB 6, you could always use LOF() to find the length of the file you were writing; however, in VB.NET or C# is not as obvious.


    Dim s As StreamWriter = New StreamWriter(filename)
    .
    .
    .
    s.BaseStream.Flush()
    Dim offsetPosition as Long = s.BaseStream.Length



    One thing to note, you will have to do the Flush before using the length property or you will not get accurate results. You can also set the AutoFlush property on the StreamWriter object.


    For more info, see:

    http://www.thescripts.com/forum/thread266352.html

    Monday, August 13, 2007

    Using a ListView in VB.NET

    Here is a basic example of how to use the Detail View with a ListView in VB.NET.
    See also AutoFitListView and CopyListViewToClipboard.

    Private Sub Form1_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load

    ' Set ListView Properties
    ListView1.View = View.Details
    ListView1.GridLines = True
    ListView1.FullRowSelect = True
    ListView1.HideSelection = False
    ListView1.MultiSelect = False

    ' Create Columns Headers
    ListView1.Columns.Add("Column A")
    ListView1.Columns.Add("Column B")
    ListView1.Columns.Add("Column C")

    Dim tempValue As Integer = 0

    For i As Integer = 0 To 9

    ' Create List View Item (Row)
    Dim lvi As New ListViewItem

    ' First Column can be the listview item's Text
    lvi.Text = "Row " + i.ToString

    ' Second Column is the first sub item
    tempValue = tempValue + 1
    lvi.SubItems.Add(tempValue.ToString)

    ' Third Column is the second sub item
    tempValue = tempValue + 1
    lvi.SubItems.Add(tempValue.ToString)

    ' Add the ListViewItem to the ListView
    ListView1.Items.Add(lvi)

    Next

    End Sub

    Private Sub ListView1_SelectedIndexChanged(ByVal sender As _
    System.Object, ByVal e As System.EventArgs) _
    Handles ListView1.SelectedIndexChanged

    If ListView1.SelectedIndices.Count = 0 Then Return

    Dim lvi As ListViewItem = _
    ListView1.SelectedItems(0)

    MessageBox.Show(lvi.Text + " has been selected.")

    End Sub

    Monday, August 6, 2007

    Critical Section in C#

    Here is a good article on using the lock statement to create critical sections in C#:

    http://www.calcaria.net/c-sharp/2006/10/c-equivalent-csinglelock-critical.html

    Here is the gist:

    Object lockobj = new Object();

    lock (lockobj)
    {
    // Do your locked work
    }

    Friday, July 27, 2007

    Formatting Number, Currency, Dates, and Time in VB.NET

    Here is a great link with lots of formatting examples:

    http://msconline.maconstate.edu/tutorials/VBNET/VBNET01/vbnet01-08.aspx

    Friday, July 20, 2007

    Path and Filename Decomposition function in VB.NET and C#

    I had already written Path and Filename Decomposition functions in VB.NET and C# before I found the simple way to do it with the Path class:

    filename = Path.GetFileName(Path)
    extension = Path.GetExtension(Path)
    fullPath = Path.GetFullPath(Path)
    directoryName = Path.GetDirectoryName(Path)
    FilenameWithoutExt = Path.GetFileNameWithoutExtension(Path)



    However, I have need to use these function for similar things that the Path class cannot handle, so I am including them in this posting.

    Here are 4 functions in VB.NET and C# that do path and filename decomposition:


    1) GetFileNameFromPath will return a filename and its extension from a full directory path.

    GetFileNameFromPath("c:\temp\test.txt") returns "test.txt"

    GetFileNameFromPath("test.txt") returns "test.txt"

    2) GetFileNameWithoutExtFromPath will return a filename without its extension from a full directory path.

    GetFileNameWithoutExtFromPath("c:\temp\test.txt") returns "test"

    GetFileNameWithoutExtFromPath("test.txt") returns "test"

    3) GetDirFromPath will get the directory from a full path.

    GetDirFromPath("c:\temp\test.txt") returns "C:\temp"

    GetDirFromPath("test.txt") returns ""

    4) GetExtensionFromPath will return only the file extension from either a filename or a full path.

    GetExtensionFromPath("c:\temp\test.txt") returns ".txt"

    GetExtensionFromPath("test.txt") returns ".txt"



    VB.NET Code:


    Public Function GetDirFromPath(ByVal path As String) _
    As String

    Try
    Return path.Substring(0, path.LastIndexOf("\") + 1)

    Catch ex As Exception
    ' error
    Return ""
    End Try

    End Function
    '
    Public Function GetFileNameFromPath(ByVal path _
    As String) As String

    Try
    Return path.Substring(path.LastIndexOf("\") + 1)
    Catch ex As Exception
    ' error
    Return ""
    End Try

    End Function
    '
    Public Function GetFileNameWithoutExtFromPath(ByVal path _
    As String) As String

    Try
    Dim filename As String = _
    path.Substring(path.LastIndexOf("\") + 1)
    Dim pos As Integer = filename.LastIndexOf(".")

    If pos <> -1 Then
    Return filename.Substring(0, pos)
    Else
    Return filename
    End If

    Catch ex As Exception
    ' error
    Return ""
    End Try

    End Function
    '
    Public Function GetExtensionFromPath(ByVal path _
    As String) As String

    Try
    Dim pos As Integer = _
    path.LastIndexOf(".")
    If pos <> -1 Then
    Return path.Substring(pos)
    Else
    Return ""
    End If

    Catch ex As Exception
    ' error
    Return ""
    End Try
    End Function



    C# Code:


    public String GetDirFromPath(String path)
    {
    try
    {
    return path.Substring(0, path.LastIndexOf("\\") + 1);
    }
    catch (Exception ex)
    {
    // error
    return "";
    }
    }


    public String GetFileNameFromPath(String path)
    {
    try
    {
    return path.Substring(
    path.LastIndexOf("\\") + 1);
    }
    catch (Exception ex)
    {
    // error
    return "";
    }

    }

    public String GetFileNameWithoutExtFromPath(String path)
    {
    try
    {
    String filename = path.Substring(
    path.LastIndexOf("\\") + 1);
    int pos = filename.LastIndexOf(".");

    if (pos != -1)
    return filename.Substring(0, pos);
    else
    return filename;
    }

    catch (Exception ex)
    {
    // error
    return "";
    }

    }

    public String GetExtensionFromPath(String path)
    {
    try
    {
    int pos = path.LastIndexOf(".");
    if (pos != -1)
    return path.Substring(pos);
    else
    return "";
    }

    catch (Exception ex)
    {
    // error
    return "";
    }

    }

    Thursday, July 19, 2007

    Sharing a file between Multiple Projects in VB.NET or C#

    It was difficult for me to figure this problem out without some help. If you want a .vb or .cs file (or any other file) shared between multiple projects in Visual Studio, the normal thing to do is to right click on the project in the Solution Explorer, select Add, then select Existing Item, and pick the file from project 1 that you want to share with project 2. This unfortunately makes a copy of the file and you now have two different versions of the file to maintain. However, the Add button on the Exiting Item's dialog has a innocuous drop down arrow. If you drop down the menu, you can choose Add as Link, which does not copy the file.




    Here is a rambling discussion on this topic, but the is solution they come to is described above:




    Generating a GUID in Windows Mobile using VB.NET or C#

    It is puzzling to me why Windows Mobile can't natively generate its own GUIDs, but Microsoft does provide VB.NET and C# source code for creating a GUID:

    http://msdn2.microsoft.com/en-us/library/aa446557.aspx

    Finding the My Documents Directory in Windows Mobile (or the Desktop)

    You can find the \My Documents directory on a Windows Mobile device by saying:

    path = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal)


    GetFolderPath also works on the desktop.


    For More Info:

    http://msdn2.microsoft.com/en-us/library/system.environment.getfolderpath.aspx

    http://blogs.msdn.com/windowsmobile/archive/2006/07/26/678742.aspx

    Camera API for Windows Mobile

    While is it sometimes a little difficult to find information on the Windows Mobile Camera API, there are several references. The CameraCaptureDialog is probably the key thing to look for, and also the CameraPresent attribute:

    http://blogs.msdn.com/vsdteam/archive/2005/06/29/433961.aspx

    http://msdn2.microsoft.com/en-us/library/microsoft.windowsmobile.forms.cameracapturedialog_members.aspx

    http://www.google.com/search?q=camerapresent&sourceid=ie7&rls=com.microsoft:en-US&ie=utf8&oe=utf8

    http://channel9.msdn.com/ShowPost.aspx?PostID=209787

    Wednesday, July 18, 2007

    File Handles are automatically closed for Files on a Storage Card when a Windows Mobile Device goes to Sleep

    A difficult problem to track down in Windows Mobile development is the annoying problem caused when a Windows Mobile or Pocket PC devices goes to Sleep (when it inactive for a specfied amount of time). If you have a file on the storage card open and the devices goes to sleep, then when the device wakes back up, the file handle to your open file is invalid, but your application does not know this.

    Here is some more information as to why:

    http://blogs.msdn.com/windowsmobile/archive/2007/01/12/everything-you-want-to-know-about-sd.aspx

    SetLength in VC++ will Throw Exception in Windows Mobile 6 emulator when file is in Shared Directory

    While this posting is not really a .NET related issue, I am posting it anyway because the information is difficult to find on the web.

    If you have a Windows Mobile 6 Emulator running (and appearently this error is also true for a few versions back), and you are sharing a directory between the desktop file system and the emulator (Shared Folder under the Emulator's Configure dialog will make a desktop directory show up as a \Storage Card directory on the emulator), then if you try to use CFile::SetLength on a file in the shared directory, the application will throw an exception for no apparent reason. I am also found other saying that FlushFileBuffers also has the same problem.

    Here is the only other reference I have found to this problem:

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=796830&SiteID=1

    Friday, July 13, 2007

    Optional Parameters and parameters with default values in VB.NET

    It is possible to use an optional parameter in VB.NET that uses a default value as shown below:

    Public Function SplitAttrValue(ByVal str As String, ByRef attr As String, ByRef value As String, Optional ByVal delimiter As String = "=") As Boolean

    However, here is an article that describes why you should not do this:

    http://www.knowdotnet.com/articles/optionalparams.html

    Main reason is that C# doesn't support them (you must use overloading).

    Using Reflection in VB.NET

    Here is a link that has lots of good examples of using Reflection in VB.NET to get a list of members in a class, calling members in a class, etc.

    http://www.java2s.com/Code/VB/Development/UseReflectiontocreateClassinstanceandcallmethod.htm

    Tuesday, July 10, 2007

    Passing a Function by Reference in VB.NET

    If you are creating Test code, it is often very useful to be able to pass a function by reference. In my example below, my test modules all have one parameter which is a pointer to a TestResult object. I pass my Test modules to the RunTest function which creates a TestResult object, populates certain fields, and passes the object to the test module (which was passed in as a reference). This allows all of the work done for each call to a test module to be consolidated into one nice and neat function.

    The key to making this work is to define a delegate with the right parameter signature, then use the delegate's name (TestDelegate in my example) when defining the type for the function you are passing.

    Example:

    Public Class TestResult

    Public name As String = ""
    Public pass As Boolean = False
    Public startTime As DateTime
    Public endTime As DateTime
    Public comments As String = ""

    End Class

    Public Delegate Sub TestDelegate(ByVal result As TestResult)



    Private Sub RunTest(ByVal testFunction As TestDelegate)

    Dim result As New TestResult
    result.startTime = DateTime.Now
    testFunction(result)
    result.endTime = DateTime.Now

    End Sub

    Private Sub MenuItemStartTests_Click(ByVal sender As System.Object,
    ByVal e As System.EventArgs) Handles MenuItemStartTests.Click

    Debug.WriteLine("Starting Tests...")
    Debug.WriteLine("")
    '==================================

    ' Add Calls to Test Modules Here

    RunTest(AddressOf Test1)
    RunTest(AddressOf Test2)

    '==================================


    Debug.WriteLine("")
    Debug.WriteLine("Tests Completed")

    End Sub


    Private Sub Test1(ByVal result As TestResult)

    result.name = "Test #1"
    .
    .
    .
    result.pass = True

    End Sub

    Private Sub Test2(ByVal result As TestResult)

    result.name = "Test #2"
    .
    .
    .
    result.pass = True

    End Sub

    Thursday, July 5, 2007

    Gridlines in a Listview with .NET Compact Framework

    The .NET Compact Framework does not support the Gridline property on a listbox, but there is a way to get Gridlines to appears in a SmartDevice appliation.

    Look at the Grid in Listview (C# and VB.NET) item on this page:

    http://www.businessanyplace.net/?p=code#listviewgrid

    Wednesday, June 27, 2007

    Adding Assemblies to the list in the "Add Reference" dialog

    This page tells how to get your assemblies or .net control to appear in the Dialog that display when you click on Add Reference:



    Summary - Add a key under HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\AssemblyFolders where the default value is the path to the directory that contains your assemblies.


    For deployment, I use [TARGETDIR] as the value for the registry entry:


    Tuesday, June 26, 2007

    Moving Listview Items Up or Down

    Here is a good example in VB.NET and C# for moving an item (row) in a listview up or down one position. This function simplifies implementing the Move Up and Move Down button on a form:

    http://www.knowdotnet.com/articles/listviewmoveitem.html

    This example suffers from one problem that I found. The .tag objects are not moved with the text. I had to add an object variable and then add the following code:

    Move Up Section:

    tagCache = .Items(selIdx - 1).Tag
    .Items(selIdx - 1).Tag = .Items(selIdx).Tag
    .Items(selIdx).Tag = tagCache


    Move Down Section:

    tagCache = .Items(selIdx + 1).Tag
    .Items(selIdx + 1).Tag = .Items(selIdx).Tag
    .Items(selIdx).Tag = tagCache

    Sunday, June 17, 2007

    Copy ListBox to Clipboard in VB.NET, C#, and VB6

    Here is a function I have written in VB.NET, C#, and VB6 to copy the contents of a ListBox to the Windows Clipboard. If you are interested in copying a ListView to the clipboard, see this posting.


    VB.NET:


    Imports System.text

    ...

    Public Sub CopyListBoxToClipboard(ByVal lb As ListBox)

    Dim buffer As New StringBuilder

    For i As Integer = 0 To lb.Items.Count - 1
    buffer.Append(lb.Items(i).ToString)
    buffer.Append(vbCrLf)
    Next

    My.Computer.Clipboard.SetText(buffer.ToString)

    End Sub


    C#:

    using System.Text;

    ...

    public void CopyListBoxToClipboard(ListBox lb)
    {
    StringBuilder buffer = new StringBuilder();

    for (int i = 0; i < lb.Items.Count; i++)
    {
    buffer.Append(lb.Items[i].ToString());
    buffer.Append("\n");
    }

    Clipboard.SetText(buffer.ToString());
    }



    VB6:

    Public Sub CopyListBoxToClipboard(lb As ListBox)

    Dim buf As String

    Dim i As Long

    For i = 0 To lb.ListCount - 1

    buf = buf + lb.List(i)

    buf = buf + vbCrLf

    Next

    Clipboard.Clear
    Clipboard.SetText buf

    End Sub

    Copy ListView to Clipboard in VB.NET, C#, and VB6

    It is often useful to be able to copy the contents of a ListView to the Windows Clipboard. I have written a function for VB.NET, C#, and VB6 called CopyListViewToClipboard that will copy the contents of a ListView (in Details mode) to the Windows Clipboard. Additional functions are also available for a ListBox control here. The column headers will be the first row and the items in the listview will be the remaining rows. To make the copied data more compatible with applications like Excel, a tab character is placed between items in a row and a carriage return/linefeed is placed at the end of the row.

    Here is an example ListView with some data in it:



    Here is what is copied to the clipboard and then to Excel:




    VB.NET:

    Imports System.text

    ...


    Public Sub CopyListViewToClipboard(ByVal lv As ListView)

    Dim buffer As New StringBuilder

    For i As Integer = 0 To lv.Columns.Count - 1
    buffer.Append(lv.Columns(i).Text)
    buffer.Append(vbTab)
    Next

    buffer.Append(vbCrLf)

    For i As Integer = 0 To lv.Items.Count - 1
    For j As Integer = 0 To lv.Columns.Count - 1
    buffer.Append(lv.Items(i).SubItems(j).Text)
    buffer.Append(vbTab)
    Next
    buffer.Append(vbCrLf)
    Next

    My.Computer.Clipboard.SetText(buffer.ToString)

    End Sub


    C#

    using System.Text;

    ...


    public void CopyListViewToClipboard(ListView lv)
    {
    StringBuilder buffer = new StringBuilder();

    for (int i = 0; i < lv.Columns.Count; i++)
    {
    buffer.Append(lv.Columns[i].Text);
    buffer.Append("\t");
    }

    buffer.Append("\n");

    for (int i = 0; i < lv.Items.Count; i++)
    {
    for (int j = 0; j < lv.Columns.Count; j++)
    {
    buffer.Append(lv.Items[i].SubItems[j].Text);
    buffer.Append("\t");
    }

    buffer.Append("\n");
    }

    Clipboard.SetText(buffer.ToString());
    }


    VB6


    Public Sub CopyListViewToClipboard(lv As ListView)

    Dim buf As String
    Dim i As Integer
    Dim j As Integer

    For i = 1 To lv.ColumnHeaders.count

    buf = buf + lv.ColumnHeaders.Item(i).Text + vbTab

    Next


    buf = buf + vbCrLf

    For i = 1 To lv.ListItems.count

    buf = buf + lv.ListItems(i).Text

    For j = 1 To lv.ColumnHeaders.count - 1
    buf = buf + vbTab + lv.ListItems(i).SubItems(j)
    Next

    buf = buf + vbCrLf

    Next

    buf = buf + vbCrLf

    Clipboard.Clear
    Clipboard.SetText buf

    End Sub

    Getting Application's Path (Desktop and Windows Mobile)

    Getting the Application's Path is different depending on the platform and application type. Ideally, you would just use the Application.StartupPath, but that only works for Forms apps on the desktop. I have provided this approach and another for Desktop Console App and another one for Windows Mobile.

    VB.NET - Forms App
    Public Function GetAppPath() As String

    return System.Windows.Forms.Application.StartupPath

    End Function


    VB.NET - Console App
    Imports System.Reflection
    ...

    Public Function GetAppPath() As String

    Return Path.GetDirectoryName([Assembly].GetEntryAssembly().Location)

    End Function

    VB.NET - on Smart Device (Windows Mobile) Platform
    Imports System.Reflection
    ...

    Public Function GetAppPath() As String

    Dim asm As [Assembly] = [Assembly].GetExecutingAssembly()

    return System.IO.Path.GetDirectoryName(asm.GetName().CodeBase)

    End Function

    How to Fit all columns in a ListView in C#, VB.NET, and VB6

    Code is shown below to Autofit the data in a listview for C#, VB.NET, and VB6:

    C#
    public void AutoFitListView(ListView lv)
    {
    for (int i = 0; i <= lv.Columns.Count - 1; i++) { lv.Columns[i].Width = -2; // longest col head and item // -1 for just longest item } }


    VB.NET
    Public Sub AutoFitListView(ByRef lv As ListView)

    For i As Integer = 0 To lv.Columns.Count - 1

    lv.Columns(i).Width = -2

    Next

    End Sub


    VB6
    Unfortunately, the VB6 solution is a bit more complicated:

    Private Const LVM_FIRST As Long = &H1000
    Private Const LVM_SETCOLUMNWIDTH As Long = (LVM_FIRST + 30)
    Private Const LVSCW_AUTOSIZE As Long = -1
    Private Const LVSCW_AUTOSIZE_USEHEADER As Long = -2

    Private Declare Function SendMessage Lib "user32" _
    Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, lParam As Any) As Long

    Public Sub AutoFitListView(lv As ListView)
    Dim i As Long

    For i = 0 To lv.ColumnHeaders.count - 1

    Call SendMessage(lv.hwnd, LVM_SETCOLUMNWIDTH, i, ByVal LVSCW_AUTOSIZE_USEHEADER)

    Next

    End Sub


    You can change the LVSCW_AUTOSIZE_USEHEADER to LVSCW_AUTOSIZE if you do not want to consider the Header when adjusting the size.

    More examples of the VB6 approach can be found at:

    http://vbnet.mvps.org/index.html?code/comctl/lvcolumnautosize.htm

    How to Sort Listview when clicking on Column Header

    http://support.microsoft.com/kb/319399

    Formatting Strings in .NET - Desktop and Windows Mobile

    Here is a great blog entry on formatting string in VB.NET or C#:

    http://blogs.msdn.com/kathykam/archive/2006/03/29/564426.aspx

    Here is the crux:




    alignment - the minimal length of the string. Positive values are right justified; Negative values are left justified.



    format string -

    Numeric format specifier:

    C or c = Currency
    D or d = Decimal
    E or e = Scientific
    F or f = fixed-point
    G or g = General

    Standard Datetime format specifier

    Custom Datetime format specifier

    Enumeration format specifier



    Zeros - Different meaning depending on the specifier:

    Leading Zeros: D, X
    Trailing Zeros: C, E, F, N, P
    Nothing: G

    Tuesday, April 17, 2007

    Random Access with StreamReader - Seeking and File Position with ReadLine

    I spent some time researching how to have dynamic access with StreamReader while using ReadLine and the solution turned out to more complicated that I would expect for .NET at this stage of its development.

    My problem is that I have a text file I am reading with a StreamReader object and I am using ReadLine to get one line of text at a time. Nothing special here, but periodically I need to go back to a previous position in the file and read that part again.

    If you use the BaseStream property of the StreamReader Object, then you can use the Position property and Seek method to get and set the current position in the file. These two items would appear to be all that you need to get the random access you need; however, when you use Position to get the offset of the file after the ReadLine, you don’t get the position of the file after the last line read, you get the position of the end of the buffer (usually 1024 bytes in size). So, when you use Seek to go back to that position, you will unlikely get back to the position you want unless the buffer boundary just happens to work out right.

    I searched around for a simple solution to this problem (there may be and I haven’t found it yet). There were lots of posting about using FileStream, but it doesn't have ReadLine to read a line of text, so they were suggesting that you implement your own version of ReadLine for FileStream. I also found information on DiscardBufferedData that can be used with StreamReader, but it doesn’t help you get the correct offset after using ReadLine.
    There were several suggestions on writing your own version of StreamReader:

    http://bytes.com/forum/thread238508.html

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=6720&SiteID=1

    I finally bit the bullet and created my own class to accomplish what I need (and only what I need). The previous two posts didn’t provide me with a working solution, so I am going to post what I have come up with. It may need some more refinement, but it appears to work okay. This is in VB.NET, but should be easily translatable into C# if necessary.

    The first code snippet is an example of using the FileClass to read a file. In this example, I am looking for the string “*****StartOfData******”. When this string is found, I get the position and then call my PreprocessData function to read the rest of the data. I then go back to the position and run ProcessData from the same point:



    Dim list() As String
    Dim sep() As Char = {""c}

    Try
    Dim s As New FileClass
    s.Open(TextBoxDataFile.Text)

    Dim buffer As String = ""

    Do

    If Not s.GetNextLine(buffer) Then
    Exit Do
    End If

    list = buffer.Split(sep)

    If buffer = "*****StartOfData*****" Then

    Dim startOfData As Integer = s.GetCurrentOffset()

    PreprocessData(s)

    s.SetCurrentOffset(startOfData)

    ProcessData(s)

    End If

    Loop Until s.EOF()

    s.Close()

    Catch ex As Exception

    Return False

    End Try



    The FileClass is shown below:



    Imports System.IO
    Imports System.text

    Public Class FileClass

    Const BUFFER_SIZE As Integer = 1024

    Private g_file As StreamReader = Nothing
    Private g_line As Integer = 0
    Private g_position As Integer = 0
    Private g_buffer(BUFFER_SIZE) As Char
    Private g_bufferSize As Integer = 0
    Private g_offset As Integer = 0
    Private g_eofFlag As Boolean = True
    Private g_lineBuffer As New StringBuilder(BUFFER_SIZE)
    Private g_bufferOffset As Integer = 0

    Public Function Open(ByVal filename As String) As Boolean

    If Not g_file Is Nothing Then Close()

    g_file = New StreamReader(filename)
    g_line = 0
    g_position = 0
    g_eofFlag = False
    g_bufferSize = 0
    g_bufferOffset = 0

    LoadBuffer()

    End Function

    Public Function Close() As Boolean

    g_file.Close()
    g_file = Nothing
    g_line = 0
    g_position = 0
    g_eofFlag = True
    g_bufferSize = 0

    Return True

    End Function

    Public Function GetCurrentOffset() As Integer
    Return g_offset
    End Function

    Public Function SetCurrentOffset(ByVal offset As Integer) As Boolean

    Dim pos As Long = g_file.BaseStream.Seek(offset, SeekOrigin.Begin)

    g_file.DiscardBufferedData()

    LoadBuffer()

    Return offset = pos

    End Function

    Public Function GetNextLine(ByRef data As String) As Boolean

    g_lineBuffer.Length = 0

    Dim ch As Char
    Dim flag As Boolean = False

    While Not flag

    ch = g_buffer(g_position)

    If ch = vbCr Then
    ' do nothing - skip cr
    ElseIf ch = vbLf Then
    flag = True
    Else
    g_lineBuffer.Append(ch)
    End If

    g_position = g_position + 1

    If g_position = g_bufferSize Then
    If Not LoadBuffer() Then
    Exit While
    End If
    End If

    End While

    If flag Then
    g_offset = g_bufferOffset + g_position
    data = g_lineBuffer.ToString
    Return True
    End If

    Return False

    End Function

    Private Function LoadBuffer() As Boolean

    g_bufferOffset = Convert.ToInt32(g_file.BaseStream.Position)
    g_position = 0
    g_bufferSize = g_file.Read(g_buffer, 0, BUFFER_SIZE)

    If g_bufferSize = 0 Then
    g_eofFlag = True
    Return False
    End If

    Return True

    End Function

    Public Function EOF() As Boolean
    Return g_eofFlag
    End Function

    End Class



    The FileClass is pretty simple, it just has to fill a buffer and look for the carriage returns and linefeeds itself to make generate the line it reads.