This blog is a depository for things I have found regarding VB.NET and C#.NET development (and other things I may need to remember). This blog is primarily for my own reference, but if the information I found is useful to others, then that is great. If others want to contribute with comments or other information, then that is great too.
Wednesday, December 19, 2007
Browsing a .SDF file (SQL Server CE database file)
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#
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
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#
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#
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
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
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
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
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)
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
- 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.
For Smartphone (Windows Mobile Smartphone 5.0):
from http://blogs.msdn.com/windowsmobile/archive/2006/06/07/620387.aspx
Saturday, September 29, 2007
Pocket Outlook on Windows Mobile
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#
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
#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
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
Sunday, August 19, 2007
Finding the Size of a file while Writing when using StreamWriter
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
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#
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
http://msconline.maconstate.edu/tutorials/VBNET/VBNET01/vbnet01-08.aspx
Friday, July 20, 2007
Path and Filename Decomposition function in VB.NET and C#
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"
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#
Generating a GUID in Windows Mobile using VB.NET or C#
http://msdn2.microsoft.com/en-us/library/aa446557.aspx
Finding the My Documents Directory in Windows Mobile (or the Desktop)
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
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
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
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
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
http://www.java2s.com/Code/VB/Development/UseReflectiontocreateClassinstanceandcallmethod.htm
Tuesday, July 10, 2007
Passing a Function by Reference in VB.NET
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
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
Tuesday, June 26, 2007
Moving Listview Items Up or Down
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
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
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)
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
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
Formatting Strings in .NET - Desktop and Windows Mobile
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
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.