Blog link of the week 32

Sun, August 14, 2005, 02:59 PM under Links
- Pablo points to "Solution Folders", a new feature in VS2005. (Note, it is not available with zero-impact projects so save if you want to use a Solution Folder)

- Tired of all the positive buzz on Indigo? Read this.
BTW, anyone here attending the Indigo event in Seattle? I'll be there :-)

- Even though this is not this week's news, I'll make an exception since I somehow missed it last month: Delphi for NETCF (cool!)

My MSDN article

Sat, August 13, 2005, 02:55 PM under MobileAndEmbedded
My MSDN article is now online. Check it out and, as always, let me have your comments.
(Had it been published in exactly 3 weeks time, the employer name under the author name would have been "Avanade", of course...)

Point-to-Point Message Queues with the .NET Compact Framework


Bug in Substring under netcf

Sat, August 13, 2005, 08:10 AM under MobileAndEmbedded

String s1 = "Some string";
this.Text = s1.Substring(1, s1.Length)
When you run the code under the full framework, you can see the ArgumentOutOfRangeException: "Index and length must refer to a location within the string. Parameter name: length".

When you run it under the .net compact framework v1.0 you see nothing. It is too tolerant (bug).

This is now fixed in netcf v2.0 so if you try the same code you'll get a ArgumentOutOfRangeException: "Specified argument was out of the range of valid values."

If your app took advantage of the bug it will now crash. It is for reasons like this you'd want to run your app in compatibility mode under netcf 2.0 (unless you can recompile your code under CF v2.0, of course).

However, in this case, that won't help you... until we get some msft comments, I guess it is probably a bug in the compatibility mode or maybe compatibility is only there for by-design changes and does not extend to bug fixes...

No more .NET

Fri, August 12, 2005, 01:27 AM under dotNET
Alternative title "What's in a name?"

This should be old news, but "repetition is the mother of all learning" [Greek proverb translated to English]

The ".NET" moniker is being phased out of new Microsoft products. We recall the craziness when .net was first launched: everything got a .NET after its name! Then it moved only to products that were relevant, and now it is being dropped.

The best example of this is Visual Studio. In February 2002 it was launched as "Visual Studio .NET 2002" (targeting .NET Framework v1.0). Visual Studio 6 developers, and specifically VB developers, needed to distinguish between VB6 and the new VB so it was aptly named VB.NET. In April 2003, the next version came along: Visual Studio .NET 2003 (targeting .NET Framework v1.1 & .NET Compact Framework v1.0).

There are real version numbers to go with the above (VS 7.0, VS7.1 and VB7), but everybody uses the .NET moniker (and/or the year) to refer to the products.

With Visual Studio 2005 (expected in November this year), the story changed. No more .NET after the Visual Studio name. No more .NET after Visual Basic - it is now simply VB2005 or just VB.

Another example is Windows CE. After Windows CE 3.x, came Windows CE.NET. That is WinCE versions 4.0, 4.1 and 4.2. The story here gets funnier as v4.0 does not support the .net compact framework so naming it CE.NET was a mistake (for the record, 4.1 and 4.2 do support netcf). So, last summer when Windows CE 5.0 was launched, it came as no surprise that WindowsCE had dropped the dotnet moniker as well.

If we look into the future where OS components are built with dot net code, we see that the trend of not including dotnet in the name continues, e.g: Windows Vista (Longhorn), Windows Communication Foundation (Indigo) and Windows Presentation Foundation (Avalon).

So where does all of this lead? It leaves us (the ones working on the Microsoft platform who have seen the true light) with an understanding of which product is officially named what. It leaves them (the ones who do not choose the Microsoft platform for political reasons alone, with no technical arguments) with ammunition to be able to say "We told you .NET wasn't going to last; where is it now in the latest Microsoft platform?"

So let's start changing our lexilogion and every time we are inclined to say ".NET" use the word "managed" instead. After all, that is what it is all about: Developing our apps with tools/languages that allow them to run in a managed environment.

Before anyone jumps in and says that Java also provides a managed environment, that helps my point. Make sure you realise "managed" is the way forward, and then make your choice... based on technical facts. I've made mine.

Sharing Cursor.WaitCursor and InputPanel in VS2005

Thu, August 11, 2005, 04:33 PM under MobileAndEmbedded
Most PPC apps use the SIP (see point 1 here). Now that resx files are compatible, many developers will try to share code at the windows forms level.

So rather than try to conditionally compile in or out the InputPanel do the following: in your desktop project only, simply add a file that provides stubs for the InputPanel class:
namespace Microsoft.WindowsCE.Forms {
public class InputPanel {
public event EventHandler EnabledChanged;
private bool mDummy;
public bool Enabled {
get { return mDummy; }
set { mDummy = value;}
}
}
}
Next hurdle will be changing the cursor. On the full framework, every control has a Cursor property and that is what you assign; on the compact framework, there is a single cursor which you access globally through Cursor.Current

So, add a new code file to your project (and share it in both projects) that has the following:
namespace YourNamespace {
public static class TheCursor {
public static void CursorCurrent(Control c, Cursor defaultOrWait) {
#if FULL_FRAME
if (c != null) {
c.Cursor = defaultOrWait;
}
#else
Cursor.Current = defaultOrWait;
#endif
}
}
}
Now, through a global find and replace (which I usually advocate against), replace all occurrences of:
Cursor.Current = Cursors.Default and
Cursor.Current = Cursors.WaitCursor
to
TheCursor.CursorCurrent(this, Cursors.Default) and
TheCursor.CursorCurrent(this, Cursors.WaitCursor) respectively.

If you get any compile errors it means you were assigning Cursor.Current from a method of a class that is not a control:
a) Review that design decision
b) If you stick with it, change the this to null

Now in your desktop project, wherever you were going to code the following:
someControlOrFormEtc.Current = Cursors.Default and
someControlOrFormEtc.Current = Cursors.WaitCursor
instead code:
TheCursor.CursorCurrent(someControlOrFormEtc, Cursors.Default) and
TheCursor.CursorCurrent(someControlOrFormEtc, Cursors.WaitCursor) respectively.

Not a strict subset

Thu, August 11, 2005, 10:20 AM under MobileAndEmbedded
We say that the .NET Compact Framework is a compatible subset of the full .NET Framework with few elements existing in the netcf and not the full fx.

For v1.0 I've mentioned previously and allow me to quote:
"[...] the CF is a subset of the full framework, but a closer look reveals functionality specific to the CF in the Microsoft.WindowsCE namespace (such as MessageWindow and InputPanel), the infrared classes and of course the SQL stuff is different."

MSDN has a couple more links for those compact framework unique areas here and here.

With v2.0, the CF-exclusive classes grow.

In particular, the Microsoft.WindowsCE.Forms namespace gains the following elements:
1. HardwareButton
2. MobileDevice.Hibernate
3. SystemSettings.ScreenOrientation
4. DocumentList
5. Notification
6. LogFont

NETCF 2.0 also adds the Microsoft.WindowsMobile.DirectX and .Direct3D namespace (as I mentioned here).

That's it... everything else in the compact framework is API compatible with the full framework. Happy reading :-)

Display Full Signature

Wed, August 10, 2005, 12:35 PM under Whidbey | VisualStudio
It seems the promise is delivered in the Visual Studio 2005 June CTP.

The first clue is on the Class Diagram toolbar and menu.

With Beta 2 there is a menuitem (and toolbaritem) that reads "Display Member Types" and it can be on or off - to either display the return types of methods and the types of fields/properties... or not.

With June CTP, there are 3 options as the following screenshot shows:


For a VB example of what a class on a diagram looks like when we "Display Full Signature", click here.

Before I show you a more involved C# example let me share with you a tip: Since VS2005 allows you to reference assemblies built with VS.NET 2003, even if you are not planning on moving to VS2005 any time soon
, you can visualize the publics of your assemblies with VS2005; in other words, use VS2005 just for the Class Designer so you can draw your class diagrams!

So,
1. In VS2005 add a reference to OpenNETCF.dll
2. Switch to Class View and make sure "Show Project References" is checked
3. Drill in the Project References until you reach the namespace OpenNETCF.ComponentModel
4. Now right click on it and choose View Class Diagram

There you have it. A class diagram showing the BackgroundWorker and its friends :-)

I followed the steps above in a C# project and the results, with full signatures, are here.

GenerateMember

Tue, August 9, 2005, 12:27 PM under Whidbey | VisualStudio
If you look at the form designer generated code (InitializeComponent and friends), when you add a control to your form, you'll see that the control gets created, sized, positioned etc and then finally added to the Controls collection of the form. That is all fine and necessary, what is not always necessary is having a form level field that points to the control. It is an extra 4 bytes per member and more importantly clutters the code and intellisense (and any diagrams you auto generate).

In this area, there is a small enhancement that I loved when I first saw Whidbey and I don't think it has had enough coverage, so here goes.

In Visual Studio 2005, when having a form open, you can select a control and toggle a new boolean property from the properties window (under the Design category): Generate Member. As the documentation says, it "Indicates if a member variable will be generated for this component."

So for all those projects you have upgraded, go though the controls on your forms and check to see if you are accessing the control variable outside InitializeComponent; if you are not set GenerateMember to false. For new projects make sure you remember to make that decision every time you add a control to your form; e.g. most Label instances never get accessed after you set their Text in the designer.

Note that this is not a true property, i.e. you don't get programmatic access to it of the Control class. It is simply a design-time thing done via an extender no doubt.

Show numeric SIP for WinCE devices

Mon, August 8, 2005, 12:25 PM under MobileAndEmbedded
Everybody knows that to show the Soft Input Panel on a WindowsCE device you have to use the Microsoft.WindowsCE.InputPanel (set the Enabled property to true/false to show/hide).

A common request, to which there is no clean answer, is to show the SIP in numeric mode or not so the user doesn't have to do it.

However, Alex Feinman has a great hack that provides just that; it checks for the color of the "123" button and sends a windows message depending on if it is black or white (pressed or not). Go download it here.

If you are targeting PocketPCs then use it and that is the end of the story, see you next time.

If you are targeting custom Windows CE devices, you need to make a few small changes (on our platform we are using the small keyboard with the "Large Keys"):
1. The calls to GetPixel/SetPixel take the X,Y coordinates which are hard coded to 2,2. Change the Y to be 77.
2. Change the last parameter in the two calls to Message.Create to be: new IntPtr(0x00490009).
3. Change the condition so it caters for showing a numeric sip in non-numeric mode.

I've wrapped the changes in an InputPanelEx class:
a) In your projects replace all occurrences of InputPanel to InputPanelEx.
b) Wherever you have inputPanel1.Enabled = true, add another line inputPanel1.Show(true) [if you want to show numeric SIP].

Blog link of the week 31

Sun, August 7, 2005, 03:50 PM under Links
If she writes a book, I'll be the first one to buy it. This week: Application.DoEvents is *not* OK (don't say I didn't tell you)

GeneratedCodeAttribute. I say... finally!

Arguing over details... my kind of arguing :-)