Monday, August 22, 2005

Convert Unix Time

Quick, easy way to convert unix time online:

http://www.onlineconversion.com/unix_time.htm

VS2005 Launch Date

November 7th is the target launch date of Visual Studio 2005.

Sunday, August 14, 2005

Cool Designer Trick for Panels

As far as I know, the VS2005 "Designer Tool" cannot be used with the System.Windows.Forms.Panel class. This can be utterly frustrating when doing layout. So, what I do instead is, first, rename my System.Windows.Forms.Panel derived class to extend System.Windows.Forms.Form. Now I can do my layout with the handy visual "Designer Tool" -- e.g. I right click on the source code and select "View Designer." Once I'm done adding widgets/controls and laying them out, I rename the .Form back to .Panel. Tada!

Wednesday, August 03, 2005

Curiosities of Control.Invoke...

I wrote about Control.Invoke(Delegate) once before with regards to the .NET CF restriction that the delegate must be an instance of the EventHandler. See the original post.

I was always curious though about Control.Invoke and whether or not it would act in a comparable manner to firing an event in the normal way (e.g. myEvent(this, EventArgs.Empty)). Is Control.Invoke essentially the same thing? The only obvious difference being that the event execution is transferred to the thread that owns the control's underlying window handle.

I finally got around to writing a little test util to verify its behavior. My strange conceptual suspicions/thoughts about what it might do were laid to rest and the reality has taken its place. Control.Invoke on an event delegate with multiple subscribers will iterate through each subscriber and fire the event (just as if you fired the event yourself -- in the non-Invoke manner).

Voice gets precedent

In the battle of voice vs. data, voice always wins. It looks like the SmartPhone got it right. If you are currently on a phone call and your app attempts to use GPRS, you receive the following message:

"Error - Unable to place a data call while a voice call is in progress. When the voice call has ended, try again."

Command Line Tools for Windows CE

A collection of tools to do many things to a windows CE device via Activesync/RAPI.These tools should work on most CE devices, tested on Ipaq, XDA(Wallaby), XDA-II(Himalaya), XDA-IIs(Blueangel), MDA Compact(Magician), i-mate SP3, i-mate SP3i, Yakumo P300, MPx200, Voq, Mitac Mio, Mitac Megas. with PocketPC 2002, PocketPC 2003, Windows Mobile 2003, Windows Mobile 2003 Second Edition, Smartphone 2002, Smartphone 2003. ( wince 3.0 and wince 4.2 )

Note, that when running on a smartphone, you have to sign itsutils.dll


link: http://www.xs4all.nl/~itsme/projects/xda/tools.html

Where is the phone number stored on the SmartPhone?

We've been looking into this issue lately and there are a number of solutions floating around the web. A colleague of mine in the lab has even written a utility to dump SIM storage memory and look for the mobile phone's number. Of course, you could always use the SmsGetPhoneNumber API in the SmartPhone SDK but that's not always guaranteed to work either.

From Hung Dang at Microsoft,

You can query the phone number from the device with the SmsGetPhoneNumber API (see Smartphone 2003 SDK). Note that not all SIM's contain the phone number, so you cannot always get the phone number.

Google Groups link.

Sunday, July 31, 2005

Remove mMode Icon from Home Screen

Here's how you can remove the mMode Icon from your SMT5600 SmartPhone home screen.

1. Download a SmartPhone registry editor, I suggest this one.
2. Open the registry editor and look for the path:
\HKEY_LOCAL_MACHINE\SOFTWARE\AT&T\PluginFavorites
3. Double click on "Order" and remove the mMode.lnk, then click OK.

4. Now we need to find a .lnk to replace mMode.lnk. Open up \HKEY_CURRENT_USER\Software\Microsoft\Shell\StartMenu to see a list of .lnk replacements. In this case, I will choose "Call History.lnk"
5. Go back to \HKEY_LOCAL_MACHINE\SOFTWARE\AT&T\PluginFavorites and add this new .lnk

6. Restart your phone.

Friday, July 29, 2005

C# Set Cursor Position in Textbox

How does one go about setting the cursor position in a .NET CF TextBox?

You use a combination of the TextBox.SelectionStart and TextBox.SelectionLength.

For example,

private void textBox1_GotFocus(object sender, System.EventArgs e)
{
textBox1.SelectionStart = 5;
textBox1.SelectionLength = 0;
}


from groups.google.

C# String Formatting Resources

Here are two incredibly useful string formatting resources, including how to do variable-width string alignment in C#.

1. http://www.stevex.org/CS/blogs/dottext/articles/158.aspx
2. http://www.codeproject.com/books/0735616485.asp

Sunday, July 24, 2005

Thread Safe Singleton

Typical WinForms applications are typically running in the UI thread, so the simple singleton will provide you with the functionality that you're looking for. However, if you are creating a multi-threaded application that needs to access a singleton across all of its threads, then you will need to create a thread-safe singleton class instead. What you gain in functionality comes at the cost of some performance, so you shouldn't use this form of the class unless you actually intend to use the class from multiple threads.

Thread Safe Singleton Code

Saturday, July 23, 2005

No Thread.Abort() in .NET CF 1.0

You cannot call Thread.Abort() in .NET CF 1.0, so how do you close/stop a thread?

See this HOWTO on msdn for a workaround.

Friday, July 22, 2005

Obtaining Memory Status w/C#

6.5. How do I determine how much memory a device has available?

You can P/Invoke the GetSystemMemoryDivision and GlobalMemorySystem functions to determine how the memory is divided and allocated between program and storage. Definitions of the parameters can be found in the API reference documentation.

from our friendly Smart Client Developer FAQ on msdn.

Control.Invoke System.ArgumentException

Even though I'd read this before, I'd forgotten about it and it caused me a slight headache today. If you call Control.Invoke on a custom event delegate which is not EventHandler, you will receive a System.ArgumentException.

From msdn,

Platform Note: In .NET Compact Framework applications, the delegate must be an instance of EventHandler. For an example, see How to: Use a Custom Delegate.

Efficiently Counting Lines in a File

Fast absolute, and statistical line counting algorithms for use with progress notification by Justin Rogers.

Creating a multi-form app on SmartPhone

Creating a Multiple Form Application Framework for the Microsoft .NET Compact Framework by Chris Tacke on msdn.

Thursday, July 21, 2005

Where art thou Java iterators?

So the C# equivalent to the Java iterator is the "Enumerator" class. As much as I like the foreach block and simple iteration in C#, I miss the ability to delete items from my collections while I traverse them like I can do in Java.

MSDN has an article (and slight fix/kludge) about this,

When this code is run, it generates an exception because you can't modify a collection while you're enumerating over it. That's a pretty good idea since you usually don't want collections to change underneath you, but it's sometimes annoying.

This got me thinking, and I realized that what was needed was a class that would isolate the enumeration from the collection. This class would do a full enumeration over the collection and store the data away to expose its own enumerable object. Changing the collection while using that object would be okay.

Logging on the SMT5600

I'm currently exploring ways to integrate logging into my application. I noticed that .NET Framework 2.0 has a class called Microsoft.Build.Utilities.Logger however this isn't available for .NET CF 2.0 much less .NET 1.0. Through a somewhat brief google driven investigation, I've determined that log4net appears to be the standard and, as the name implies, isn't much different from log4j and like that java library, is also an Apache OSS project. There are also other, less dramatic options.

For example, Neil Cowburn talks about ultra-simple application logging, though it does require P/Invoke.

This is a really cool technique that you can use to add simple logging/tracing functionality to your .NET Compact Framework apps. In Windows CE, there is a Win32 API which goes by the moniker of SetStdioPathW. By calling this API, you can redirect standard input, output and error output. The cool thing about this is that you can actually redirect the I/O to a text file! By redirecting standard output like this, you can scatter Console.WriteLine()'s all throughout your code and hey presto! Instant instrumentation. (link)

There is also nspring written by Jeff Varszegi, which seems to be a fairly complete logger he wrote by himself in ~1 month. You can read about it here.

.NET CF 2.0 Performance

Very interesting read here by the Microsoft .NET Compact Framework Team on .NET CF 2.0 performance. Not sure how relevant this is to those of us still developing in 1.0 -- but interesting nonetheless.

Wednesday, July 20, 2005

No Linked Lists in C# 1.0, 1.1

Argh, no linked lists in C#. They do have this in .NET 2.0 however, in the form of Generic Linked Lists.

Monday, July 18, 2005

My Classes Are Sealed

Continuing the theme tonight of talking about new C# keywords and language implementations (and comparing them to Java), I would be remiss if I didn't mention the keyword "sealed."

By marking a class "sealed" you prevent other classes from deriving from it. A sealed class, then, is sort of a one off. In contrast, you could also mark a class abstract (just like in Java -- behaves the same way too), which means that the class is made to be derived and cannot be instantiated itself.

readonly vs. const

I came across the "readonly" keyword haphazardly when I attempted to mark a static member variable as const. This is not possible in C#. Instead, use "readonly."

Please, Let Me Keep My Unassigned Variables

If you compile code in C# that contains uninitialized variables, you will receive a compilation error in VS. C# imposes definite assignment, which requires that all variables be assigned before they are used (from Programming C#). I typically resolve this by assigning my object vars to null or, in the case of primitives, something like int.MaxValue or -1.

Enumerations

When I first learned programming it was difficult for me to perceive the importance of enumerations (i.e. enum in C++). Then I moved from C++ to Java and I missed them. Now, with C#, enumerations are back... and the sweet thing about them is you can print them or add them to a string and their declaration name prints out instead of their value.

For instance,

enum Choice
{
Yes = 1,
No = 2
}


String strChoice = "Does Ian Smith actually like Debbie Gibson? " + Choice.Yes;

actually prints out, "Does Ian Smith actually like Debbig Gibson? Yes"

cool, no?

(PS, you c++ types should note that you don't have to follow the closed bracket with a semi-colon -- ahhh, feel the Java influence)

C# Entry Point

One thing that I found useful in Java was the ability to declare multiple static void main(string [] args) functions in different classes. This made it easy to setup simple test code. It's technically possible to do the same thing in C#; however, in this case you must use the /main command line switch to tell C# which class contains the Main method you'd like to execute.

Properties

I like Properties in C#, I think it begins to better define that space of functionality within a class that is not really a method but shouldn't just be a public member. In fact, according to MSDN protected instance fields and public instance fields should be used sparingly in C#.

A property is preferable to using a protected or public instance field.

From here.

I think this decoupling is good. It provides another layer of abstraction and allows the class designer to be a bit clever about what they expose and how they expose it.

Interestingly, I just found out that in addition to placing an access modifier on the Property itself, you can also apply one individually to the get/set. So, you could expose the "get" publically but make the set protected. For example,

public Size Size
{
get{ return _size; }
protected set { _size = value; }
}

I should mention that in my short experience with using interfaces in C#, I don't believe that it is possible to declare an access modifier on a Property (or its accessors) in an interface.

Saturday, July 16, 2005

Creating a Splash Screen

Two links from msdn:

1. Creating a Splash Screen Form on a Separate Thread
2. Crafting Smartphone User Interfaces Using .NET Compact Framework

Overview of .NET Compact Framework Garbage Collection

What are the ramifications of calling GC.Collect()?

You’ve probably heard the old wisdom “Yes, there is an API you can use to force a garbage collection, but don’t ever call it – the garbage collector can do a better job on its own”. Here’s the thinking behind that statement:
Garbage collection is a relatively expensive operation. As we’ve seen, a collection involves “suspending” threads, traversing object graphs, moving blocks of memory around and so on. Each time you force a collection, you’re forcing the Compact CLR to, at a minimum, get all threads to a state in which a collection can start, and scan the object graph looking for unused objects. Clearly, calling GC.Collect() repeatedly will have a seriously negative performance impact. The Compact Framework’s collector will kick in automatically after 750KB of objects have been created. As such, collections do happen occasionally - they don’t only happen when memory is exhausted. Furthermore, when a call to GC.Collect() returns, you can’t be guaranteed that all object finalizers have finished running. As a result, you cannot force a collection in hopes of deterministically finalizing a particular object (use the Dispose pattern to deterministically free resources associated with an object). That said, it is possible that you may have a scenario in which you’ll benefit by initiating collections yourself. If you believe you have such a scenario, feel free to try it, but be aware of the implications and measure performance carefully to make sure you’re not doing more harm than good.


from Steven Pratschner's .Net CF WebLog - link to above article can be found here.

Friday, July 15, 2005

MenuItem.MenuItems.Clear NotSupportedException

When I call myMenuItem.MenuItems.Clear() during runtime, I get a

"An unhandled exception of type 'System.NotSupportedException' occurred in System.Windows.Forms.dll

Additional information: NotSupportedException"

This same error occurs if I call myMenuItem.MenuItems.Remove(menu_i) in a for loop at the point when myMenuItem.MenuItems.Count is down to 1. I can remove all menu items up until that point successfully.

I posted to forums.microsoft.com here.

Sunday, July 10, 2005

Native Interoperability

To do really cool stuff on the SMT5600, sometimes it's necessary to use native code and the P/Invoke functionality. MSDN has some pretty good articles on native interoperability with the .NET Compact Framework.

Here are a select few that interest me:

For a good introduction into this world, download the sample P/Invoke Library solution and source code for C# and VB. Note however that this code is for Pocket PC 2003, rather than SmartPhone.

Friday, July 08, 2005

OpenNET CF SDF 1.3 Installation Failure

I just downloaded OpenNETCF Smart Device Framework 1.3 and was unpleasantly surprised by the following installer error ("Object reference not set to an instance of an object").


Others are apparently having this problem as well (here, here and here). I also attempted installation on my laptop, which resulted in the same error. I was looking forward to playing around with the various OpenNET CF offerings -- it's unfortunate that their installer is plagued with bugs.

Platform Invoke List!

Daniel Moth points to various P/Invoke listings on the web:

Every .NET developer is familiar with platform invocation services (PInvoke), the ability to call native functions declared in dlls via the DllImport attribute. In the early .NET days it was common to see queries about specific API declarations, but 4 years down the road you would have thought people would stop asking and instead use the ready-made ones easily found all over the web. This blog entry is proof of the opposite and it will serve as my pointer next time someone requests a particular Win32 DllImport declaration.

(link)

More Useful Blogs

Added Peter Foot's blog to the list of blogs on the sidebar. He is a .NET Compact Framework Microsoft MVP, opennetcf.org developer, and overall .NET CF guru.

Also added the Windows Mobile Team Blog to the sidebar.

As well as Daniel Moth's blog -- another .NET Compact Framework Microsoft MVP.

Numeric Textbox

No easy way to make a "numbers" only TextBox with .NET CF on the SmartPhones. There are two easy ways of adding this, one simply traps keypresses on a custom TextBox and the other uses Platform Invoke.

(1) from http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=47854

// in InitializeComponents, add this event handler.
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.NumbericTextValidator);

// now this is the event handler's method.
private void NumbericTextValidator(
object sender,
System.Windows.Forms.KeyPressEventArgs e)
{
if ("0123456789".IndexOf(e.KeyChar) > -1)
e.Handled = false;
else
e.Handled = true;
}

(2) http://www.devx.com/wireless/Article/21291/1763

This solution uses Platform Invoke, which has the advantage of actually changing the text input mode icon in the upper right hand corner of the SMT5600 (e.g. T9, abc, 123, etc.).

(3) Something similar over at opennetcf.org.

Update (April 24th, 2006): In .NET CF 2.0 this is easy.
For CF 2.0 (Windows Mobile 5.0 Smartphone):
using Microsoft.WindowsCE.Forms; //at the top
InputModeEditor.SetInputMode(textBox1, InputMode.Numeric); //somewhere in your code

(from link)

Play An Alert Sound w/.NET CF

Unfortunately it looks like there is no easy way to play an audible beep or alert in .NET CF --Console.Beep() is unsupported:( To be fair, this is not necessarily an issue with the CompactFramework, but infact, affects all of .NET 1.0. From the level of posts on newsgroups/forums, it has been duly noted by Microsoft and supposedly .NET 2.0 has a sound player control. Of course, this doesn't help those of us stuck with .NET CF 1.

Here is what information I gathered in a preliminary investigation:

1. A .NET example from codeproject that plays .Wav files (http://www.thecodeproject.com/cs/media/PlaySounds1.asp)
2. No simple playsound or beep function (http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=26126)

Force Form to Top Level Focus

My .NET Compact Framework application requires that, from time to time, the user gets audibly alerted and a messagebox or form is displayed (using the System.Threading.Timer). Unfortunately, I have been unable to get my Form to display over the home screen. I have tried:

this.Focus();
this.Visible = true;
this.Show();

All in various combinations. I've found a few solutions about this on the web (I haven't tried either yet).

(1)
[DllImport("coredll.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd );
[DllImport("coredll")]
public static extern IntPtr FindWindow(string className, string wndName);
this.Show();
IntPtr hwnd = FindWindow(null, this.Text);
SetForegroundWindow(hwnd );

A full example can be found here.

(2)
If you need to fix your form at the top of the z-order, then rather than continually pulling the window to the front, use SetWindowPos (you'll need to P/Invoke) with the HWND_TOPMOST flag. This will keep your form at the top even if it loses focus. See the code for OpenNETCF.Win32.Win32Window for P/Invoke declaration:-http://vault.netcf.tv/VaultService/VaultWeb/GetFile.aspx?repid=2&path=%24%2fSDF%2fOpenNETCF.Windows.Forms%2fWin32%2fWin32Window.cs&version=2(username guest, password guest)

Thursday, July 07, 2005

Controls.Add ArgumentException

When executing this rather innocuous line of code within a System.Windows.Forms.Form:

this.Controls.Add(new Label());

I get this cruel, indescript error:


Note that I get the error no matter what type of Control I try to add (e.g. TextBox, ListView, etc.). Unfortunately, this is the worst type of error because the Exception can't be easily searched via Google.

My hunch at the moment is that this Exception is indicative of something more wrong than an ArgumentException (particularly because I KNOW that the argument is correct). The method that contains this Control.Add function is called by an event triggered by a Timer thread, I suspect that this could be the root of the problem. I found a post in the .NET newsgroups stating that manipulating a Windows Form from another thread is highly hazardous.

Update July 8th, 2005 12:29AM: I found out more information about the underlying problem here. From Code Project,

.NET allows you to call System.Windows.Forms.Control functions only from the thread in which the control was created. To run them from another thread we need to use the Control.Invoke (synchronous call) or Control.BeginInvoke (asynchronous call) functions.

Aha, now we're on the right track. However, note that .NET Compact Framework 1.0 does not support Control.BeginInvoke (although .NET CF 2.0 does). That's fine though. I created my own delegate and tried this on my own -- something really simple like public delegate void MyDelegate(); But then what do you know, I get the exact same System.ArgumentException as before but now when I call MyForm.Invoke(MyDelegate). It took me forever to track down why because it's in very small print in the MSDN API for the Control.Invoke method (and I missed it quite a few times):

Platform Note: In .NET Compact Framework applications, the delegate must be an instance of EventHandler. For an example, see How to: Use a Custom Delegate.

So, you can't use your own delegate, it has to be an instance of EventHandler. I haven't actually tried this yet because it took me roughly two hours to figure this out. I originally found out about this delegrate constraint here:

7.10. Can I create a custom delegate to pass to invoke?

No, in the .NET Compact Framework, only EventHandler methods can be invoked. The proper method for doing this is described here:

public void HandleMe(object o, EventArgs e) {...}
form.Invoke(new EventHandler(form.HandleMe));

Although the following will compile, it will not work properly:

public delegate void MyHandler();
public void HandleMeBadly() {...}
form.Invoke(new MyHandler(form.HandleMeBadly));

In fact, the HandleMeBadly code above does compile, which makes it even more confusing. If you try to run that code, you will get an ArgumentException error. Given what I know now, however, that Exception actually makes sense, as opposed to when I called this.Controls.Add(new Label()) in the non-creation thread.

Naming Conventions

People at my work are used to the Java naming conventions; C# is fairly different. For example, the guideline states that the first letter of methods and package names should be capitalized. Go here for more.

Wednesday, July 06, 2005

Update: Tab Order

Previously, I posted about tab order problems with custom controls.

I found more information about it in the .NET Compact Framework Developer's Guide (here), which says,

To tab out of the custom control to the previous control, call this.Parent.Controls(this.Parent.GetChildIndex(customcontrol) - 1).Focus() in the KeyDown event handler when a Keys.Up key is detected.

I also found this exact phrasing in the Smart Client Developer Center Home: Frequently Asked Questions (link).

5.41. How do I tab out of a custom control to the previous control?
Call this.Parent.Controls(this.Parent.GetChildIndex(customcontrol) - 1).Focus() in the KeyDown event handler when a Keys.Up key is detected.

There are multiple glaring errors with this documentation, which I find completely unsatisfactory. The code they meant to write was something more along the lines of:

this.Parent.Controls[this.Parent.Controls.GetChildIndex(customcontrol) - 1].Focus() ;

1. this.Parent.Controls returns a ControlCollection which is accessed with brackets, not parenthesis
2. this.Parent.GetChildIndex does not exist, they meant to write this.Parent.Controls.GetChildIndex

Even given these two corrections, this code is still not entirely accurate. We really don't want to try and give focus to just any Control -- in fact, some controls can't be focused (e.g. panels, labels, etc.) so using their code, in some cases, we end up with nothing being focused at all. To fix this, we could change this code to something more like this:

int index = this.Parent.Controls.GetChildIndex(customcontrol);
do{
if(index == 0)
index = this.Parent.Controls.Count; //roll over
} while(!this.Parent.Controls[--index].CanFocus());
this.Parent.Controls[index].Focus();

However, CanFocus() is not supported by the .NET Compact Framework, so instead we have to do something like this:

int index = this.Parent.Controls.GetChildIndex(customcontrol);
do{
if(index == 0)
index = this.Parent.Controls.Count; //roll over
} while(!this.Parent.Controls[--index].Focus());

In the above code, we rely on the fact that the Control.Focus method returns false if the focus request was unsuccessful to find a Control that is focusable.

Update July 6th 2005, 2:00PM: Hmm, actually, as it turns out the Control.Focus() method returns true for Controls like Label -- which is somewhat contradictory to API documentation. So, I had to change this slightly. Here is some OnKeyDown code that I wrote for the SmartPhone that provides tab control for custom controls (sorry about the formatting, if I keep writing code on this blog, I will have to get a tool that simplifies posting code and formats it nicely as well).

protected override void OnKeyDown(KeyEventArgs e){
switch (e.KeyCode)
{
case Keys.Down:
int index = this.Parent.Controls.GetChildIndex(this);
do{
if ((index + 1) == this.Parent.Controls.Count)
index = -1; //roll over
index++;
} while (!isFocusable(this.Parent.Controls[index]));
break;

case Keys.Up:
index = this.Parent.Controls.GetChildIndex(this);
do{
if (index == 0)
index = this.Parent.Controls.Count; //roll over
index--;
} while(!isFocusable(this.Parent.Controls[index]));
break;
}
base.OnKeyDown(e);
}

public bool isFocusable(Control control)
{
if(control is Label)
return false;
else
return true;
}

Tuesday, July 05, 2005

No Transformation (or any GDI+) Support

I wouldn't think so, but Google confirmed it by returning this article, .NET Compact Framework Graphics, by David Durant and Paul Yao (an excerpt from their book .NET Compact Framework Programming with C#).

This brings up another difference between the desktop .NET Framework and the .NET Compact Framework: available coordinate transformations. The desktop provides a rich set of coordinate transformations—scrolling, scaling, and rotating—through the Matrix class and the 3 × 3 geometric transform provided in the System.Drawing.Drawing2D namespace. The .NET Compact Framework, by contrast, supports no coordinate mapping. That means that, on handheld devices, application software that wants to scale, scroll, or rotate must handle the arithmetic itself because neither the .NET Compact Framework nor the underlying operating system provides any coordinate transformation helpers. What the .NET Compact Framework provides, as far as coordinates go, is actually the same thing that the underlying Windows CE system provides: pixels, more pixels, and only pixels.

SmartPhone Screen Resolution

Pocket PC:

  • Portrait / Landscape QVGA (240x320, 96 dpi)
  • Portrait / Landscape VGA (480x640, 192 dpi)
  • Square screen (240x240, 96 dpi)
  • Square screen VGA (480x480, 192 dpi)

Smartphone:

  • Portrait (176x220, 96 dpi) <-SMT5600
  • Portrait QVGA (240x320, 131 dpi)

The Audiovox SMT5600 features a TFT (Thin Film Transistor) screen, capable of displaying 65K colors. Measuring 2.2-inch-diagonally, it has a resolution of 176 x 220 px.

(from MSDN)

Monday, July 04, 2005

Reading in Files on SmartPhone Emulator

The other day I made a post on http://forums.microsoft.com about trying to load input files on the SmartPhone SE Emulator, which you can find here. The problem, of course, is trying to figure out how the SmartPhone Emulator maps a portion of the desktop file system to its file system. The response I got was,

The easiest way is to use folder sharing. Under File\Configure\General Tab set the folder sharing directory to any directory on your desktop. Put your text files into that directory and they will be accessible from "\Storage Card\" inside the Windows Mobile OS.

Though these instructions were either for VS2003 or inaccurate -- I got the point. In VS2005 you can do something similar by going to the File Menu -> Tools -> Options -> Device Tools -> Devices -> Smartphone 2003 SE Emulator -> Properties -> Emulator Options. The Emulator Options button opens a Emulator Properties dialog box. In the General tab of this dialog, you can input a "Shared folder" path, which I did (Incidentally, if you hit F1 on this tab for Help, you will note that the only function not explained in the Help is the "Shared folder"! Hmm, maybe it's supposed to be self-explanatory).

However, we're not done yet. We still have to figure out a way to refer to this "Shared folder" in your code -- This is something I have yet to figure out. I tried one thing this morning, which was to create a file programtically on the SmartPhone Emulator and see if I could find it on the desktop. I ran this simple test code:

string FILE_NAME = "MyFile.txt";
if (File.Exists(FILE_NAME))
{
Console.WriteLine("{0} already exists.", FILE_NAME);
}
StreamWriter sw = File.CreateText(FILE_NAME);
sw.WriteLine("This is my file.");
sw.Close();


After the code completed, I could not find the file anywhere on my desktop's filesystem. I also tried "\\Storage\\MyFile.txt" and "\\Storage Card\\MyFile.txt" for FILE_NAME but no dice. If you create FileInfo or DirectoryInfo objects to look at the file, it appears to be using the SmartPhone-type filesystem (e.g. root dir is \ instead of, say, c:\).

Update (July 5th 2005, 3:35PM): As Vladimir's comment suggests, he followed up on his original reply to me on the message boards here. A copy of the post follows:

The directions were for VS2005 DE for configuration of the running instance of the emulator. There are three emulator configurations that exist - global, local saved and instance. The Global configuration is what you set under Tools\Options\Device Tools\Pick Platform\Properties\Emulator Options. The global configuration will be applied to an emulator if there is no local saved state. If you have created a local saved state - the global configuration is ignored until you clear the saved state. The instance configuration is accessed after the emulator is started via File\Configure (on the emulator itself) and is only applied to the instance that is running.

So if you start the emulator and click on the emulator File menu, select Configure option and then select General Tab - you should see the "Shared Folder" textbox.

The folder is accessed as "\Storage Card\". My guess is that you changed your global configuration but it was not applied because you had a local saved state. You can verify that the shared folder works correctly by craddling your emulator with Device Emulator Manager and using ActiveSync to browse the filesystem.

I tried this and it works perfectly.

Sunday, July 03, 2005

By Pen You Mean Color

The Pen object in .NET CF 1.0 is incredibly limited. It has no methods and only one property, which is Color. So basically the Pen object is a glorified Color object. The .NET CF 2.0 fixes this a bit by including the Width attribute.

I found this in the MSDN .NET CF 1.0 FAQ:

Setting the pen width is not available in the .NET Compact Framework. Some alternate solutions include:

  • Drawing filled rectangles with the Graphics.FillRectangle method
  • Drawing multiple lines next to each other
  • Writing a custom graphics routine with GAPI

Let the Designers Choose

I can understand why Microsoft has endeavored to make clear the interaction/ui differences between a desktop and a SmartPhone or even a PocketPC and SmartPhone to developers. Obviously, the lack of a mouse or touchscreen introduces a new set of HCI issues. I will say, though, that I am fundamentally opposed to how Microsoft has chosen to ensure SmartPhone developers don't veer off a fairly rigid idea about how SmartPhone interaction should take place -- which is somewhat ironic given that the developers in my research group find the SmartPhone OS UI to be overly complicated. The focus seemed to be create an OS interface that follows the most prominent UI features/models of Windows rather than creating an OS interface that is actually good as a phone UI (e.g. syncing to the Outlook contact list probably seemed like a good idea until you test it with actual users, where you would find that, in fact, much of an Outlook contact list is not made up of phone numbers but rather e-mail addresses! This is great if I want to use e-mail on my phone but not when I just want to make a phone call. My Outlook contact list is populated with 100s of contacts whom I rarely talk to and would never call (because, for one, I don't even have their numbers). But I digress...

Back to my original topic which is: the way Microsoft has structured the .NET CF API to enforce its limited vision of HCI on the phones.

Case in point, radio buttons. Yes, radio buttons. Microsoft disallows Radio Buttons on the SmartPhones. They made that choice for me. They think radiobuttons are a bad idea on an interface that small with limited input mechanisms. Instead, they suggest I use a ListView where only one item can be selected at a time (ah, how clever, that's just like a radiobutton but not!). However, in my application, it is much more relevant and intuitive to usea radiobutton. But somehow this choice isn't mine, it's Microsofts.

You know, fundamentally, I think the .NET CF GUI API should really just expose everything. Let the designers choose what's right or wrong. I know Microsoft is trying to provide some baseline standard, fine, but don't restrict my creative freedom and design talents.

Saturday, July 02, 2005

How Dare You Take My OwnerDraw Away!

So, I thought the ListView class might be the answer to all of my Key Event problems. I need an interface on the phone with multiple controls that all respond to "hot key" presses. The ListView Control, which is probably the most used layout control on the phone, basically gives you this functionality if your two controls are "labels" and "checkboxes." In my case, I need one more control ala "radiobuttons" -- how hard could it be to draw a radiobutton instead of a checkbox in a custom ListView class?

So, I derived the ListView class and overrode the OnPaint and OnBackgroundPaint methods and launched a test on the emulator. Hmm, it looked like my OnPaint methods were not being called. WTF? Some searching found, "The ListView control is drawn by the operating system or is owner drawn, so the Paint event is never raised. For more information about owner-drawing, see the OwnerDraw property." Stop right there!

Yes things still sound salvagable until you note that the .NET CF 1.0 ListView control does NOT have an OwnerDraw property. Try it yourself if you like -- create a simple class MyListView : ListView and then override OnPaint and OnBackgroundPaint. Note how those methods are never called. So, unless you are using .NET 2.0 you're screwed.

Jon goes back to the drawing board now (which will probably involve something like the custom list view found here, which is really not even a custom list view but rather a completely new custom control). Oh the woes of programming UI on the SmartPhones. Which bears the question, why build a huge set of widgets and then restrict their usage so much that they become useless?

Thursday, June 30, 2005

Trap All Key Presses Independent of Focus

I posted the following to the C# msdn forums (http://forums.microsoft.com/msdn). You can find the thread here.

Using Visual C# .NET Compact Framework 1.0, I'm trying to trap all keypresses in a top level System.Windows.Forms.Form whether or not the form has Focus. Basically I want to delegate key events on my own. The problem is that only the currently Focused Control receives events (KeyPress, KeyDown, etc.). I would like a high level key event manager that peeks (does not consume) all key related events for a Form. Can anyone help me here?

I looked at the RegisterHotKey API but that is only for C++ and, as the method name implies, that is only for registered keys -- not the entire set of keys. If this is the only way or best way of trapping keypresses, I guess I will have to write a C# wrapper but I would prefer some other method.

Is there a known way of doing this?

I got one response from Daniel who said, "Look at the ApplicationEx class (and message filters) in the Smart Device Framework (SDF) from OpenNETCF." Unfortunately I can't use OpenNet CF because it is Open Source. He also pointed me to a newsgroup discussion. The consensus seems to be that the .NET CF does not make this easy, so you should just use OpenNET CF :( For example, here.

Tuesday, June 28, 2005

OpenSource .NET CF

I added a link to this site (http://www.opennetcf.org/) on the right sidebar. It is a giant repository of OpenSource .NET Compact Framework source code.

Confusion About .NET & .NET CF

I'm using Visual Studio 2005 b2 for my C# development. My current solution file contains both projects that are .NET 2.0 and .NET Compact Framework 1.0. It only recently became clear to me that the SmartPhone 2003 projects in VS2005 b2 are, in fact, .NET Compact Framework 1.0 (bear in mind that this is a different, more restricted API than just .NET 1.o).

To add a .NET CF 1.0 project to your solution with VS2005 b2, select the solution in the solution explorer->Add->New Project->Visual C#->Smart Device->SmartPhone 2003. You have just implicitly started a .NET CF 1.0 project :)

More frustrating things about developing for these phones:

(1) Again, there is no good documentation source that simply displays the .NET CF 1.0 API. You have to wade through all of the .NET documentation and then scroll down to the bottom of the class description to make sure it's supported by your flavor of .NET.

(2) When you open up any class in VS2005 help, the bottom of the class description details three things.
  1. Development Platforms
  2. Target Platforms
  3. Version Information

The Version Information is most critical for .NET CF developers. It is here that Microsoft tells us whether or not this class is supported by the .NET CF framework (and which versions 2.0, 1.0, etc.). Of course, this does not mean that ALL members of this class are supported by the .NET CF framework; in fact, more often than not only a subset of the members are supported. So, you must then browse to the class members and look for the little Pocket PC icon. If it exists to the left of a method/property, you can be assured that it is supported by the .NET CF.

Now, this post is NOT a rant about the lack of functionality in .NET CF (of course the compact framework is going to have a more constrained API offering) but rather in the organization of the MSDN help system. After programming in .NET for the SMT5600 for only two weeks I have run into a couple of confusing instances where a method I expected to be available (e.g. the Control.ControlAdded event in Forms) was not and, critically, it took some proactive documentation perusing to understand why.

Finally, I will say that part of my struggle is most definitely a result of being relatively new to .NET as a whole (my Master's thesis project was in Java, my language of choice) -- there are inevitable growing pains and disconnects whenever learning a new language; it's just been a very frustrating experience.

Sunday, June 26, 2005

Property Browser with Custom Controls

One cool feature of VS2005 is the integration of user controls into the Forms Designer. You can even categorize your properties by using browse attributes. By default new properties for a control are filed under "misc" to change this add:

[
CategoryAttribute("Appearance"),
DescriptionAttribute("This is a description of this property")
]
public object MyProperty{
get { ... }
set { ... }
}

For more info on customizing the property browser, go here and search for "Property Browser" within your web browser.

UPDATE (06/26/2005 @ 12:09PM): It appears that the .NET Compact Framework has a relatively restricted ComponentModel space to affect run-time and design-time behaviors. For example, code completion with System.ComponentModel in VS2005 b2 shows only three available methods: (1) DefaultValue (2) DesignerCategory and (3) EditorBrowsable

Tab Order

I created my own custom widget and am having trouble using the SMT5600 "joystick" to navigate to it. I thought it might be an issue with tab order...

The .NET Compact Framework supports tabbing between controls with Service Pack 2 and later, but requires that you explicitly use the Focus method on the first control that should receive the focus.
The .NET Compact Framework does not support the TabIndex and TabStop properties or the UpdateZOrder method, but you can design your application to have a predictable tab order and explicitly set controls to receive focus. The up and down navigation follows the tab order.


The default tab order follows the sequence of focusable controls as they are added in code to the Controls collection.


Note that the forms designer creates the Controls collection in reverse order of when the controls were added to the form. For example, if TextBox1, TextBox2, and TextBox3 are added to the form in that order, then first control in the Controls collection is TextBox3. The following Visual Basic example shows designer-generated code in the InitializeComponent method of a form.

(from MSDN -- scroll down to bottom)

Saturday, June 25, 2005

MSDN API for SmartPhones

I must admit, I find the MSDN API really confusing compared to javadoc. Err, scratch that. I find the MSDN API really confusing compared to any documentation system ever including IKEA assembly instructions.

I am trying to find an easy reference for the C# SmartPhone API. Unfortunately, all I can find is the ordinary MSDN .NET API (can't even find the reduced .NET Compact Framework API). So, I have to scroll down to the bottom of the API reference to make sure that it includes .NET Compact Framework... Even then, the class is not guaranteed to work.

Case in point: the ButtonBase class. Go to the MSDN ButtonBase Class Overview page and you will see that it is a compatible with the compact framework. Then open up the constructor page, found here, and note that platform support for the compact framework is curiously missing. I had a devil of a time trying to build a custom control class that inherits from ButtonBase (VS2005 b2 kept saying "No overload for method 'ButtonBase' takes '0' arguments"). I finally gave up. I had then hoped to derive a class from UserControl but it seems that this class is not supported by the .NET compact framework either. Hmm...

I feel like I am certainly missing something with regards to the MSDN documentation system. Is it too much to ask for to gain access to an easy API reference which just includes SmartPhone 2003 supported classes?

Connect to Device Failed

I have been unable to get the SmartPhone 2003 Device Emulator to work on my laptop. This is particularly frustrating because I have successfully run the device emulator on two different desktop machines at work. My laptop is a corporate system and, therefore, may have some firewall software or strange setting unbeknownest to me.

The error I get is identical to this thread on forums.microsoft.com. Basically, I try debugging a simple test application with the SmartPhone 2003 SE Emulator and I have to suffer through a long pause before I get an error dialog that reads, "There were deployment errors. Continue?" I have the option of selecting Yes or No... neither of which helps. In the Error List in Visual Studio I get "Connect to Device Failed - Conman HelpText System."

According to the help thread mentioned above, this connection error is most likely due to a problem with the ip of the emulator. By default VS2005 beta 2 uses TCP/IP as the transport to the emulator. Unfortunately there is no easy way to determine the ip of the SmartPhone 2003 emulator (though there is a way to do it in the PocketPC 2003 emulator). I then installed the Microsoft Loopback Adapter solution, instructions found here. This did not solve my problem either -- in fact, I get the exact same error.

Beyond this, I've tried just about every setting in Tools->Options->Devices->SmartPhone 2003 SE Emulator->Properties but to no avail. In addition, I foundthat the easiest way to test the connection setting was to employ the "Device Emulator Manager" found in VS2005 (Tools->Device Emulator Manager) rather than to attempt a debug execution on the emulator.

I'm going to give up for now and debug straight off the cell phone itself. This, however, was not a possible solution this past week because I did not have my cord with me.

Friday, June 17, 2005

Storing Application Data on SmartPhones

Application data is typically about two things: settings and application preferences that the user expects the application to keep even after it is terminated, and transactional or reference data brought from a remote server or entered by the user. Microsoft SQL Server™ 2000 for Windows CE Edition (SQL Server CE) is a popular choice for application data storage on Pocket PCs and other Windows CE devices. Other options have to be used in Smartphone applications since SQL Server CE is not available for the platform. Persisting data to the registry is not generally recommended because flushing the registry to permanent store is quite resource intensive. For Smartphone applications, using local XML files is a common alternative.

(from MSDN)

Thursday, June 16, 2005

Signing SmartPhone Apps

The security model for Smartphone applications is based on certificates. A device can be configured by the device manager (usually the network operator) to allow only signed applications to run. Whether an application can run or not depends on:

  • If the device has a one- or two-tiered security model
  • The current security mode of the device: Open, Locked, or Prompt
  • How the application was signed: with a privileged certificate, unprivileged certificate, or not at all

One-tiered devices give access to all APIs for applications that are allowed to run. On two-tiered devices, there are APIs that cannot be access unless the application was signed with a privileged certificate.

If the device has:

  • Open security mode, all applications can run, signed and unsigned.
  • Locked security mode, only signed applications run on the device.
  • Prompt security mode, all signed applications run without a prompt, and the user is prompted to reject or accept all unsigned applications.

(from MSDN).

Application Data Path on SmartPhones

You can Platform Invoke the Windows CE API SHGetSpecialFolderLocation with CSIDL_APPDATA (26) as parameter to retrieve the application data path.
RAM is erased when a Smartphone is switched off. This means that application data has to be put in the \Storage folder. The \Storage folder is persisted to flash memory. For more information, see "Storing Data" in the Smartphone Guide found in the Smartphone 2003 SDK.

(from MSDN)

Thursday, June 09, 2005

Sets in C#

Unlike Java, C# does not include Sets in the Collections framework. HashedSets are relatively easy, just use the same key and value in a Hashtable object. If you need something more advanced (e.g. SortedSet), I found this on codeproject by Jason Smith. It adds support for "Set" collections to .NET. Disclaimer: I haven't actually used it yet...

Wednesday, June 08, 2005

Windows Mobile 5.0 on the SMT5600

Some initial impressions of Windows Mobile 5.0 running on the Audiovox SMT5600 found here.

You can take away my buttons, but you...

The SmartPhone form designer in Visual Studio 2005 does not include support for buttons (e.g. Button, RadioButton, etc.). Of course, there are other widget absences as well, ListBoxes, RichTextBoxes, etc., but I am most dissapointed by the disappearance of buttons. Presumably, they left them out because SmartPhones lack "touch input" or any interaction devices that makes it easy to use buttons (e.g. a mouse). However, my SamSung SGH-e315 phone uses what could pass for buttons in its top level menu -- the buttons are arranged in a 3x3 matrix so that you can just press the corresponding digit on your cell phone. I think a similar mapping would work with radio buttons (e.g. have numbers next to the radio button choices and allow the user to press a number to select a radio button). (link)

Tuesday, June 07, 2005

SmartPhone Registry Editor

I tried a few SmartPhone registry editors today, some that work on the desktop and access the phone dynamically and some that work on the phone itself. The only one I could actually get to work was from breaksoft.com (link). The other two I tried were: (1) PHM Registry Editor and (2) an open source registry editor from this.Pose() as Expert.

On my SmartPhone, the registry link:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
does not contain the Run directory. So perhaps you cannot register your application to autostart through the registry on SmartPhones...

Monday, June 06, 2005

Auto-Start App on Device Startup

I need to auto-start my application when the Audiovox phone boots up. In Windows XP, there appears to be two primary methods developers use to auto-load their applications when Windows loads: (1) the application installer copies a shortcut of the program into the "StartUp" directory (C:\Documents and Settings\user\Start Menu\Programs\Startup) or a more popular method (2) add a path to your program in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run of the Windows Registry.

The nice thing about the latter method is that many programs use command line switch options to load in a special way if executed by autostart rather than by user. You could imagine building a program that uses a command line switch like -autostart that would simply load itself passively into the background when initiated by the device, while the same program might show a load screen or user interface when initiated by the user.

I am not entirely sure how this works on Smartphones. I am quite confident that method one above works. The model here is, let the installer do the work and copy a shortcut of your application into the Smartphone's Startup directory. However, I found a discussion on msdn that seems to indicate shortcuts on mobile devices are limited compared to their desktop counterparts. In WindowsXP, for example, you can set the Shortcut's target application and in the process you can include command line switches. This does not appear possible on Smartphones (link). Of course, this does not limit you in just creating a simple shortcut to your application or, as the above link outlines, creating a special boot application independent of your main executable.

Incidentally, you can see a list of programs slated to auto-start by typing "msconfig" in the Run window of Windows XP, then click the "Startup" tab. (See link for more information)