This article in PC Magazine discusses a utility called the Process Explorer (free from Sysinternals):
http://www.pcmag.com/article2/0,2817,2332918,00.asp
The utility can be downloaded from:
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
This utility is like Task Manager's Process Viewer, only it tells much more information that can be used to diagnose problems.
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 17, 2008
Tuesday, November 18, 2008
How to determine the .NET Compact Framework Version on the Device
Here is the best posting I have found to determine the version of the .NET Compact Framework on the device:
http://www.byteswired.com/2007/09/27/how-to-determine-compactframework-version/
The summary is that you look at the registry key:
HKLM\SOFTWARE\Microsoft\.NetCompactFramework
http://www.byteswired.com/2007/09/27/how-to-determine-compactframework-version/
The summary is that you look at the registry key:
HKLM\SOFTWARE\Microsoft\.NetCompactFramework
Labels:
Compact Framework,
registry
Tuesday, November 11, 2008
Determine OS version with .NET Compact Framework
If you are running a Device application and want to know (in the code) which platform you are running on (it could be CE.NET or Windows Mobile or various versions of each), then you can use:
Environment.OSVersion.Platform
For much more information and several examples, see:
http://www.christec.co.nz/blog/archives/77
Environment.OSVersion.Platform
For much more information and several examples, see:
http://www.christec.co.nz/blog/archives/77
Labels:
Environment,
Windows Mobile
Friday, November 7, 2008
Selecting all Items in a ListBox in VB.NET
It seems to me like there should be a method that would select or deselect all items in a listbox, but there is not. Here is a simple sub to accomplish this task:
Public Sub SelectAllListBoxItems(ByVal lv As ListBox, ByVal selected As Boolean)
For i As Integer = 0 To lv.Items.Count - 1
ListBoxValidations.SetSelected(i, selected)
Next
End Sub
Public Sub SelectAllListBoxItems(ByVal lv As ListBox, ByVal selected As Boolean)
For i As Integer = 0 To lv.Items.Count - 1
ListBoxValidations.SetSelected(i, selected)
Next
End Sub
Labels:
listbox
Saturday, October 25, 2008
Parsing text Syntax Highlighting in a Rich Text Box
Here is an interesting posting on how to format text in a Rich Text Box control so that it does Syntax Highlighing:
http://www.c-sharpcorner.com/uploadfile/duncanharris/syntaxhighlightinrichtextboxp112012005050840am/syntaxhighlightinrichtextboxp1.aspx
http://www.c-sharpcorner.com/uploadfile/duncanharris/syntaxhighlightinrichtextboxp112012005050840am/syntaxhighlightinrichtextboxp1.aspx
Labels:
Rich Text,
Syntax Highlighting
Friday, October 24, 2008
Great Info on Working with Text in .NET
The following link shows how to Align Text, Clip Text, Wrap Text, Transform Text, and Shade Text in .NET:
http://www.devx.com/dotnet/Article/33464/1954
http://www.devx.com/dotnet/Article/33464/1954
Labels:
Text
Converting a TrueType Font Character into a Bitmap
Here is an excellent article on creating a bitmap from a TrueType Font Character. If you want to create a symbol selection dialog with a ListView, these routines can generate the Bitmap image for the listview items.
http://www.codeproject.com/KB/GDI-plus/TTF_to_bitmap_convert.aspx
This article did more than I needed. I only wanted to create the images for a ListView for all of the characters in a TrueType font. I have boiled down the code from the above article to the following:
Private Sub UpdateSymbolList(fontName as String)
ListView1.Items.Clear()
For i As Integer = 0 To 255
Dim bm As Bitmap = ConvertChar(fontName, i, Color.Blue, 32, 32, 20)
ImageList1.Images.Add(i.ToString, bm)
Next
ListView1.LargeImageList = ImageList1
ListView1.SmallImageList = ImageList1
For i As Integer = 0 To 255
Dim lvi As New ListViewItem
lvi.Text = i.ToString
lvi.ImageKey = i.ToString
ListView1.Items.Add(lvi)
Next
End Sub
Public Shared Function ConvertChar(ByVal fontName As String, _
ByVal charCode As Integer, _
ByVal color As Color, _
ByVal bitmapWidth As Integer, _
ByVal bitmapHeight As Integer, _
ByVal characterSize As Single) As Bitmap
Dim charToDraw As Char = Chr(charCode)
Dim bitmap As New Bitmap(bitmapWidth, bitmapHeight)
Dim g As Graphics = Graphics.FromImage(bitmap)
Dim fnt As Font = New Font(fontName, characterSize, FontStyle.Regular)
Dim textFormat As New StringFormat()
textFormat.Alignment = StringAlignment.Center
textFormat.LineAlignment = StringAlignment.Center
g.DrawString(charToDraw.ToString, fnt, New SolidBrush(color), New RectangleF(0, 1, bitmapWidth, bitmapHeight), textFormat)
g.DrawRectangle(New Pen(Drawing.Color.Black, 1), New Rectangle(0, 0, bitmapWidth - 1, bitmapHeight - 1))
Return bitmap
End Function
http://www.codeproject.com/KB/GDI-plus/TTF_to_bitmap_convert.aspx
This article did more than I needed. I only wanted to create the images for a ListView for all of the characters in a TrueType font. I have boiled down the code from the above article to the following:
Private Sub UpdateSymbolList(fontName as String)
ListView1.Items.Clear()
For i As Integer = 0 To 255
Dim bm As Bitmap = ConvertChar(fontName, i, Color.Blue, 32, 32, 20)
ImageList1.Images.Add(i.ToString, bm)
Next
ListView1.LargeImageList = ImageList1
ListView1.SmallImageList = ImageList1
For i As Integer = 0 To 255
Dim lvi As New ListViewItem
lvi.Text = i.ToString
lvi.ImageKey = i.ToString
ListView1.Items.Add(lvi)
Next
End Sub
Public Shared Function ConvertChar(ByVal fontName As String, _
ByVal charCode As Integer, _
ByVal color As Color, _
ByVal bitmapWidth As Integer, _
ByVal bitmapHeight As Integer, _
ByVal characterSize As Single) As Bitmap
Dim charToDraw As Char = Chr(charCode)
Dim bitmap As New Bitmap(bitmapWidth, bitmapHeight)
Dim g As Graphics = Graphics.FromImage(bitmap)
Dim fnt As Font = New Font(fontName, characterSize, FontStyle.Regular)
Dim textFormat As New StringFormat()
textFormat.Alignment = StringAlignment.Center
textFormat.LineAlignment = StringAlignment.Center
g.DrawString(charToDraw.ToString, fnt, New SolidBrush(color), New RectangleF(0, 1, bitmapWidth, bitmapHeight), textFormat)
g.DrawRectangle(New Pen(Drawing.Color.Black, 1), New Rectangle(0, 0, bitmapWidth - 1, bitmapHeight - 1))
Return bitmap
End Function
Labels:
Bitmap,
Large Fonts,
TrueType
Tuesday, October 21, 2008
Option Strict On causes Disallows Late Binding Error when getting Variant Array from a COM Object
I have several ActiveX controls that I use with .NET. Generally, there are not too many problems using them with .NET, but I have come across one error that was difficult (for me) to solve.
Since the ActiveX controls were originally written for VB6, they return Variants and arrays are returned as Variants of Variants. This is all fine because .NET has an Object type to work with the variants. As a rule, however, I use Option Strict On because if you don't use this option, Dotfuscator will really cause problems without letting you know in advance. But the catch is that with Option Strict on, you cannot do something like the following:
Dim varArray as Object
Dim count as Integer
SomeComObject.GetList( varArray, count )
For i as Integer = 0 to count - 1
Debug.WriteLine( varArray(i).ToString )
Next
varArray will return list of integers, but as a Variant Array of Variant Integer values.
The code above will not work with Option Strict On because the varArray(i) is late bound and this is not allowed. My first though was to try:
Dim val as integer = CType( varArray(i), Integer)
The above code does not work or any similar cast.
The only solution I have discovered (and there are probably others) is to cast the Variant array as an Object array like:
Dim vArray() as Object = CType( varArray, Object())
Then the vArray is a Object Array and can be further cast to other types without catching on the Option Strict On. For example:
Dim catList As Object = Nothing
Dim offsetList As Object = Nothing
Dim filterList As Object = Nothing
While viewObj.GetElementsInRangeFetch(1000, catList, offsetList, filterList, blockCount)
Dim cList() As Object = CType(catList, Object())
Dim oList() As Object = CType(offsetList, Object())
Dim fList() As Object = CType(filterList, Object())
For j As Integer = 0 To blockCount - 1
ProcessFeature(CInt(cList(j)), CInt(oList(j)), CInt(fList(j)))
Next
catList = Nothing
offsetList = Nothing
filterList = Nothing
End While
This may not be the cleanest solution, but it does work and allow the Option Strict setting to be left on.
Since the ActiveX controls were originally written for VB6, they return Variants and arrays are returned as Variants of Variants. This is all fine because .NET has an Object type to work with the variants. As a rule, however, I use Option Strict On because if you don't use this option, Dotfuscator will really cause problems without letting you know in advance. But the catch is that with Option Strict on, you cannot do something like the following:
Dim varArray as Object
Dim count as Integer
SomeComObject.GetList( varArray, count )
For i as Integer = 0 to count - 1
Debug.WriteLine( varArray(i).ToString )
Next
varArray will return list of integers, but as a Variant Array of Variant Integer values.
The code above will not work with Option Strict On because the varArray(i) is late bound and this is not allowed. My first though was to try:
Dim val as integer = CType( varArray(i), Integer)
The above code does not work or any similar cast.
The only solution I have discovered (and there are probably others) is to cast the Variant array as an Object array like:
Dim vArray() as Object = CType( varArray, Object())
Then the vArray is a Object Array and can be further cast to other types without catching on the Option Strict On. For example:
Dim catList As Object = Nothing
Dim offsetList As Object = Nothing
Dim filterList As Object = Nothing
While viewObj.GetElementsInRangeFetch(1000, catList, offsetList, filterList, blockCount)
Dim cList() As Object = CType(catList, Object())
Dim oList() As Object = CType(offsetList, Object())
Dim fList() As Object = CType(filterList, Object())
For j As Integer = 0 To blockCount - 1
ProcessFeature(CInt(cList(j)), CInt(oList(j)), CInt(fList(j)))
Next
catList = Nothing
offsetList = Nothing
filterList = Nothing
End While
This may not be the cleanest solution, but it does work and allow the Option Strict setting to be left on.
Labels:
Casting,
Dotfuscator,
Late Binding,
Option Strict
Option Strict On causes Disallows Late Binding Error when getting Variant Array from a COM Object
I have several ActiveX controls that I use with .NET. Generally, there are not too many problems using them with .NET, but I have come across one error that was difficult (for me) to solve.
Since the ActiveX controls were originally written for VB6, they return Variants and arrays are returned as Variants of Variants. This is all fine because .NET has an Object type to work with the variants. As a rule, however, I use Option Strict On because if you don't use this option, Dotfuscator will really cause problems without letting you know in advance. But the catch is that with Option Strict on, you cannot do something like the following:
Dim varArray as Object
Dim count as Integer
SomeComObject.GetList( varArray, count )
For i as Integer = 0 to count - 1
Debug.WriteLine( varArray(i).ToString )
Next
varArray will return list of integers, but as a Variant Array of Variant Integer values.
The code above will not work with Option Strict On because the varArray(i) is late bound and this is not allowed. My first though was to try:
Dim val as integer = CType( varArray(i), Integer)
This doesn't work or any similar cast.
The only way solution (and there are probably others) is to cast the Variant array as an Integer array like:
Dim vArray() as Integer = CType( varArray, Integer())
Then the vArray is a regular Integer Array.
Since the ActiveX controls were originally written for VB6, they return Variants and arrays are returned as Variants of Variants. This is all fine because .NET has an Object type to work with the variants. As a rule, however, I use Option Strict On because if you don't use this option, Dotfuscator will really cause problems without letting you know in advance. But the catch is that with Option Strict on, you cannot do something like the following:
Dim varArray as Object
Dim count as Integer
SomeComObject.GetList( varArray, count )
For i as Integer = 0 to count - 1
Debug.WriteLine( varArray(i).ToString )
Next
varArray will return list of integers, but as a Variant Array of Variant Integer values.
The code above will not work with Option Strict On because the varArray(i) is late bound and this is not allowed. My first though was to try:
Dim val as integer = CType( varArray(i), Integer)
This doesn't work or any similar cast.
The only way solution (and there are probably others) is to cast the Variant array as an Integer array like:
Dim vArray() as Integer = CType( varArray, Integer())
Then the vArray is a regular Integer Array.
Sunday, October 19, 2008
Auto Fit Columns in a DataGridView
I have posted a function to auto-fit the columns in a ListView before. However, when I wanted to do the same thing for a DataGridView, the task is a little different (yet easier):
DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
Labels:
DataGridView,
fit
Thursday, October 16, 2008
Basic Registry Operations with VB.NET
Reading and Writing to the Registry in VB.NET is fairly simple, especially when compared to using C++. However, it can still be a little difficult to get going. Here are 3 functions to perform the basic Registry operations: Read, Write, and Delete.
Examples Using the Functions:
Dim value As String = _
GetRegistryValue(Registry.LocalMachine, _
"SOFTWARE\CompanyName\ApplicationName", "License")
SetRegistryValue(Registry.LocalMachine, _
"SOFTWARE\CompanyName\ApplicationName", _
"License", "value")
DeleteRegistryValue(Registry.LocalMachine, _
"SOFTWARE\CompanyName\ApplicationName", "License")
Read a Registry Value
Public Function GetRegistryValue(ByVal regKey As RegistryKey, _
ByVal subKey As String, ByVal valueName As String) As String
Dim value As String = ""
Dim registryKey As RegistryKey = regKey
Dim registrySubKey As RegistryKey
registrySubKey = registryKey.OpenSubKey(subKey)
If registrySubKey IsNot Nothing Then
Try
value = registrySubKey.GetValue(valueName).ToString
Catch ex As Exception
value = ""
End Try
registrySubKey.Close()
End If
Return value
End Function
Write a Registry Value
Public Function SetRegistryValue(ByVal regKey As RegistryKey, _
ByVal subKey As String, ByVal valueName As String, ByVal value As String) As Boolean
Dim registryKey As RegistryKey = regKey
Dim registrySubKey As RegistryKey
registrySubKey = registryKey.OpenSubKey(subKey, True)
If registrySubKey Is Nothing Then
registrySubKey = registryKey.CreateSubKey(subKey, RegistryKeyPermissionCheck.ReadWriteSubTree)
End If
If registrySubKey IsNot Nothing Then
registrySubKey.SetValue(valueName, value)
registrySubKey.Close()
Return True
End If
Return False
End Function
Delete a Registry Value
Public Function DeleteRegistryValue(ByVal regKey As RegistryKey, _
ByVal subKey As String, ByVal valueName As String) As Boolean
Dim value As String = ""
Dim registryKey As RegistryKey = regKey
Dim registrySubKey As RegistryKey
registrySubKey = registryKey.OpenSubKey(subKey, True)
If registrySubKey IsNot Nothing Then
Dim retValue As Boolean = True
Try
registrySubKey.DeleteValue(valueName)
Catch ex As Exception
retValue = False
End Try
registrySubKey.Close()
Return retValue
End If
Return False
End Function
Examples Using the Functions:
Dim value As String = _
GetRegistryValue(Registry.LocalMachine, _
"SOFTWARE\CompanyName\ApplicationName", "License")
SetRegistryValue(Registry.LocalMachine, _
"SOFTWARE\CompanyName\ApplicationName", _
"License", "value")
DeleteRegistryValue(Registry.LocalMachine, _
"SOFTWARE\CompanyName\ApplicationName", "License")
Read a Registry Value
Public Function GetRegistryValue(ByVal regKey As RegistryKey, _
ByVal subKey As String, ByVal valueName As String) As String
Dim value As String = ""
Dim registryKey As RegistryKey = regKey
Dim registrySubKey As RegistryKey
registrySubKey = registryKey.OpenSubKey(subKey)
If registrySubKey IsNot Nothing Then
Try
value = registrySubKey.GetValue(valueName).ToString
Catch ex As Exception
value = ""
End Try
registrySubKey.Close()
End If
Return value
End Function
Write a Registry Value
Public Function SetRegistryValue(ByVal regKey As RegistryKey, _
ByVal subKey As String, ByVal valueName As String, ByVal value As String) As Boolean
Dim registryKey As RegistryKey = regKey
Dim registrySubKey As RegistryKey
registrySubKey = registryKey.OpenSubKey(subKey, True)
If registrySubKey Is Nothing Then
registrySubKey = registryKey.CreateSubKey(subKey, RegistryKeyPermissionCheck.ReadWriteSubTree)
End If
If registrySubKey IsNot Nothing Then
registrySubKey.SetValue(valueName, value)
registrySubKey.Close()
Return True
End If
Return False
End Function
Delete a Registry Value
Public Function DeleteRegistryValue(ByVal regKey As RegistryKey, _
ByVal subKey As String, ByVal valueName As String) As Boolean
Dim value As String = ""
Dim registryKey As RegistryKey = regKey
Dim registrySubKey As RegistryKey
registrySubKey = registryKey.OpenSubKey(subKey, True)
If registrySubKey IsNot Nothing Then
Dim retValue As Boolean = True
Try
registrySubKey.DeleteValue(valueName)
Catch ex As Exception
retValue = False
End Try
registrySubKey.Close()
Return retValue
End If
Return False
End Function
Friday, October 3, 2008
FTP Upload and Download in VB.NET and C#
The following site has C# code to upload and download a file via FTP in C#:
http://www.codeguru.com/csharp/csharp/cs_internet/desktopapplications/article.php/c13163
You can take the C# code and paste into the converter at the following web site to get VB.NET:
http://www.developerfusion.com/tools/convert/csharp-to-vb/
http://www.codeguru.com/csharp/csharp/cs_internet/desktopapplications/article.php/c13163
You can take the C# code and paste into the converter at the following web site to get VB.NET:
http://www.developerfusion.com/tools/convert/csharp-to-vb/
Labels:
FTP
Thursday, October 2, 2008
Getting Windows Mobile Owner Name and Device Name
It is sometimes useful to get the Owner Name and/or the Device Name of the Windows Mobile device. If you are wanting a Device Id, then see this posting.
There are different ways to get the Owner Name and Device Name:
For Owner Name, add the following reference to your project:
Microsoft.WindowsMobileMicrosoft.WindowsMobile.Status
Then in your code:
Imports Microsoft.WindowsMobile.Status
.
.
.
MessageBox.Show(SystemState.OwnerName)
More info at:
http://www.c-sharpcorner.com/Forums/ShowMessages.aspx?ThreadID=46306
To get the Device Name (which is what you find under Start/Settings/System Tab/About), you simply have to say:
MessageBox.Show(System.Net.Dns.GetHostName())
For more Info:
http://msdn.microsoft.com/en-us/library/system.net.dns.gethostname.aspx
There are different ways to get the Owner Name and Device Name:
For Owner Name, add the following reference to your project:
Microsoft.WindowsMobileMicrosoft.WindowsMobile.Status
Then in your code:
Imports Microsoft.WindowsMobile.Status
.
.
.
MessageBox.Show(SystemState.OwnerName)
More info at:
http://www.c-sharpcorner.com/Forums/ShowMessages.aspx?ThreadID=46306
To get the Device Name (which is what you find under Start/Settings/System Tab/About), you simply have to say:
MessageBox.Show(System.Net.Dns.GetHostName())
For more Info:
http://msdn.microsoft.com/en-us/library/system.net.dns.gethostname.aspx
Labels:
Device Name,
Owner Name,
Windows Mobile
Wednesday, September 24, 2008
Unresolved Externals when using POOM in VC++
I found several postings when searching for a solution to compiling a POOM app that errors out with Unresolved External Symbol CLSID_Application and IID_IPOutlookApp. Only one of the solutions I found worked for me using Visual Studio 2008 C++:
http://www.tech-archive.net/Archive/PocketPC/microsoft.public.pocketpc.developer/2006-03/msg00236.html
The trick is to use:
#include "initguid.h"
#include "pimstore.h"
at the begining of the .cpp file. The initguid.h is the item that fixes the problem.
http://www.tech-archive.net/Archive/PocketPC/microsoft.public.pocketpc.developer/2006-03/msg00236.html
The trick is to use:
#include "initguid.h"
#include "pimstore.h"
at the begining of the .cpp file. The initguid.h is the item that fixes the problem.
Labels:
POOM,
Windows Mobile
Saturday, September 6, 2008
Incrementing FileVersion for VC++
In a recent posting, I talked about solutions to incrementing the FileVersion in Visual Studio .NET for VB.NET and C# project. This need was motivated by the changes in VS2008 that requires a FileVersion to be changed before the Windows Installer will replace a file.
Some of my projects have Native DLLs that are compiled in VS 2008's VC++ compiler. These files has the same problem with the installer, yet the previous solution (http://dotnetref.blogspot.com/2008/09/auto-incrementing-file-version-in.html) did not address.
I found this very handy Add-In that works well with VS2008 (and previous versions) that will increment the FileVersion (Product Version, etc.) in the VC++ projects resource file.
http://www.codeguru.com/cpp/v-s/devstudio_macros/visualstudionet/article.php/c14981
Some of my projects have Native DLLs that are compiled in VS 2008's VC++ compiler. These files has the same problem with the installer, yet the previous solution (http://dotnetref.blogspot.com/2008/09/auto-incrementing-file-version-in.html) did not address.
I found this very handy Add-In that works well with VS2008 (and previous versions) that will increment the FileVersion (Product Version, etc.) in the VC++ projects resource file.
http://www.codeguru.com/cpp/v-s/devstudio_macros/visualstudionet/article.php/c14981
Labels:
file version,
installer,
VC++
Friday, September 5, 2008
Visual Studio 2008 Setup Project always requiring .NET Framework 3.5 even when 2.0 is Targeted
I am slowly upgrading my projects from VS2005 to VS2008. I had a puzzling problem with the Setup Projects always requiring the .NET Framework 3.5 even when the Setup Project is targeted to 2.0 and the application it is delivering is using .NET Framework 2.0.
There are several posting on the the internet about solving this problem. It basically requires you to go to View/Editor/Launch Condition and change the .NET Framework to the version you desire. The Project properties for your setup project are a bit misleading when they have no affect on this problem.
Read these posting for more detailed explanations:
http://impressionsoft.blogspot.com/2008/03/visual-studio-2008-setup-project-and.html
http://blogs.msdn.com/cschotte/archive/2007/08/15/vs2008-launch-conditions-and-prerequisites.aspx
There are several posting on the the internet about solving this problem. It basically requires you to go to View/Editor/Launch Condition and change the .NET Framework to the version you desire. The Project properties for your setup project are a bit misleading when they have no affect on this problem.
Read these posting for more detailed explanations:
http://impressionsoft.blogspot.com/2008/03/visual-studio-2008-setup-project-and.html
http://blogs.msdn.com/cschotte/archive/2007/08/15/vs2008-launch-conditions-and-prerequisites.aspx
Labels:
Setup Projects,
Visual Studio 2008
Thursday, September 4, 2008
Auto-Incrementing the File Version in Visual Studio 2005 and 2008
*** Update - Since I made this post, I have found another tool that is simpler to use and also work with VS2010. See this http://autobuildversion.codeplex.com/
If this doesn't work for you, then you may with to view the info below:
The Setup and Deployment (Windows Installer) has a significant change between VS2005 and VS2008. In VS2008, a file will not be updated by the installer if the File Version has not changed. This pretty much breaks all of the VS2005 Installations I have created. There are various reasons for this, and I will let you read for yourself:
http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.vstudio.general&tid=c4c56abf-9bde-45ed-8737-90cf90514d89&cat=&lang=&cr=&sloc=&p=1
The solution to the problem is to increment the File Version (under Project Properties/Assembly Information) between Setup (.msi) builds. So, before every setup you create, you have to go manually update the File Version so the setup will update the file. Before, you just had to update the Version property in the Installer Project (and let it update the Product Code); you still have to do this (which is probably acceptable). I thought there must be someway to automatically increment the File Version since this change to the Installer breaks all of my setups; however, there is not (that I can find anyway). The only workable solution I have found is to use a BuildTask that updates the AssemblyInfo.vb (or AssemblyInfo.cs) before each build is made. This solution is a really complicated for something that was a checkbox in VB6 (as someone pointed out).
Here is the solution I tried and it does work:
http://www.codeproject.com/KB/dotnet/Auto_Increment_Version.aspx
Here is a similar solution:
http://weblogs.asp.net/bradleyb/archive/2005/12/02/432150.aspx
If this doesn't work for you, then you may with to view the info below:
The Setup and Deployment (Windows Installer) has a significant change between VS2005 and VS2008. In VS2008, a file will not be updated by the installer if the File Version has not changed. This pretty much breaks all of the VS2005 Installations I have created. There are various reasons for this, and I will let you read for yourself:
http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.vstudio.general&tid=c4c56abf-9bde-45ed-8737-90cf90514d89&cat=&lang=&cr=&sloc=&p=1
The solution to the problem is to increment the File Version (under Project Properties/Assembly Information) between Setup (.msi) builds. So, before every setup you create, you have to go manually update the File Version so the setup will update the file. Before, you just had to update the Version property in the Installer Project (and let it update the Product Code); you still have to do this (which is probably acceptable). I thought there must be someway to automatically increment the File Version since this change to the Installer breaks all of my setups; however, there is not (that I can find anyway). The only workable solution I have found is to use a BuildTask that updates the AssemblyInfo.vb (or AssemblyInfo.cs) before each build is made. This solution is a really complicated for something that was a checkbox in VB6 (as someone pointed out).
Here is the solution I tried and it does work:
http://www.codeproject.com/KB/dotnet/Auto_Increment_Version.aspx
Here is a similar solution:
http://weblogs.asp.net/bradleyb/archive/2005/12/02/432150.aspx
Labels:
auto-increment,
file version,
installer
Wednesday, September 3, 2008
Launch Internet Explorer or Default Browser from VB.NET (or C#)
I found several ways to launch IE from VB.NET, but the following approach appears to be the simplest:
Process.Start("IExplore.exe", "http://dotnetref.blogspot.com")
More information at:
http://bytes.com/forum/thread413370.html
If you want to launch the default browser (such as Firefox), it may be easiest to just say the following:
Process.Start("http://dotnetref.blogspot.com")
and let the Shell do the work of deciding th default browser.
For more info on this approach:
http://www.vbforums.com/showthread.php?t=323257
The C# approach is not any different, just use the approprate syntax.
Process.Start("IExplore.exe", "http://dotnetref.blogspot.com")
More information at:
http://bytes.com/forum/thread413370.html
If you want to launch the default browser (such as Firefox), it may be easiest to just say the following:
Process.Start("http://dotnetref.blogspot.com")
and let the Shell do the work of deciding th default browser.
For more info on this approach:
http://www.vbforums.com/showthread.php?t=323257
The C# approach is not any different, just use the approprate syntax.
Labels:
default browser,
Internet Explorer,
launching
Thursday, August 28, 2008
Getting a Device ID using the Compact Framework
Here are a couple of approaches I found for getting a Device ID using the compact framework. Both are lengthy solutions to something that should probably be built into platform.
http://msdn.microsoft.com/en-us/library/ms172516.aspx
http://msdn.microsoft.com/en-us/library/aa446562.aspx
http://blogs.msdn.com/jehance/archive/2004/07/12/181067.aspx
http://msdn.microsoft.com/en-us/library/ms172516.aspx
http://msdn.microsoft.com/en-us/library/aa446562.aspx
http://blogs.msdn.com/jehance/archive/2004/07/12/181067.aspx
Labels:
device Id,
Windows Mobile
How to do a CDC.Escape() in .NET
There may be ways around using the old CDC Escape function from MFC, but when you are porting C++ to C#, it is nice to just call the same Win32api functions that you were using before. For printing, I used the Escape function to get information about the printer, but since this method can return a Point structure the PInvoke was more difficult. Here is the code necessary to call the Escape method:
First you need the POINT structure defined in .NET:
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
Then you need the Signature for the Escape method ):
[DllImport("gdi32.dll")]
private static extern int Escape(IntPtr hdc, int nEscape, int cbInput, string lpvInData, IntPtr lpvOutData);
There are also the constants that are sent as the Escape type (I just provide a couple of example that return a Point structure):
private const int GETPRINTINGOFFSET = 13;
private const int GETPHYSPAGESIZE = 12;
Then you can call the method. You can get the Graphics object from various places, but you need the HDc from it regardless:
IntPtr hDC = e.Graphics.GetHdc();
IntPtr pnt;
long stat;
POINT printingOffsetPoint = new POINT(0,0);
pnt = Marshal.AllocHGlobal(Marshal.SizeOf(printingOffsetPoint));
Marshal.StructureToPtr(printingOffsetPoint, pnt, false);
stat = Escape(hDC,GETPRINTINGOFFSET, 0, null, pnt);
printingOffsetPoint = (POINT)Marshal.PtrToStructure(pnt, typeof(POINT));
Marshal.FreeHGlobal(pnt);
POINT physPageSizePoint = new POINT(0, 0);
pnt = Marshal.AllocHGlobal(Marshal.SizeOf(physPageSizePoint));
Marshal.StructureToPtr(physPageSizePoint, pnt, false);
stat = Escape(hDC, GETPHYSPAGESIZE, 0, null, pnt);
physPageSizePoint = (POINT)Marshal.PtrToStructure(pnt, typeof(POINT));
Marshal.FreeHGlobal(pnt);
First you need the POINT structure defined in .NET:
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
Then you need the Signature for the Escape method ):
[DllImport("gdi32.dll")]
private static extern int Escape(IntPtr hdc, int nEscape, int cbInput, string lpvInData, IntPtr lpvOutData);
There are also the constants that are sent as the Escape type (I just provide a couple of example that return a Point structure):
private const int GETPRINTINGOFFSET = 13;
private const int GETPHYSPAGESIZE = 12;
Then you can call the method. You can get the Graphics object from various places, but you need the HDc from it regardless:
IntPtr hDC = e.Graphics.GetHdc();
IntPtr pnt;
long stat;
POINT printingOffsetPoint = new POINT(0,0);
pnt = Marshal.AllocHGlobal(Marshal.SizeOf(printingOffsetPoint));
Marshal.StructureToPtr(printingOffsetPoint, pnt, false);
stat = Escape(hDC,GETPRINTINGOFFSET, 0, null, pnt);
printingOffsetPoint = (POINT)Marshal.PtrToStructure(pnt, typeof(POINT));
Marshal.FreeHGlobal(pnt);
POINT physPageSizePoint = new POINT(0, 0);
pnt = Marshal.AllocHGlobal(Marshal.SizeOf(physPageSizePoint));
Marshal.StructureToPtr(physPageSizePoint, pnt, false);
stat = Escape(hDC, GETPHYSPAGESIZE, 0, null, pnt);
physPageSizePoint = (POINT)Marshal.PtrToStructure(pnt, typeof(POINT));
Marshal.FreeHGlobal(pnt);
Thursday, August 7, 2008
Using Dock Fill on a Control when you have a Menu and/or Status Bar
I have long been frustrated in Visual Studio .NET when I try to use a control's Dock property set to Fill and also have a Menu or Status bar on the same form. The Docked control typically fills to the form and is not the right size (not accounting for the size of the Menu or Status bar).
It turns out that there is a very simple (but not very obvious) solution to this problem. Taken from Alex Fr's response to a comment on a similar problem:
"Actually, all you need to do is rightclick the panel and choose "bring to front", the dock layout logic handles each component in order so when it reaches your panel first it doesnt know it has other components that fill up other parts of the container with their docking settings. "
Just make sure the Docked control is in front of the menu and status bar and it works as you would expect.
It turns out that there is a very simple (but not very obvious) solution to this problem. Taken from Alex Fr's response to a comment on a similar problem:
"Actually, all you need to do is rightclick the panel and choose "bring to front", the dock layout logic handles each component in order so when it reaches your panel first it doesnt know it has other components that fill up other parts of the container with their docking settings. "
Just make sure the Docked control is in front of the menu and status bar and it works as you would expect.
Labels:
Dock,
Fill,
Menu,
Status Bar
Sunday, August 3, 2008
Seeing what color the .NET Color names actually are
I found a very useful .NET Color reference at the following web site. If you want to compare AliceBlue, DodgerBlue, and SteelBlue, here is an easy way to do it:
http://www.opinionatedgeek.com/DotNet/Tools/Colors/default.aspx
http://www.opinionatedgeek.com/DotNet/Tools/Colors/default.aspx
Wednesday, July 30, 2008
Setting the Form Icon to an Application Resource in VB.NET
I have an application with a main form and many dialogs. I want the main form and all of the dialogs to use the same icon in the forms' title bars. So, instead of defining the Icon property on each form, I have created an application resource and added a line of code to each Form_Load method.
First, add an Icon to your Project Resources (Project/Properties then on the Resource tab). Remember the name of the icon resource you create. Mine is AppIcon in this example.
Then for each Form_Load method in the VB.NET app (for the main form and each dialog's form), I add the following:
Me.Icon = My.Resources.AppIcon
There may be even better ways to do this, but this is the simplest I have found so far.
For more information on using resources, see:
http://visualbasic.about.com/od/usingvbnet/a/ResVBNET.htm
First, add an Icon to your Project Resources (Project/Properties then on the Resource tab). Remember the name of the icon resource you create. Mine is AppIcon in this example.
Then for each Form_Load method in the VB.NET app (for the main form and each dialog's form), I add the following:
Me.Icon = My.Resources.AppIcon
There may be even better ways to do this, but this is the simplest I have found so far.
For more information on using resources, see:
http://visualbasic.about.com/od/usingvbnet/a/ResVBNET.htm
Tuesday, July 29, 2008
Keeping a Nonmodal form on top of App, but not on top of Everything
It took me a while to figure this one out, but the solution is pretty simple.
I want to keep a nonmodal form on top of my main app form. I have tried using:
Dlg.TopMost = True
in the nonmodal form (Dlg), but this approach keeps the form on top of everything, not just my main app form.
The solution is:
Dlg.Owner = Me ' Me is the main app form
Dlg.TopMost = False
More info can be found at:
http://www.syncfusion.com/faq/windowsforms/faq_c95c.aspx#q975q
I want to keep a nonmodal form on top of my main app form. I have tried using:
Dlg.TopMost = True
in the nonmodal form (Dlg), but this approach keeps the form on top of everything, not just my main app form.
The solution is:
Dlg.Owner = Me ' Me is the main app form
Dlg.TopMost = False
More info can be found at:
http://www.syncfusion.com/faq/windowsforms/faq_c95c.aspx#q975q
Thursday, July 24, 2008
Changing a Control's Font Size at Runtime in VB.NET
If you have a control that is using a font with size 8.25 (which was defined at design-time), then at runtime you want to change it to a different size (such as 12), you cannot simply say:
ctrl.Font.Size = 12 (this will not work - Property Size is Read-Only)
However, you can replace the whole font:
ctrl.Font = new Font(ctrl.Font.FontFamily, 12, ctrl.Font.Style)
For more info and examples in C#, see: http://bytes.com/forum/thread261450.html
ctrl.Font.Size = 12 (this will not work - Property Size is Read-Only)
However, you can replace the whole font:
ctrl.Font = new Font(ctrl.Font.FontFamily, 12, ctrl.Font.Style)
For more info and examples in C#, see: http://bytes.com/forum/thread261450.html
Sunday, June 29, 2008
Using Brushes with Semi-Transparent Color
Filling a Rectangle, Ellipse, Shape, etc. with a semi-transparent fill is done by using a SolidBrush with a Alpha value somewhere between solid and transparent.
C#:
Color col = Color.FromArgb(75, 100, 100, 100);
SolidBrush b = new SolidBrush(col);
g.FillRectangle(b, 0, 0, this.Width - 1, this.Height - 1);
VB.NET:
Dim col As Color = Color.FromArgb(75, 100, 100, 100)
Dim b As New SolidBrush(col)
g.FillRectangle(b, 0, 0, Me.Width - 1, Me.Height - 1)
For better examples, go to this link:
http://www.java2s.com/Code/CSharp/2D-Graphics/Filledwiththesemitransparentandtransparentcolor.htm
C#:
Color col = Color.FromArgb(75, 100, 100, 100);
SolidBrush b = new SolidBrush(col);
g.FillRectangle(b, 0, 0, this.Width - 1, this.Height - 1);
VB.NET:
Dim col As Color = Color.FromArgb(75, 100, 100, 100)
Dim b As New SolidBrush(col)
g.FillRectangle(b, 0, 0, Me.Width - 1, Me.Height - 1)
For better examples, go to this link:
http://www.java2s.com/Code/CSharp/2D-Graphics/Filledwiththesemitransparentandtransparentcolor.htm
Labels:
Semi-Transparent Fill,
SolidBrush
Wednesday, June 18, 2008
Disappearing Controls in the Left SplitContainer Panel when using Large Fonts
I have been experiencing a strange problem that I have finally confirmed as a bug in the .NET Framework 2.0. If you are using a SplitContainter and place controls in your Left panel, then if you anchor those controls to the Right or the Bottom, they will disappear when you run the app on a machine that is using Large Fonts. My controls happen to all be in a group box, but I don't think that matters. The controls disappear because the anchor is setting the height and/or width to 0 and they are not visible. If you can drag the size wide or tall enough, the controls will start to appear, but they scaling is off and the anchor is not working correctly. If using Small Fonts, this problem does not exists.
I found a few other people with the same problem, but no solutions. I found one suggestion to do a Refresh on the Splitter move event, but this did not help me. My solution has been to adjust the size of the controls in the left panel myself and not rely on the anchor. Please post a comment if you have a better solution to this problem.
I found a few other people with the same problem, but no solutions. I found one suggestion to do a Refresh on the Splitter move event, but this did not help me. My solution has been to adjust the size of the controls in the left panel myself and not rely on the anchor. Please post a comment if you have a better solution to this problem.
Labels:
Anchor,
Large Fonts,
SplitContainer
Saturday, June 14, 2008
Setting BackColor to System Colors (like "Control")
It took a little searching to find out how to set the BackColor or ForeColor property of a control to the predefined colors you gets in the Visual Studio Properties window for BackColor's popup color setting on the System tab. For example, I want to set to the BackColor to the "Control" color.
I found this on:
http://bytes.com/forum/thread654472.html
control.BackColor = Color.FromKnownColor(KnownColor.Control)
I found this on:
http://bytes.com/forum/thread654472.html
Labels:
backcolor,
control,
forecolor,
KnownColor
Thursday, June 12, 2008
TechEd 2008 in Orlando
The TechEd 2008 Deveveloper’s Conference was in Orlando last week. I have always attended MEDC (Mobile and Embedded Developer’s Conference) before, but it has now been merged into TechEd. I believe that I prefer the more focused content of MEDC, but if my only way to get this information is to go to TechEd, then it is not too bad of an alternative. However, there were only 11 Windows Mobile session at TechEd 2008.
There is always a flavor to a Microsoft conference. I don’t know if this is directed by the powers that be or simply a natural alignment to the new features they are providing (or a combination of both). This year, the flavor definitely tastes of LINQ (Language Integrated Query). LINQ is undeniably an interesting concept that directly integrates SQL-like statement into the language syntax of any .NET language (VB.NET, C#, etc.). What makes this new feature somewhat interesting is that the SQL statements can be applied to data in arrays, enumerable objects, XML, and databases. So, the SQL way of querying a database can now be directly applied to data in your application, not just databases.
It also appears that most of the new language features we get from Visual Studio 2008 are directly related to LINQ: Anonymous Types, Extension Methods, Lambda Expressions, Implicitly typed locals, and Object Initializers. All of these new features were added just to support LINQ. One session on the Visual Studio 2008 IDE revealed that there wasn’t much added to the IDE because all of the developers were working on LINQ. On the downside, while LINQ does run on Windows Mobile, it will only work with your application data and does not work with SQL CE. There are a lot of things in the Compact Framework I would have rather had than a partially implemented version of LINQ.
While just about every session had to work LINQ in somehow, there were a couple of other technologies that were shown off. The Windows Presentation Manager (WPF) has developed a good deal since last year and can really produce some spectacular looking demos. The new support in Visual Studio 2008 for WPF is nice, but really seems to be early in its development. All of the WPF sessions seem to highlight a few points: it has great potential, it’s not here yet, and you will need a graphic designer to properly use it. A common phrase I heard in the session is “I’m not a graphic designer, so my WPF doesn’t look very good.” Nevertheless, I still found the Technology compelling enough to pursue. As an aside, Silverlight, which is an offshoot of WPF, came across as a very immature technology. Maybe it will mature quickly.
The Window Communication Foundation (WCF) was also a popular topic. It is just the extension of Web Services to what it probably should have been in the first place.
The Windows Workflow Foundation (WF, because WWF was already taken), was new to me and looks really interesting. An oversimplified description of it would be a project type in Visual Studio that lets you create a flow chart or diagram of your business logic and then can add the code behind the items in the diagram. The WF demos were compelling, but I have to question how well it really works in the real world. The demos used very simplistic logic. How well WF scales to a real application would be interesting to know. I think time will tell on this technology. It will become really popular or just disappear.
Another interesting thing about TechEd 2008 is what they didn’t talk about. Normally, these conferences are all using beta versions of something that hasn’t been released. I went to MEDC two years in a row and all they talked about was Whidbey (VS2005). Then it was all about Orcas (VS2008). With the exception of running VS2008 service pack 1 betas and a Silverlight beta, everyone was pretty content with the released software (quite a change from previous conferences). Does this mean there isn’t anything new in the queue or they are just taking a little longer to ramp up to the new stuff.
All and all, I was pretty pleased with the conference. Visual Studio 2008 looks good enough now to upgrade to (although I may wait until SP1 until I start upgrading all of my projects). Check out the full video and text of Bill Gates’ key: http://www.microsoft.com/presspass/exec/billg/speeches/2008/06-03teched.mspx
There is always a flavor to a Microsoft conference. I don’t know if this is directed by the powers that be or simply a natural alignment to the new features they are providing (or a combination of both). This year, the flavor definitely tastes of LINQ (Language Integrated Query). LINQ is undeniably an interesting concept that directly integrates SQL-like statement into the language syntax of any .NET language (VB.NET, C#, etc.). What makes this new feature somewhat interesting is that the SQL statements can be applied to data in arrays, enumerable objects, XML, and databases. So, the SQL way of querying a database can now be directly applied to data in your application, not just databases.
It also appears that most of the new language features we get from Visual Studio 2008 are directly related to LINQ: Anonymous Types, Extension Methods, Lambda Expressions, Implicitly typed locals, and Object Initializers. All of these new features were added just to support LINQ. One session on the Visual Studio 2008 IDE revealed that there wasn’t much added to the IDE because all of the developers were working on LINQ. On the downside, while LINQ does run on Windows Mobile, it will only work with your application data and does not work with SQL CE. There are a lot of things in the Compact Framework I would have rather had than a partially implemented version of LINQ.
While just about every session had to work LINQ in somehow, there were a couple of other technologies that were shown off. The Windows Presentation Manager (WPF) has developed a good deal since last year and can really produce some spectacular looking demos. The new support in Visual Studio 2008 for WPF is nice, but really seems to be early in its development. All of the WPF sessions seem to highlight a few points: it has great potential, it’s not here yet, and you will need a graphic designer to properly use it. A common phrase I heard in the session is “I’m not a graphic designer, so my WPF doesn’t look very good.” Nevertheless, I still found the Technology compelling enough to pursue. As an aside, Silverlight, which is an offshoot of WPF, came across as a very immature technology. Maybe it will mature quickly.
The Window Communication Foundation (WCF) was also a popular topic. It is just the extension of Web Services to what it probably should have been in the first place.
The Windows Workflow Foundation (WF, because WWF was already taken), was new to me and looks really interesting. An oversimplified description of it would be a project type in Visual Studio that lets you create a flow chart or diagram of your business logic and then can add the code behind the items in the diagram. The WF demos were compelling, but I have to question how well it really works in the real world. The demos used very simplistic logic. How well WF scales to a real application would be interesting to know. I think time will tell on this technology. It will become really popular or just disappear.
Another interesting thing about TechEd 2008 is what they didn’t talk about. Normally, these conferences are all using beta versions of something that hasn’t been released. I went to MEDC two years in a row and all they talked about was Whidbey (VS2005). Then it was all about Orcas (VS2008). With the exception of running VS2008 service pack 1 betas and a Silverlight beta, everyone was pretty content with the released software (quite a change from previous conferences). Does this mean there isn’t anything new in the queue or they are just taking a little longer to ramp up to the new stuff.
All and all, I was pretty pleased with the conference. Visual Studio 2008 looks good enough now to upgrade to (although I may wait until SP1 until I start upgrading all of my projects). Check out the full video and text of Bill Gates’ key: http://www.microsoft.com/presspass/exec/billg/speeches/2008/06-03teched.mspx
Labels:
TechEd 2008
Getting Selection and Arrow keys to behave right with a ListBox in the.NET Compact Framework
I had a form in a Window Mobile application that contains a Label and a ListBox. I wanted the ListBox to behave according to the Windows Mobile UI guidelines where you click on an item with the stylus and it is automatically selected. I used the SelectedIndexChanged event to implement this behavior and it worked fine when an item was selected with the stylus. However, with all of the different kinds of devices, many of them have partial or even full keyboards and at the very least they have a joypad or equivalent, my users were wanting to use the arrow keys to navigate to a specific item in the list and then press the enter button (never using the stylus). Unfortunately, the SelectedIndexChanged event is fired anytime the ListBox’s selected item is change (by stylus or keys) and since using the arrow keys usually requires scrolling through several items before getting to the item you want, the next item in the list is always selected (be it the one you want or not). I could not find a way in the .NET Compact Framework to get the ListBox to work like I wanted.
My solution was to replace the ListBox with a ListView. Change the View property to Details and change the Activation property to OneClick. Then use the ItemActivate event provided by the ListView instead of the SelectedIndexChanged event. You also have to add at least one Column to the ListView, and you can optionally set HeaderStyle to None to get rid of the column header and make the ListView look just like a ListBox.
My solution was to replace the ListBox with a ListView. Change the View property to Details and change the Activation property to OneClick. Then use the ItemActivate event provided by the ListView instead of the SelectedIndexChanged event. You also have to add at least one Column to the ListView, and you can optionally set HeaderStyle to None to get rid of the column header and make the ListView look just like a ListBox.
Labels:
arrow keys,
itemactivate,
listbox,
listview,
selectedindexchanged,
selection,
stylus
Thursday, May 29, 2008
Not xxx Is Nothing and xxx IsNot Nothing in VB.NET
It took me a while to figure that that you can say:
If var1 IsNot Nothing Then
...
End If
Instead of the awkward:
If Not var1 is Nothing Then
...
End If
Of course the IsNot is like the Is and will work with when comparing any two object references, not just for testing for Nothing.
If var1 IsNot Nothing Then
...
End If
Instead of the awkward:
If Not var1 is Nothing Then
...
End If
Of course the IsNot is like the Is and will work with when comparing any two object references, not just for testing for Nothing.
Tuesday, May 20, 2008
Finding the "My Documents" folder in VB.net
Finding the My Documents folder in VB.NET (or C#) is pretty simple:
There are several other special folders you can get as well:
http://www.thescarms.com/dotnet/SpecialFolders.aspx
Dim dir as String
dir = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
There are several other special folders you can get as well:
- Personal (My Documents also work on devices)
- MyPictures
- DesktopDirectory
- MyMusic
- StartMenu
- Startup
- Favorites
- ApplicationData
- CommandApplicationData
- CommonProgramFiles
- Cookies
- History
- InternetCache
- LocalApplicationData
- MyComputer
- ProgramFiles
- Programs
- Recent
http://www.thescarms.com/dotnet/SpecialFolders.aspx
Friday, May 16, 2008
StartupPosition for MessageBox
Sometimes it seems that .NET has some obvious shortcomings. For example, all I want to do is have a MessageBox center in my application instead of the screen. This task shouldn't be that difficult; however, there is no way (that I have found) to set the StartPosition property for the MessageBox dialog. While there may be a functional and elegant solution to this problem (please post as a comment if you have one), the only solution I have found on the internet is to implement your own MessageBox class, and code it to do what you want. This isn't hard, but it doesn't seem like a lot of work for something so simple. Also, the Messagebox probably does more than you might first think. It does a lot of autosizing to hold whatever text you provide it.
Here is one implementation of a custom MessageBox I have found:
http://www.codeproject.com/KB/dialog/MessageBoxEx.aspx?fid=155440&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=76&select=1069708
I am sure there are more such implementations. Please post comments if you know of any.
Here is one implementation of a custom MessageBox I have found:
http://www.codeproject.com/KB/dialog/MessageBoxEx.aspx?fid=155440&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=76&select=1069708
I am sure there are more such implementations. Please post comments if you know of any.
Labels:
MessageBox,
StartPosition
Wednesday, May 14, 2008
Finding VB.NET or C# Signatures for Interop/PInvoke
There are several places to find the Signatures in VB.NET and C# for Win32Api calls online. Here is one that is pretty good:
http://pinvoke.net
http://pinvoke.net
Defaulting to Thumbnail View when using OpenFileDialog
You would think that it would be very simple to default an OpenFileDialog to any view type you want via its properties. However, there is no property exposed for setting the view type. I simply want to browse for images with my OpenFileDialog instance, and I would prefer for the user not to have to manually set the view type to Thumbnail everytime.
I found a couple of solutions:
http://www.codeproject.com/cs/miscctrl/FileDialogExtender.asp (C#)
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2741273&SiteID=1&mode=1 (same as above only in VB.NET)
and the following offers even more functionality:
http://www.codeproject.com/KB/dialog/OpenFileDialogEx.aspx
If someone else has found or created a better solution, please let me know.
I found a couple of solutions:
http://www.codeproject.com/cs/miscctrl/FileDialogExtender.asp (C#)
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2741273&SiteID=1&mode=1 (same as above only in VB.NET)
and the following offers even more functionality:
http://www.codeproject.com/KB/dialog/OpenFileDialogEx.aspx
If someone else has found or created a better solution, please let me know.
Monday, May 12, 2008
Converting VB.NET to C# and C# to VB.NET
Here is a web site that will quickly converting VB.NET to C# or C# to VB.NET:
http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx
It is not perfect, but it does all of the grunt work and it is free.
http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx
It is not perfect, but it does all of the grunt work and it is free.
Thursday, May 8, 2008
Keeping a VB.NET Form Always on Top
In VB6, you used a Win32API call to SetWindowPos to get a form to always stay on top. This has been simplified somewhat in VB.NET. Put the following in Form_Load or other appropriate place:
Me.TopMost = True
Me.TopMost = True
Monday, April 21, 2008
DoEvents in VB.NET
I am not sure why this is so difficult to find, but if you need to do the equivalent to a VB6 DoEvents in VB.NET or even in C#:
or if you are in a form's code, it is simply:
System.Windows.Forms.Application.DoEvents()
or if you are in a form's code, it is simply:
Application.DoEvents()
Labels:
DoEvents
Thursday, April 17, 2008
Random Access with StreamReader - File Position and Seeking 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:
The FileClass is shown below:
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.
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.
Labels:
File Position,
Offset,
ReadLine,
Seeking,
StreamReader
Thursday, March 27, 2008
Finding the Temp Directory and Getting Temporary Filenames in VB.NET and C#
In a previous post, I showed how to get special directories like My Document and System32, but I also need to get the location of the Windows Temp directory and this is not covered by the SpecialFolders property (see previous post for more info on it).
Getting the Temp folder is just as simple, but it is done with a different property:
You can also generate temp filenames with:
Getting the Temp folder is just as simple, but it is done with a different property:
tempPath = System.IO.Path.GetTempPath
You can also generate temp filenames with:
tempFilename = System.IO.Path.GetTempFileName
Sunday, March 23, 2008
Launching Excel to view Files from VB.NET
Launching Excel from VB.NET to view a file (.xls, .csv, .etc) has a seemingly simple solution:
Process.Start("c:\temp\test.csv")
However, this simple solution has a problem. After Excel is running, it does not respond to this type of command anymore. Excel has to be closed (killed) before you can successfully call Start again with any file that is associated with Excel.
I see several different approaches to this problem:
http://vbnetsample.blogspot.com/2007/08/start-and-kill-process.html
http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic17364.aspx
http://www.devx.com/dotnet/Article/7914
There is also a totally different approach using Excel's automation to open the file:
http://www.webmaster-talk.com/net-programming-forum/85020-open-excel-file-in-vb-net.html
http://support.microsoft.com/default.aspx/kb/301982
http://support.microsoft.com/kb/302094
http://www.thescripts.com/forum/thread348936.html
Process.Start("c:\temp\test.csv")
However, this simple solution has a problem. After Excel is running, it does not respond to this type of command anymore. Excel has to be closed (killed) before you can successfully call Start again with any file that is associated with Excel.
I see several different approaches to this problem:
http://vbnetsample.blogspot.com/2007/08/start-and-kill-process.html
http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework.windowsforms/topic17364.aspx
http://www.devx.com/dotnet/Article/7914
There is also a totally different approach using Excel's automation to open the file:
http://www.webmaster-talk.com/net-programming-forum/85020-open-excel-file-in-vb-net.html
http://support.microsoft.com/default.aspx/kb/301982
http://support.microsoft.com/kb/302094
http://www.thescripts.com/forum/thread348936.html
Exporting ListView to CSV File in VB.NET
I have posted an article on copying a ListView to the Windows Clipboard, but I have also found it useful to export a ListView directly to a .CSV file (comma separated value file). The process to go from a ListView to the clipboard or to a CSV file is similar.
There are number of rules for creating a CSV file. Here is a good place to look if you want to see them all. I have simplified the process to a few rules that will work for most cases. I put quotes around all values and column names. Technically, this is not required, but by putting them around all cases eliminates the need to determine if you need them or not. I also replace any quote in the data with a double quote.
You may want to get the file name from the user and automatically open the file in Excel too. Here is an example of how to do that:
There are number of rules for creating a CSV file. Here is a good place to look if you want to see them all. I have simplified the process to a few rules that will work for most cases. I put quotes around all values and column names. Technically, this is not required, but by putting them around all cases eliminates the need to determine if you need them or not. I also replace any quote in the data with a double quote.
Public Function ExportListViewToCSV(ByVal filename As String, ByVal lv As ListView) As Boolean
Try
' Open output file
Dim os As New StreamWriter(filename)
' Write Headers
For i As Integer = 0 To lv.Columns.Count - 1
' replace quotes with double quotes if necessary
os.Write("""" & lv.Columns(i).Text.Replace("""", """""") & """,")
Next
os.WriteLine()
' Write records
For i As Integer = 0 To lv.Items.Count - 1
For j As Integer = 0 To lv.Columns.Count - 1
os.Write("""" & lv.Items(i).SubItems(j).Text.Replace("""", """""")+ """,")
Next
os.WriteLine()
Next
os.Close()
Catch ex As Exception
' catch any errors
Return False
End Try
Return True
End Function
You may want to get the file name from the user and automatically open the file in Excel too. Here is an example of how to do that:
Public Sub TestExportToCSV()
Dim dlg As New SaveFileDialog
dlg.Filter = "CSV files (*.CSV)|*.csv"
dlg.FilterIndex = 1
dlg.RestoreDirectory = True
If dlg.ShowDialog = Windows.Forms.DialogResult.OK Then
If ExportListViewToCSV(dlg.FileName, ListView1) Then
Process.Start(dlg.FileName)
End If
End If
End Sub
Saturday, March 15, 2008
Creating Events for a Class in VB.NET
I have found the ability to create and raise events in a class to be a very useful feature of .NET. It also turns out to be very easy to implement.
I could provide an example here, but I will instead point to a good example I have found:
http://www.devsource.com/c/a/Using-VS/Using-Class-Events-in-VBNet/
I could provide an example here, but I will instead point to a good example I have found:
http://www.devsource.com/c/a/Using-VS/Using-Class-Events-in-VBNet/
Comparing Objects (Pointer Equality) in VB.NET
It was not readily obvious to me how to compare references (pointers) to an object to see if both references are pointing to the same object in VB.NET.
The specific example that raised this question for me was the need to see if a reference pointing to a ToolStripMenuItem object was in a list of ToolStripMenuItem objects:
Private m_itemList As New Generic.List(Of ToolStripMenuItem)
.
.
.
Private Function GetItemPosition(ByVal item _
As ToolStripMenuItem) As Integer
For i As Integer = 0 To m_itemList.Count - 1
' If m_itemList(i)=item Then ' This doesn't work
If Object.ReferenceEquals(m_itemList(i), item) Then ' This does
Return i
End If
Next
Return -1
End Function
You can't just directly compare the references. You will get an error message that says: Operator '=' is not defined for types 'System.Windows.Forms.ToolStripMenuItem' and 'System.Windows.Forms.ToolStripMenuItem'. But there is a simple, if not readily obvious to me, solution. Just use the Object.ReferenceEqual method:
If Object.ReferenceEquals(item1, item2) Then
.
.
.
End If
The specific example that raised this question for me was the need to see if a reference pointing to a ToolStripMenuItem object was in a list of ToolStripMenuItem objects:
Private m_itemList As New Generic.List(Of ToolStripMenuItem)
.
.
.
Private Function GetItemPosition(ByVal item _
As ToolStripMenuItem) As Integer
For i As Integer = 0 To m_itemList.Count - 1
' If m_itemList(i)=item Then ' This doesn't work
If Object.ReferenceEquals(m_itemList(i), item) Then ' This does
Return i
End If
Next
Return -1
End Function
You can't just directly compare the references. You will get an error message that says: Operator '=' is not defined for types 'System.Windows.Forms.ToolStripMenuItem' and 'System.Windows.Forms.ToolStripMenuItem'. But there is a simple, if not readily obvious to me, solution. Just use the Object.ReferenceEqual method:
If Object.ReferenceEquals(item1, item2) Then
.
.
.
End If
Friday, March 14, 2008
Tooltips in VB.NET
One nice feature of VB.NET is the ease in which you can implement tooltips for any Control on the desktop (unfortunatley not for .NET CF, see here).
Define a global variable for the tooltip object:
Dim g_toolTip As ToolTip = Nothing
Initialize the tooltip object. There are several settings that can be initialized too:
g_toolTip = New ToolTip()
g_toolTip.AutoPopDelay = 5000
g_toolTip.InitialDelay = 1000
g_toolTip.ReshowDelay = 500
g_toolTip.ShowAlways = True
When you are ready to display a tooltip, you must specify the control that the tooltip is associated with (ctrl in my example). The control is any object derived from Control, so if you make your own .NET control (deriving it from the Control base class), it can be associated with the tooltip. You can also use existing controls like Button and PictureBox.
g_toolTip.SetToolTip(ctrl, "tooltip text")
g_toolTip.Active = True
This functionality is actually documented pretty well in the Microsoft documentation. There are also C# example and detailed descriptions of the options like AutoPopDelay.
Define a global variable for the tooltip object:
Dim g_toolTip As ToolTip = Nothing
Initialize the tooltip object. There are several settings that can be initialized too:
g_toolTip = New ToolTip()
g_toolTip.AutoPopDelay = 5000
g_toolTip.InitialDelay = 1000
g_toolTip.ReshowDelay = 500
g_toolTip.ShowAlways = True
When you are ready to display a tooltip, you must specify the control that the tooltip is associated with (ctrl in my example). The control is any object derived from Control, so if you make your own .NET control (deriving it from the Control base class), it can be associated with the tooltip. You can also use existing controls like Button and PictureBox.
g_toolTip.SetToolTip(ctrl, "tooltip text")
g_toolTip.Active = True
This functionality is actually documented pretty well in the Microsoft documentation. There are also C# example and detailed descriptions of the options like AutoPopDelay.
Sunday, March 9, 2008
Color Selection Dialog in VB.NET
The Color Selection Dialog for VB.NET (and C# would be similar) is fairly easy to do if you have and example:
VB.NET
Dim colorValue As Color = Color.Red
Dim dlg As New ColorDialog
dlg.Color = colorValue
If dlg.ShowDialog() = DialogResult.OK Then
colorValue = dlg.Color
End If
For VB6, here is one way to do it:
http://www.devx.com/vb2themax/Tip/19257
VB.NET
Dim colorValue As Color = Color.Red
Dim dlg As New ColorDialog
dlg.Color = colorValue
If dlg.ShowDialog() = DialogResult.OK Then
colorValue = dlg.Color
End If
For VB6, here is one way to do it:
http://www.devx.com/vb2themax/Tip/19257
Labels:
color dialog,
color picker,
color selection
Monday, March 3, 2008
Tooltips with the .NET Compact Framework
I have been looking for a way to support Tooltips in .NET CF like I do on the desktop with the Tooltip object. There must be something better out there that I just haven't come across. Please post a comment if you know of something.
This is the only thing I have found that is reasonably close to what I want, but it is still not what I really want (wich is the Tooltip object from the desktop):
Here is the full posting from the Windows Mobile Team Blog:
http://blogs.msdn.com/windowsmobile/archive/2005/02/15/373120.aspx
The source code for the control is:
http://www.marcusperryman.members.winisp.net/blogstuff/tooltipCF.zip
The example project that uses it is:
http://marcusperryman.members.winisp.net/BlogStuff/smartdeviceapplication3.zip
This is the only thing I have found that is reasonably close to what I want, but it is still not what I really want (wich is the Tooltip object from the desktop):
Here is the full posting from the Windows Mobile Team Blog:
http://blogs.msdn.com/windowsmobile/archive/2005/02/15/373120.aspx
The source code for the control is:
http://www.marcusperryman.members.winisp.net/blogstuff/tooltipCF.zip
The example project that uses it is:
http://marcusperryman.members.winisp.net/BlogStuff/smartdeviceapplication3.zip
Thursday, January 3, 2008
Determine your current Screen Orientation on a Windows Mobile Device
There are many facets of "orientation-aware" apps. There are 2 portrait and 2 landscape modes making 4 possible orientations (0, 90, 180, 270).
I have an application that lets the user set custom keys in an application. At first, I thought I only need to store a landscape set and a portrait set; however, depending on the user, the landscape mode might be in the 90 degree position or the 270 degree position. The keys selected by the user may be very different depending on which one of these orientations gets used.
However, it is very simple to find out what the current screen orientation in on the device:
Imports Microsoft.WindowsCE.Forms
.
.
.
Select Case SystemSettings.ScreenOrientation
Case ScreenOrientation.Angle0
.
.
.
Case ScreenOrientation.Angle90
.
.
.
Case ScreenOrientation.Angle180
.
.
.
Case ScreenOrientation.Angle270
.
.
.
End Select
More Info at:
http://msdn2.microsoft.com/en-us/library/microsoft.windowsce.forms.systemsettings.screenorientation(VS.80).aspx
I have an application that lets the user set custom keys in an application. At first, I thought I only need to store a landscape set and a portrait set; however, depending on the user, the landscape mode might be in the 90 degree position or the 270 degree position. The keys selected by the user may be very different depending on which one of these orientations gets used.
However, it is very simple to find out what the current screen orientation in on the device:
Imports Microsoft.WindowsCE.Forms
.
.
.
Select Case SystemSettings.ScreenOrientation
Case ScreenOrientation.Angle0
.
.
.
Case ScreenOrientation.Angle90
.
.
.
Case ScreenOrientation.Angle180
.
.
.
Case ScreenOrientation.Angle270
.
.
.
End Select
More Info at:
http://msdn2.microsoft.com/en-us/library/microsoft.windowsce.forms.systemsettings.screenorientation(VS.80).aspx
Detecting Screen Orientation Changes in Windows Mobile Apps
If you are working on a Windows Mobile application, you probably need to be orientation-aware. If the user changes the screen from portrait to landscape or vice versa, you may need to do something based on this change.
The Resize event for the form will tell you when an orientation change has occured. You will probably have to use the me.Width and me.Height to know how it was changed. Look at the If statement in the UpdateButtonLayout sub below.
Private Sub Form_NumberEntry_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
UpdateButtonLayout()
End Sub
Private Sub UpdateButtonLayout()
Dim ratio As Double = CInt(Me.Width) / CDbl(Me.Height)
If ratio <= 0.9 Then ' portrait .
.
.
Else ' landscape
.
.
.
End If
End Sub
Being orientation away for control may be as simple as using the Anchor and Dock properties on the control, but there are many times, that this is not sufficient or that you need to do something else like auto fit columns in a listview.
The Resize event for the form will tell you when an orientation change has occured. You will probably have to use the me.Width and me.Height to know how it was changed. Look at the If statement in the UpdateButtonLayout sub below.
Private Sub Form_NumberEntry_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
UpdateButtonLayout()
End Sub
Private Sub UpdateButtonLayout()
Dim ratio As Double = CInt(Me.Width) / CDbl(Me.Height)
If ratio <= 0.9 Then ' portrait .
.
.
Else ' landscape
.
.
.
End If
End Sub
Being orientation away for control may be as simple as using the Anchor and Dock properties on the control, but there are many times, that this is not sufficient or that you need to do something else like auto fit columns in a listview.
Subscribe to:
Posts (Atom)