Sunday, September 9, 2007

Is your mobile application ready for two-sided touchscreens?

If not, don't worry, there is still some time because so far this is only available as a prototype :-) It is interesting to think about this though. Microsoft Research and Mitsubishi have created a device that has a touchscreen on its back side, and finger positions are projected to the display on the front. This way the current application is not obscured when trying to use it with one or more fingers, one of the major drawbacks especially with small screens. Read more about this and watch a video with the prototype in action at Technology Review.

Tuesday, September 4, 2007

New OpenNETCF community site launched

A promising new community site for Windows CE / Embedded developers has been launched by the well-known OpenNETCF group. Considering the great things the guys from OpenNETCF have proved to bring to life in the past, namely their Smart Device Framework, the articles and forum, I am sure that the new site will quickly develop into one of the premium site for mobile development. Check it out at http://community.opennetcf.com/.

Tuesday, August 21, 2007

Link tip: Using NUnitLite for Unit Tests with Compact Framework

Neil Cowborn has written a quick introduction on how to use NUnitLite for unit testing in CF applications. If you are currently not using any automated testing in your application, you should definitely try this out.

Link tip (video): How to use Windows messages in Compact Framework to determine if a combobox dropdown is open

There is a new 13-minute video by Jim Wilson online at MSDN that shows how to determine if a combobox list is currently open in .NET Compact Framework:
Unfortunately the CF does not support the DroppedDown property available in the full framework, so you need to use a WinAPI message. It boils down to the following code:

const int CB_GETDROPPEDSTATE = 0x0157;

bool ComboBoxDroppedDown(ComboBox target)
{
Message comboBoxMessage =
Message.Create(target.Handle,
CB_GETDROPPEDSTATE,
IntPtr.Zero, IntPtr.Zero);
MessageWindow.SendMessage(ref comboBoxMessage);
return comboBoxMessage.Result != IntPtr.Zero ;
}

Check out the video page for the video itself and for downloadable sample code. This is a nice walk-through on how easy it can be to add missing functionality to CF using Windows messages, so if you haven't done this before and wouldn't have been able to come up with the above code yourself, watch the video not just as a tip for the DroppedDown property, but as an introduction into using native Windows messages.

Sunday, August 12, 2007

10 ways to annoy your software developer


Inspired by 10 things your IT guy wants you to know, I suddenly felt the need to write down some things that sales or support people might want to avoid when interacting with their colleagues from software development (and I am well aware that none of those will read this here, but anyway, I got it off my mind :-)). So here are my personal favourites on how to annoy me as a software developer:

1. Give me some ultra-super-urgent stuff to do until the end of the week, then hand over the specification and some emails dated two months ago that have been sitting in your in-box all the time.
For the sake of the company, I will work on it, but if this happens more than once, be assured that future not-so-urgent things from you will get less attention than usual.

2. Send me an email, then call me two minutes later and start with "Hi, I just send you an email ....".
The second you say that, I am instantly annoyed and in the future probably won't answer the phone if I see your caller ID immediately after you sent me an email, because you obviously don't understand what email is for and how it should be used. I check my emails multiple times a day, everything gets read and answered within one day, nothing gets lost.

3. Send me an email about some urgent stuff, then don't answer my email with clarification questions.
This essentially tells me that whatever you label as urgent in the future really isn't urgent at all as soon as work or thoughts from your side are required.

4. Ask for something to get done until date X, get my answer that it isn't possible because the workload is much more than the available remaining days, then reply with "But it MUST be done, because blablablabla...".
I don't care much why it must be done. If I say it can't be done, I mean it, and I can't change the limits of time. I am really bored of always repeating the questions "what else can be postponed; what part of this can possibly be delivered later; ...". Isn't this common sense?? Just emphasizing the word "must" won't get your anywhere.

5. Forward me some email from a customer saying something like "How do I do [some-standard-task-that-is-fully-described-in-the-manual]".
I am not first level support, so please first try to find a solution yourself. If your email does not show any signs of effort from your side, I am not very inclined to make much effort myself.

6. Forward me some email from a customer saying something like "I get an error when trying to import file XY into the database".
Well, would you call your car mechanic, tell him "My car is making problems", and then expect him to provide a solution? No, you obviously would at least tell him what kind of problems your car is making. Similarly, but often surprisingly for many people, a software developers needs to know the actual error message! Even better, provide the actual file and step by step instructions on how to reproduce the problem.

7. Ask me to create a work-around for a problem in some other developer's software, because you are not comfortable directly asking that developer, either because he usually isn't as responsive and fast, or because you think his code quality is not that good and you fear more bugs are introduced with the fix.
I really don't care what the reason is. If one piece of software developed in our company is faulty, then it should be fixed in that software by its developer, not by creating work-arounds. If this is really such a big problem, ask me to talk to that developer, but don't ask me to do other people's work just for your convenience.

8. Call me on the phone for every minor problem or question.
Every phone call while I am doing development work costs me much more time than just the phone call itself because my thoughts are interrupted. Development is focused, concentrated brain work. Every interruption is a big time waster to that respect. I am sure your work is just as demanding and important, but the problem is that you outnumber me. You are not the only one that needs answers, explanations, estimations etc. from me. If everyone always phones me, I have a phone call every 10 minutes and don't get any actual work (yes, that includes the one you are probably waiting for) done. Just send me an email, so I can process everything in batches, and only call if it is really urgent.

9. Forward me emails or specifications in Dutch, Arabic or some other foreign language.
Just because my software is available in a dozen different languages for world-wide distribution doesn't mean that I personally speak all those languages. And even computer geeks are not able to extract all the relevant information from a specification document by just looking at the diagrams and database schema.

10. Talk to others about software bugs that had already been fixed and reappeared in a new release.
Even if the bug on the outside is similar to a bug that had already been resolved, this does not mean that the actual bug in the code is the same and has magically (or due to a developer's thoughtlessness or inability to use his version control system) been reintroduced. A non-working feature may be the result of totally different faulty parts of the code that make the same feature fail under different circumstances. At least have the courtesy to first talk to the developer about the problem before spreading word about reappearing bugs behind his back.

Saturday, August 11, 2007

Work on the important things, not on the urgent ones


I just heard an excerpt from an audio book by Tony Robbins that made me think about the work I am doing in the company I work for.

Tony pointed out that one usually works on what is urgent and important, which obviously is quite stressful, but most of the time an issue has only become urgent because it hasn't gotten the required attention while it was "only" important.

Like 99% percent of the self-help advice that you can find out there, this is just common sense, but speaking of myself, I need a reminder now and then to think about such things and rethink what I am doing and how I work.
In my company, urgent things appear all the time: CeBIT surprisingly shows up each year, but the sales department requests new demo software only a few days before. New technologies that we should look into are postponed again and again because of more urgent things, but inevitably at some point in the near future, an important customer will request this, and request it to be available in short time of course. Code refactorings, clean-up and documentation are postponed due to lack of time, until some months later an urgent change to the code then requires a multiple of that time because of the still messy or poorly documented code.
Again, this is all common sense, but it gets forgotten so easily during the usual busy days, when you struggle with other people's urgencies.

Time to switch over to my planning calender and schedule some weekly time to work on the important, but not so urgent tasks, no matter what urgent stuffs gets thrown at me ...

Friday, August 10, 2007

Use HMLView.dll on devices that come without that DLL

HTMLView.dll (together with its wrapper from OpenNETCF) is a nice control for displaying Html files, either local or from a web page, within your application. I use it for displaying context-sensitive online help (because the default Windows CE help system with PegHelp.exe doesn't fit well to my kiosk mode application). However some devices, namely the Psion Workabout Pro with Windows CE.NET 4.2, come without that DLL for whatever reason. After digging through the web with Google, I finally found this page that has a "htmlview dlls" download with all necessary files and settings (there is a bit more involved than just copying the Htmlview.dll file to the device). Also I had to copy the DLL files to my applications folder instead of the suggested WINDOWS\ folder (and change the registry import file accordingly) because the DLLs in the Windows folder got deleted again after each reset (there may be a way to prevent this, but I did not look into it any further due to lack of time).

Please note that I don't know about the legal issues involved with using those files. I still need to investigate this. So use at your own risk.

Thursday, August 9, 2007

Link tip: Deprecated APIs in Windows Mobile 5 and 6

There is an interesting new article on MSDN listing Deprecated APIs to Avoid Using in Windows Mobile 5.0 and Windows Mobile 6 Applications.

Logging mouse input in a Compact Framework application

Recently there was a bug in my Compact Framework 1.0 application that I wasn't able to reproduce, but that showed up regularly at a customer. Unfortunately the customer was not able to reproduce this on demand, but it happened every couple of days during standard operation in the field, while clicking around in the application. To get to know what the customer did, I implemented a log file of the mouse clicks using the Smart Device Framework 1.4 from OpenNETCF:


using OpenNETCF.Windows.Forms;
using OpenNETCF.Win32;

[...]
private MouseFilter mouseFilter = new MouseFilter();

[...]
static void Main()
{
ApplicationEx.Run(new Form1());
}

private void StartLogging();
{
mouseFilter.LoggedMessagesCount = 0;
ApplicationEx.AddMessageFilter(mouseFilter);
}

private void StopLogging();
{
ApplicationEx.RemoveMessageFilter(mouseFilter);
}



class MouseFilter : IMessageFilter
{
public static int LoggedMessagesMax = 1000;
public Message[] LoggedMessages =
new Message[LoggedMessagesMax];
public int[] LoggedMessageTimes =
new int[LoggedMessagesMax];
public int LoggedMessagesCount = 0;

#region IMessageFilter Members

public bool PreFilterMessage(ref Message m)
{
if (LoggedMessagesCount<LoggedMessagesMax)
{
switch(m.Msg)
{
case 0x0201:
case 0x0202:
case 0x0100:
case 0x0101:
case 0x0102:
Message aMsg =
LoggedMessages[LoggedMessagesCount];
aMsg.Msg = m.Msg;
aMsg.LParam = m.LParam;
aMsg.WParam = m.WParam;
aMsg.HWnd = m.HWnd;
LoggedMessageTimes[LoggedMessagesCount] =
Environment.TickCount;
LoggedMessagesCount++;
}
}
return false;
}
#endregion
}

The LoggedMessages array in the above code snippet stores the last 1000 mouse clicks, which I regularly save to a file, so that in case of a crash I can replay them to reproduce the problem.

Thursday, July 26, 2007

News: Visual Studio 2008 Beta 2 (Orcas) is available

Beta version 2 of Visual Studio 2008 a.k.a. Orcas is now available here. It includes Compact Framework 3.5, though I could not find any information whether the CF version has been updated over the previous beta 1. Information about what is new in CF 3.5 in general can be found here.
Also a video interview about Beta 2 is available on Channel 9.

Wednesday, July 25, 2007

Replace keyboard events in Compact Framework apps

Isn't it annoying that you have a KeyDown event for most controls, where you can check for the key that has been pressed and execute some actions, but you are not able to replace that key with some other key? I needed this for an application to replace the default behaviour of the Tab key (due to some weird hardware keyboard layout of the device I was developing for). Here is a quick way how to do that for a custom control (using theOnKeyDown event of a standard control works similarly):

using System.Runtime.InteropServices;

[...]

[DllImport("user32.dll")]
private static extern void keybd_event(
byte
bVk, byte bScan, int dwFlags, int dwExtraInfo);

protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
e.Handled = true;
keybd_event((byte)Keys.F4, 0, 0, 0);
return;
}
base.OnKeyDown(e);
}

Tuesday, July 24, 2007

Note to self: Get involved earlier


Every once in a while, a "very very urgent" development need pops up in our company, where something worth n days of work must be ready in n-x days, "else this big great tender/order/customer will be lost forever". Well, when I then review the emails and specifications about this task that are forwarded to me, I usually find dates on them showing that the information has been in my company for days, weeks or even months, but just hadn't made it to the development department.

If this sounds familiar: Try to establish a good relationship with the sales people, product marketing or project management (whoever is responsible in your company), and next time this kind of thing happens, ask them to CC or BBC you early on possible upcoming projects with deadlines attached to them, so that at least you are warned, or are able to ask what came out of the tender xy that was due last week. This may be outside of standard company policy where development does not get involved in that early stages of a project, and at first your colleagues may think (but not tell you) that you should care of your own business instead of messing with theirs, so you may need to make it absolutely clear that this is totally informal and that you are just interested in the big picture in order to better classify upcoming issues for dev department. A quick and smalltalk-like question about what is going on currently will also be beneficial when you have those colleagues on the phone anyway about some other things.

Link tip: Detect if you are connected to a network with Compact Framework

Richard Jones from the Mobile LOB Blog has posted a nice code snippet last month that I just came across, showing how to detect if your device currently has a network connection. Quite useful if for example you want to automatically start synchronizing data, or give the user an indication if this is possible right now or not.

Monday, July 23, 2007

Link tip: Symmetric encryption for Compact Framework

If you are interested in encryption for Compact Framework, check out the post

Symmetric Key Encryption on the Compact Framework

on the Windows Mobile Development blog.

Note that the above article doesn't mention it explicitely, but it is for Compact Framework 2.0. For Compact Framework 1.1 the used methods and classes are not available yet, but you can use similar ones from OpenNETCF's Smart Device Framework 1.4.

Saturday, July 21, 2007

Note to self: Request specifications without room for interpretation


I often (about 90% of the time) get specifications where some required features are roughly laid out, but miss details about GUI integration, input validation or something like this. If you can't get this information from the client (which in my case often is the sales department), make it perfectly clear that for everything that isn't specified in enough detail, you will create a solution to your best knowledge, and this area then later is no place that can be tagged as needing rework or bug fixing just because the customer now makes up his mind that he wants it to look different. Change requests are fine, but implementation of these changes can not be pre-condition for project sign-off if there wasn't a specification for them. Make it clear that those requests can be implemented later. And remember to make this clear BEFORE giving an actual workload estimation and of course before starting with implementation. I usually submit some requests for clarification, and if I don't receive a satisfying answer to some points within a reasonable time, I put an appropriate sentence in my email, stating that the workload estimation and current implementation plan is based on either not implementing features X and Y at all, or as the developer see fit, due to lack of detailed specification, and any change requests to this must be communicated within the next two days, else they will have to be treated as additional items for the roadmap, not for initial implementation phase, or the deadline must be rescheduled.

PS: I know that in an ideal world, someone (may be even me, if I just had the time) would write a technical specification from the initial specification, containing each and every detail of the planned implementation, including screen layouts for each screen, etc., so that there are no open loops or unspecified details at all. Well, I must admit that in the company I work for there is seldom the time to do so. We just don't have the man-power available. And if this sounds like a lame excuse to you, just leave me tips in the comments but don't just tell me "You must" :-)

Wednesday, July 18, 2007

A localizable date picker control for Compact Framework 1.0

Yesterday I needed to implement a date picker control for my CF application. While this is certainly no really difficult task to implement this from scratch, to save time I searched the web for available free solutions. I found plenty of samples how to use the native date picker or monthly calender control of WindowsCE, but all of them lack the ability to be localizable, i.e. to be able to translate the month identifiers and have the month names e.g. in Portuguese language while using a device with an English language operating system. Luckily I came across the following (rather old) sample code by Microsoft that implements a date picker completely in managed code, and I though I'd share this link:

Microsoft .NET Compact Framework-based DateTimePicker Control

It is quite easy to modify the code so that you are able to set the month identifiers. Just add the following method:


public void SetMonthName(int Month, string MonthName)
{
m_monthMenu.MenuItems[Month-1].Text = MonthName;
}

Tuesday, July 17, 2007

Use AutoIt to speed up non-coding tasks

Your IDE very probably has keyboard shortcuts and templates to speed up cranking out standard source code constructs. Typical work however usually involves a few more steps apart from producing code, and as soon as you leave the IDE, there are no time-saving shortcuts etc. anymore except maybe some batch files and shell scripts that you have created.

For example, my standard non-coding tasks include:

  1. update version history
  2. copy together the necessary files for an update release (i.e. all the files that have changed compared to the previous release) and create a setup package
  3. run some automatic tests on the setup package
  4. create an info file with details about the update (who did it? what is it for? what must be done before or after installation? etc.)
  5. upload software releases to our FTP server for testers or sales staff (in case of demos)
  6. send out emails notifying colleagues about uploaded files, or directly sending files to them by email

I was able to speed up most of the above tasks using AutoIt, which is an extremely powerful scripting engine for automating user input. Here are some examples that may not fit to your specific work, but might at least give you an idea why it is worth the effort to learn a script tool like AutoIt and use it:

Update version history:
After I have used an Excel sheet for this for some time, I noticed that for minor changes I was to lazy to start up Excel, which always takes a couple of seconds. I would just scribble the changes down on some paper or put it into some Notepad file, and hopefully some days later managed to go through these unsorted notes and put everything into the Excel file. While this is far from efficient, it is also quite error prone because sometimes I would forget or loose one of my notes, and sometimes I would have needed the history information when I hadn't found the time to move my notes over to the "official" version history. So finally I settled for simple plain text files for each product or module, with columns like "Date", "Time", "Author", "Category" separated by tabs. And I set up an AutoIt script with a global hotkey that allows me to append a new entry to the version history file with just a keypress. I created a script then when pressing Ctrl+Alt+H opens up an input box where I type in an identifier for the product I am working on, then an identifier for the category of the change (e.g. "+" means "new feature", "b" means bug fix, "i" means internal change), and the actual text. So after I fixed bug "Blablabla" in product "SuperApp", I would press Ctrl+Alt+H and type "s f Blablabla". The script will then automatically add a line like this to my version history for product Foo, while extracting the version number information from the .exe file along the way:

....
6.20.02 12/07/2007 09:29 TH + Added setup switch for option xyz
6.20.02 12/07/2007 09:29 TH I Refactored code for db table export
6.20.03 14/07/2007 14:11 TH F Blablabla


Here is my script for adding to the history of one of my Delphi applications or one of my CF applications (lets call them DelphiApp and CFApp). Note that for the Delphi app the script automatically extracts the version number from the .DOF file, and for the CFApp from the AssemblyInfo.cs file.

Func AddToHistory()
$input = ""
do
$input=InputBox("History for DelphiApp/CFApp",
"[D(elphiApp),C(fapp)][I(ntern),B(ugfix)," &
"+(New/changed)] [Text]",
$input)
$produkt=StringUpper(StringLeft($input,1))
$typ=StringUpper(StringMid($input,2,1))
$input=StringStripWS(StringMid($input,3),1)
until ($input="") or ($produkt="T") or ($produkt="P")
if ($input<>"") then
$Ver = ""
if ($produkt="D") then
FileCopy("S:\DelphiAppHistory.txt","S:\DelphiAppHistory.bak",1)
$file=FileOpen("S:\DelphiAppHistory.txt",1)
$MajorVer=IniRead("S:\DELPHIAPP.DOF","Version Info","MajorVer","0")
$MinorVer=IniRead("S:\DELPHIAPP.DOF","Version Info","MinorVer","0")
$Release=IniRead("S:\DELPHIAPP.DOF","Version Info","Release","0")
$Ver = $MajorVer & "." &amp;amp;amp; $MinorVer & "." & $Release;
else
FileCopy("S:\CFAppHistory.txt","T:\CFAppHistory.bak",1)
$file=FileOpen("T:\CFAppHistory.txt",1);
$assembly=FileOpen("T:\AssemblyInfo.cs",0)
While 1
$line = FileReadLine($assembly)
If @error = -1 Then ExitLoop
if (StringLeft($line,27)="[assembly: AssemblyVersion(") then
$Ver=StringMid($line,29,7)
ExitLoop
endif
Wend
FileClose($assembly)
endif
FileWriteLine($file, _NowDate() & " " &
StringLeft($Ver & " ",11) &
"TH " & $typ & " " & $input)
FileClose($file)
endif
EndFunc


Uploading a software update/release to our company's FTP server
Usually I have to upload my updates to a customer-specific folder on our company's FTP server, where I create a folder according to the current date and upload all the neccessary files into it, e.g. "2007-11-27\". In TotalCommander this means pressing F7 to create a folder, check the current date, type it in, press Enter to create the folder, press Enter, press Enter again to switch to that folder, select all files to upload, press F5 and Enter to start the upload. I have to do this about once a day. Of course it takes only seconds, but I still find it annoying :-) The AutoIt script looks like this:

Func MakeDateDir()
Send("{F7}" & StringReplace(_NowCalcDate(),"/","-") & "{ENTER}")
WinWaitActive("Total Commander")
Send("{ENTER}")
WinWaitActive("Total Commander")
Send("{TAB}{NumPadMult}{F5}")
WinWaitActive("Send")
Send("{ENTER}")
EndFunc

Monday, July 16, 2007

SD-Card problems revisited

Following up to my recent post on the problems I encountered when running my CF application from a SD-Card on a Psion Workabout Pro, I just stumbled across this older blog entry about SD-Cards from the Windows Mobile Team blog (I always seem to find information about a problem only a few days after I encountered it and searched the net without success) . The article explains why and under what circumstances SD-Cards get dismounted and all file handles invalidated after a suspend/resume. It boils down to the fact that the mobile device only waits for a certain amount of seconds for the SD-Card to re-initialize after a resume, and after that, it is assumed that the card isn't there or has been changed. So in my situation, may be the SD-Cards we used just were too slow, or some other process slowed down the device somewhat (see also the article's comments, that include some interesting information as well), or the device manufacturer set the timeout value too low (unfortunately, the time out can only be set by the manufacturer and not by just changing some registry settings).

So the fact remains that one should better not run applications (or keep open file handles) on a SD-Card. This indeed all makes sense for standard devices where SD-Cards can be removed easily. For the devices that I develop for, which are ruggedized, industry-grade devices, the SD-Card slot is usually not accessible from the outside, so it would be nice if it was possible to disable this automatic dismount after resume

Sunday, July 15, 2007

Debugging Compact Framework apps over ethernet or WiFi with Visual Studio 2005, without ActiveSync

Some mobile devices I develop software for don't have an USB port. They connect to the desktop via serial cable (which is so slow that one shouldn't even bother trying to use this kind of connection for debugging purpose) or via network cable. The network option works great for debugging with VS 2003: Just create an ActiveSync partnership using serial cable connection once, then use the fast network connection afterwards. It even works for WLan, so your device doesn't need to be connected to a cable or docking station for debuggin.
Now someone at Microsoft decided that for "security reasons", such an ActiveSync connection over network is not supported anymore by ActiveSync 4 (which is a requirement when using VS 2005). This literally means that it isn't available, not only that you need to turn on some options and ignore some security warning messages. Or is there some hack available that I don't know about? If yes, please let me now!
Well, here is the workaround. It is not nice, and not very comfortable, but at least it works:

How to: Connect to Windows CE Device Without ActiveSync

Note that as far as I know, you really need to use the command prompt of your device to run those tools. It may not work to just double-click them from file explorer. In case your older device does not have a command prompt, look here

Windows Mobile Developer Power Toys

I really wish Microsoft would have put a bit more thought into this and for example created some developer version of ActiveSync if they absolutely don't want network connectivity in the "official" version. On my developer machine, with a crossover cable connecting my device with my computer, I really don't care about any security issues with that connection. I just want fast debugging.

Link tip: Project management defined

FreelanceSwitch has a nice sarcastic article about project managers.

Funny reading, and sad at the same time because quite a few traits described here actually fit to PMs I have met as a developer over the past few years (current ones excluded) :-)