Sunday, December 09, 2007

Detecting the SDF file version

SDF files don't have an explicit way of letting you know their versions. What can you do to tell the version of a given SDF file? In my products I detect the SDF file version as a side effect of opening it: if a given engine can open that SDF file then I can safely assume it has the same version as the engine. This is not a very straightforward approach because it requires that you have all engines installed on the device (not a typical scenario).

The alternative way to detect the SDF file version is by reading a few signature bytes on the file. Just open the file, set the read location at offset 16 and read the 32 bit int there. The following values will tell you the file version:
2.0: 0x73616261
3.0: 0x002dd714
3.5: 0x00357b9d

I wrote a very simple .NET CF 2.0 application to illustrate this. The download link is this. If you find any SDF file that fails this test, please let me know.

Friday, December 07, 2007

WM6 GPSID problem workaround

John Spaith from Microsoft has blogged about a workaround solution to the HTC GPS problems on WM6. Apparently the size of the GPS_POSITION structure must be tweaked in order for the call to GPSGetPosition to work, but this can only be applied on devices where the first call returns 87... I actually worked around this by falling back to the COM port.

Monday, November 26, 2007

COM Port Enumeration

If you want to enumerate the available COM ports on your WM device, there is a very simple solution: look under the HKEY_LOCAL_MACHINE\Drivers\Active for all keys that have the Name value starting with the "COM" string. With some luck, you can even find a FriendlyName value under the key specified by the Key value.

The only problem with this very simple method is that it does not enumerate the Microsoft Bluetooth stack emulated COM ports. If you create a partnership with a device that has the serial port profile, you will be able to assign a free COM port to it. This COM port works like any regular serial port but does not show up in the list of active drivers on the registry. Microsoft decided to enumerate all Bluetooth virtual COM ports under HKEY_LOCAL_MACHINE\
Software\Microsoft\Bluetooth\Serial\Ports. To find all available COM ports you must enumerate all the child keys and look for the Port value under each key.

Interestingly, the Widcomm stack does put the virtual COM ports where they should be (or at least where I expected them to be).

Tuesday, November 20, 2007

VS2008 Install Heads Up

Before you install Visual studio 2008, make sure you read the readme file. There are two important implications for native and mobile developers: SQL CE 3.5 must be uninstalled prior to installinv VS2008 and the Windows Mobile 6 SDK will have to be uninstalled and reinstalled after installing VS2008.

Monday, November 19, 2007

VS2008 is out!

Check out the subscriber downloads in MSDN!

Thursday, November 15, 2007

Windows Live

Off-topic: Today I noticed that for the first time in the last few years Google is not on the top of the list of search engine referrals on my comany's site web log data. Out of the blue (or maybe not) Windows Live is leading the searches! This is intersting news for a chart that used to show a huge Google bar and essentially nothing else.

Monday, November 12, 2007

Performance Improvements in VS 2005

Jim Springfield has just posted in the Visual C++ Team Blog a very interesting piece of information: there is a new performance improvement QFE for Visual Studio 2005. This download addresses a number of performance issues and its features will roll over to VS 2008. I'm getting it right now to give it a spin.

Wednesday, November 07, 2007

Carousel Demo

Now that the carousel code is working correctly across a range of devices, I decided to upload it as a preview (download here). The code illustrates the carousel animation and user control as a strip on the child window of the WTL main frame. I'm still wondering how this "control" should be implemented, either as a "widget" on the main frame or as a toolbar-like control.

The main frame approach would implement the carousel code in the main frame allowing it to correctly resize the child window and even allowing the application to change the child view (like in a property sheet). With this approach it might also be easier to implement a means to change the location of the bar whan the screen is rotated. In fact, the carousel looks much nicer in a vertical position when you rotate your screen to landscape (right or left would be up to you).

Implementing this as a toolbar control would have the advantage of allowing the developer to reuse the code outside the main window, especially on dialogs and modified property sheets...

While I think about what to do, please do take a look at the code. The icons were "created" with Axialis IconWorkshop, one of the best icon editors around. Please note that these icons can only be used by registered users of the product and I'm not sure that you can reuse them on your applications.

Wednesday, October 31, 2007

GradientFill and a memory DC with a viewport

I’m working on a “carousel” control similar to the one you can find in the Yahoo Go! 2.0 application. This thing showed up in my HTC S620 WM6 upgrade and the control is very cool, so I decided to write my own implementation of it in C++ using WTL 8.0. The scrolling animation is achieved by painting to a memory DC and then blitting it to the screen. All went smoothly until I decided that the carousel background would look so much nicer with a gradient, making the center item stand out in a lighter background.

WTL 8.0 does a lot for you and I found myself having more work creating the icons for the sample than actually implementing the code... I started by using the CMemoryDC class which worked beautifully until I used GradientFill. All other GDI functions work correctly, but the gradient refused to appear correctly or at all. Interestingly, when the carousel strip was set at the top of the client window it would paint correctly, but would fail at the bottom.

Looking at CMemoryDC's source code I found that the constructor sets a viewport origin in order to cope with any rectangle. When setting the carousel strip at the top, the gradient would show up because the viewport origin would match the child window's (0,0), but fail when set to the bottom because the viewport origin would be different.

I ended up by using a slightly modified version of CMemoryDC, by removing the SetViewportOrg call on the constructor and zeroing the source bitmap coordinates at the destructor's BitBlt call. The carousel now works correctly on all four window edges (top, bottom, left and right).

Presently the carousel is implemented as a child view window but I'm looking at ways to make it work as a toolbar.

HTC P3300 GPS problems (again)

After posting in January about the failed implementation of COM events on the GPS port of the HTC P3300, I have another sad story to tell. After upgrading the device to Windows Mobile 6, the GPSGetPosition function always returns 87 (ERROR_INVALID_PARAMETER). There seems to be no appropriate set of parameters that this thing will take, you will always get back an error 87. Great! The GPSID on the P3300 is useless. The solution is to fall back to the COM port code...

Friday, October 26, 2007

Access 2007 woes

I don't have any complaints about using the Access 2007 application whatsoever. After the not so brief period that took me to learn the new user interface (some stuff on the older UI was quicker to use), the experience is quite smooth. Not so on the nuts-and-bolts side of the question.

As you already know I'm an OLEDB freak, and I use it for all native code database access I write both on the device and on the desktop. Last year I did write a sizeable amount of code for my data synchrnization component (Data Port Sync) and this targeted the JET 4.0 database engine. The code I wrote implemented both the Access database preparation and also change tracking. Database preparation involves creating a few extra tables and adding two columns to every tracked table. This looks pretty simple to do using straight SQL, but when I consistently failed to create self generating "replication id" columns (the SQL equivalent of the uniqueidentifier type with the rowguidcol property) I turned to the low-level
ITableDefinitionWithConstraints OLEDB interface to do all the table creation work. The code is not nice to see, but it is effective and gave me an added bonus: I can hide the tables from the user. To add the extra columns to the tracked tables, I used the
ITableDefinition interface.

Recently I started to get requests from my customers to support the new Access 2007 file format on my data transfer products. Changing the provider from Microsoft.Jet.OLEDB.4.0 to Microsoft.ACE.OLEDB.12.0 did the trick quite nicely because Microsoft kept all the other connection string properties untouched. BTW: where can I find a reference to all the properties and most importantly, where are the new header files for OLEDB?

The first implementation of the Access 2007 database engine was shipped on the Data Port Console release. Although it does not create the mdb or accdb files (yet), it successfully imports and exports data to and from the various SDF formats.

Going back to the desktop synchronization code (which will eventually see its way into the Console) I recently began to write a small desktop agent for simple desktop scenarios. Putting the new code to work was quite easy until I decided to test the code against an Access 2007 database. I picked up the old Northwind sample and converted it to the new engine only to find that my preparation code would fail miserably. There were no issues when the tracking columns were created, but it proved next to impossible to create the tracking tables: the engine would throw an E_FAIL error with a very strange OLEDB error description: "Could not find field." Period. I changed every possible factor that could be causing this: column names, the table name, absence or presence of delimiter brackets. Nothing would work. Out of desperation, I replaced the code with a straight SQL DDL command only to be greeted with a similar error: "Could not find field 'SID'." I beg your pardon? There is no 'SID' in my command! Has Access gone mad?

No, Access is working perfectly but the accdb file seems to be corrupt. After reverting all the code back to what it was, I decided to create a new accdb from scratch and then import new data from an SDF using the Console. After running it through the preparation code there was no error! Is the database conversion code broken in Access 2007?

Bottom line: don't convert mdb to accdb. Create a new accdb and then import the old data into it. Sigh.

Friday, October 19, 2007

The edit control under Windows Mobile 2003 and 5.0

After publishing my last article, I found out an interesting thing about the edit control on a Windows Mobile 2003 Pocket PC device: the up and down arrow keys behave differently from the edit control in Windows Mobile 5. In WM5, the single line edit control responds to the up and down navigation keys by setting the focus to the parent window. When this happens, the parent window receives the corresponding WM_KEYUP messages and thus is able to set up a navigation mechanism. Not so with the Windows Mobile 2003 edit control. This version of the control seems to "eat" these messages so the parent has no clue about the requested user navigation. This became quite apparent on my implementation of the CFormListCtrl: the navigation would not work.

This problem was quickly solved by adding the OnKeyDown message handler to the CCeEdit class and forcing the control to set the focus to the parent window whenever an up or down navigation keys are detected. Voilá!

Thursday, October 18, 2007

A list-based form for Windows Mobile

I have just published an article on CodeProject that better describes the list-based form control. As you can see from the article, I added a few other bells and whistles to the code.

Next two projects: port this thing to WTL and start writing an OLE DB class library for Windows Mobile. This second project is necessary because Microsoft no longer ships the atloledbcli.h file on the SDKs and this must mean something...

Thursday, October 11, 2007

Bug in the FormListSample

There is a bug in the FormListSample that causes a stack fault exception if you close the dialog with a created item control (edit, combo or date time). I'm looking at this right now.

Solution: On the CFormListCtrl::OnDestroy method, set the m_iEdit member variable to -1 after calling ShowEditor.

Meanwhile, I added some code to handle edit control resizing when the screen is rotated. The code can be found on the same location.

Monday, October 08, 2007

The list-based form control

Back in 2003 when the Smart Device Extensions were still in Beta and about to be renamed .NET Compact Framework, some people had to use C++ to develop database applications. I was one of these developers struggling with a crude set of tools: ADOCE for database access and the eVC3 dialog editor to design the user interfaces.

Soon we learned that ADOCE would be deprecated and so I started to look at the ATL OLE DB consumer templates. This is a great technology and I still fail to understand why it is not present on the WM5 and WM6 SDKs. In my code, I use an adapted version of the header file you get on the Pocket PC 2003 SDK but to be honest I don't like this approach (I will come back to this issue in a future post).

On the user interface side, we already had a very nice alternative to dialogs: the list-based form control used by the Pocket Outlook Contacts application. Not only this is an intuitive control for the user, it also promised to be easy for a developer to use: no designer needed to be involved, you just specified the list of items to edit and fired the object.

The big problem with this control was that there was no API for it so I had to write one. Back then I was using MFC big time due to the compiler support for it on eVC3 and eVC4. Now I am not so sure that MFC is a good option for native user interfaces and I'm leaning towards WTL. You now have great tool support in VS 2005 with the WTL Helper tool which I am using on a daily basis and with great results.

So I eventually wrote an MFC control to implement a list-based form and in the process I threw in couple of goodies such as grouping, context menus for managing the items, control notifications and a few other bells and whistles. After a recent request of fellow MVP Christian Forsberg for a similar control, I decided to go back to my 4 year old code, adapt it to VS 2005 and publish it. I had to do more work than expected because nowadays there are lots of devices that have a keyboard, display in landscape and even have VGA screens! Back then I was used to portrait QVGA screens and no keyboard, so some changes were in order.

Before I publish this code as an article, I decided to preview it here so you get a chance to look at it and let me know what you think. Download FormListSample.zip

Thursday, September 20, 2007

Supporting SQL Compact 3.5

Native code is so cool! As of today I can write applications that target SQL CE 2.0, 3.0 and the new 3.5 Beta 2. The trick? Extend this technique to the SQL Compact 3.5 header files. Microsoft made our life really easy by making very small changes to the header file, so you only need to copy the definition of CLSID_SQLSERVERCE_3_5 and all the property definitions of
DBPROP_SSCE_DBENCRYPTIONMODE. Now your header file can be used for 2.0, 3.0 and 3.5!

What this means for me is that SQL Compact 3.5 will be supported by the release version of Data Port Console and I will also issue a last version of DesktopSqlCe that will also support the new database engine. This will be the only game in town for .NET 2.0 desktop applications that must support both the 3.0 and the 3.5 database formats (without code changes, of course).

Cool!

Friday, September 07, 2007

SQL Compact 3.5 Beta 2 and VS2005

Ready to move forward and add SQL Compact 3.5 support to my products, I downloaded the Beta 2 bits in the hope to find the required header files. Unfortunately they were nowhere to be found. Does that mean that you cannot use VS2005 with SQL Compact 3.5 Beta 2? No. Fortunately there is an indirect way to get the much-needed header files: download and install either Orcas Beta 2 (not yet for me) or Microsoft Visual C# 2008 Express Edition Beta 2. Apparently the header files are also available on the Visual Basic edition.

Now back to work.

Friday, August 31, 2007

Database Diagrams for Data Port Console

The second release candidate of Data Port Console 1.0 is almost out and while I was removing some bugs, I failed to resist the urge to bring back some code that had been sleeping for amost one year: database diagrams. Yes, coding should also be fun so I decided to add this to the 1.0 and in this post I'm offering my readers the chance to try this new feature. You can create multiple diagrams per database and now all information is persisted as an XML file instead of using the registry. You will also notice that there is a new folder for tables and that you can group them by their first letter. Please let me know what you think about these new features while RC2 is not uploaded to the site. Grab your copy of this interim build here.

Tuesday, August 21, 2007

ZIP and RAPI - The article

My latest musings on this subject have been published on CodeProject. Read the article here.

Sunday, August 19, 2007

ZIP and RAPI - Yes, it's faster

I really was not pleased with the performance results I got from the RAPI Unzip extension I published in my last post. My reasoning was that if you send a compressed data stream to a device and decompress it you should get a better performance than decompressing the data on the PC and sending it to the device. The results I got were not very satisfying: the RAPI extension DLL was not clearly faster than the PC decompression, especially for ZIP files with small compression rates.

So I decided to take a harder look at the code and found the culprit: WriteFile latency. The function was being called way too often and sometimes with small sets of data. If you look at the code, you will see that WriteFile is called when either the decompression input or output buffers are emptied. This is wrong. The call must only be made when the output buffer is empty and not when the input buffer is. When the input buffer is emptied it must be refilled from the RAPI stream and the output buffer should not be flushed, otherwise we risk flushing a small amout of data expending one WriteFile call.

The final result is now ready and is consistently faster than the PC decompression approach. Try it!