Saturday, May 27, 2006

C# programming for the Compact Framework part 2

If you followed the steps from part 1 you've created a .NET CF program that runs on your PocketPC. No doubt you also tried to add functionality to the basic program, and soon found out that it isn't all good clean fun.
First, whenever you add a control from the sidebar, the IDE automatically adds a new reference to the required .NET assembly so the compiler complains about 'duplicates' and will not compile untill you remove the reference. This is not a real big problem, just don't forget to remove it before you compile. Also when you add controls by just copying them from the form (select the control you need, press [Ctrl]C and [Ctrl]V to add a copy) the IDE does not add a new reference.
Second, and this is worse, whenever you change something on the form, the IDE re-creates the form.designer.cs file, and all the CF-incompatible lines you just removed are back. So I created a little program (in C# ofcourse) that walks throught all .designer. files in a directory, finds lines with unsupported CF statements and turns them into comment. You can find it here.
Actually it loads a file named 'Exclude.txt' that contains the unsupported statements, and checks every line in the source code to see if it contains on of the words in the Exclude-file. If a match is found AND the source code line is not already a comment, the line is turned into a comment by adding '//' at the beginning of the line. I agree it's a rather crude solution, but it works fine. So if we enter this program in the 'Project->Project Options->Build Events' page as the 'Pre-build event', it is executed every time when we compile our code from the IDE, and there will be no error messages like 'System.Windows.Form.ComponentX does not contain a definition for MethodY'
Since the CFPreprocessor program is very basic, you should take care of the following:
- If the pre-build event is configured as shown above, the CFPreProcessor.exe file must be in the 'bin\Debug' directory of the project to be compiled, because this is the default directory when the compiler starts. It's probably better specify the full path (E.G. C:\CF\CFPreprocessor.exe)
- There are no warning messages in the IDE when the program runs or fails. It just writes a 'CFPreprocessor.log' file with each run, so if you think something is going wrong, just open this file to see what happened.
- Just add things to the Exclude.txt file if you run into another unsupported feature. I first considered it an option create a full list of unsupported methods from the 'Compact Framework Helpfile', but I think the program will soon get very slow, since it will have to check every line of code against every line in the Exclude file. I think it is best to keep this file as short as possible.

Another issue when programming for the CF is that it is really 'compact', so apart from the unsupported methods there are also a lot of controls that are not supported at all. In general you should stick to the the very basic Windows controls like Button, TextBox, Label, CheckBox, ComboBox etc. Anything more advanced or fancy, like MaskedTextBox, RichTextBox, CheckedListBox is probably not suported. It is good practice to check the .NET help first before entering any control, and see if it is supported.

Thursday, May 25, 2006

C# programming for the Compact Framework

As always when you want to try a new technique or programming language, it works best if you have a goal. Just writing 'a program' , or re-typing exercises from books seldom gets me excited. So when I found out that .NET 2.0 finally contains a native Serial port control, I decided to create a terminal program for use on the Pocket PC. Since I often work with instruments that send (binary) data on a serial port, it's someting I wanted to have for a long time.
As mentioned before, the SharpDevelop 2.0 IDE is a very good environment for creating C# programs, but unfortunately it has no direct support for the Compact Framework. Yet it's not too dificult to get a simple Windos Forms application running on a Pocket PC with CF 2.0 installed.
First you must have the CF2.0 installed on your pc, and you should also install the Windows Mobile 5.0 SDK. If you did this, you can find the CF assemblies in: C:\Program Files\Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE
(At least, that's where they are on my computer.)
For convenience you can copy them to a root folder like C:\CF (like me), but you can also keep them where they are.
For the first try, keep it simple. Just create a new Windows Application from the File->New->Solution menu. Name it something like 'CFTest'. The designer presents an empty form, that's probably too large to fit on the screen of the Pocket PC, so resize it to 240 x 320 (the standard screen resolution for a Pocket PC) and place a button and label on it. You can also add an event handler to the button that for example changes the text of the label so you can check if the program is actually working.
Now you can compile and run it, just to see if this standard program works.
If so, it's time to change the settings so we can compile the same program for the CF.
First open the View->Projects window, and open the 'References' section on the project tree. This will contain the default assembly references for a standard windows project. When you right-click on each assembly you get the 'Open, Remove, Properties' option as show here. Since all these references now point to the 'full' framework versions, you must delete them from the list. Click on each item, and choose 'Remove' untill the list is empty. Now right click the 'References', and select 'Add reference'. In the 'Add Reference' window, select the '.NET Assembly Browser' tab and click 'Browse'. Navigate to the folder with the CF assemblies (as shown above), and select all files with the .DLL extension. After closing the assembly browser by clicking OK, the Reference section in your project view should now contain only references to the CF assemblies. Note that one of the dll's is named 'mscorlib.dll'. This is the core library of the framework, and you might have noticed that it was not referenced in the standard project. This is because the compiler references this library automatically since it is always required for a .NET application. Unfortunately this means it always uses the default mscorlib.dll, which on a desktop computer, always belongs to the standard .NET library. To stop this unwanted behaviour we have to change the compile settings. Select Project->Project Options, and select the 'Compiling' tab. Here you can (and must) select [x]Do not reference mscorlib.dll.
Now it's time to Run the program again, just to see that we end up with a disencouraging long list of errors. But this is actually the nice part. All errors are related to functions or properties that are unavailable in the Compact Framework, and these lines can just be removed (or better yet, commented out) without breaking the basic functionality of the program. So just click on each line of the error list to take you to the 'unsupported' line, and turn this line into a comment. Yes, even the [STAThread] directive at the beginning of the main program can be removed.
Now Run the program again, et voila.. it works. It actually still looks identical to the first run. But now you can copy the executable you just created to a Pocket PC, and it will run exactly like on your desktop.