Wednesday, December 17, 2008

Utility: Process Explorer

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.

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

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

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

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

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

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

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.

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.

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

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

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/

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

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.

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

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

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

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.

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

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);

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.

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

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

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

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

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

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.

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.

control.BackColor = Color.FromKnownColor(KnownColor.Control)


I found this on:

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

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

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.

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.

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:

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
Here is another article on using SpecialFolders:

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.

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

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.

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.

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

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#:

System.Windows.Forms.Application.DoEvents()

or if you are in a form's code, it is simply:
Application.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:



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.

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:

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

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.

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/

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

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.

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

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

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

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.