Monday, August 22, 2005
Sunday, August 14, 2005
Cool Designer Trick for Panels
Wednesday, August 03, 2005
Curiosities of Control.Invoke...
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
"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
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?
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
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
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
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
Thread Safe Singleton Code
Saturday, July 23, 2005
No Thread.Abort() in .NET CF 1.0
See this HOWTO on msdn for a workaround.
Friday, July 22, 2005
Obtaining Memory Status w/C#
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
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.
Creating a multi-form app on SmartPhone
Thursday, July 21, 2005
Where art thou Java iterators?
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
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
Wednesday, July 20, 2005
No Linked Lists in C# 1.0, 1.1
Monday, July 18, 2005
My Classes Are 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
Please, Let Me Keep My Unassigned Variables
Enumerations
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
Properties
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
Overview of .NET Compact Framework Garbage Collection
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
"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
Here are a select few that interest me:
- Accessing Phone APIS from .NET Compact Framework
- Advanced P/Invoke on the .NET Compact Framework
- An introduction to P/Invoke and marshaling on the .NET Compact Framework
- Creating a P/Invoke Library
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
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!
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
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
(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
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
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
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
Wednesday, July 06, 2005
Update: Tab Order
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
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 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
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
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 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
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
Confusion About .NET & .NET CF
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.
- Development Platforms
- Target Platforms
- 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
[
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
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 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
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
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#
Wednesday, June 08, 2005
Windows Mobile 5.0 on the SMT5600
You can take away my buttons, but you...
Tuesday, June 07, 2005
SmartPhone Registry Editor
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
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)