More "Getting started with managed code (C#) development for Windows Mobile" articles


Last year Chris Craft wrote this excellent "30 days of .NET" articles where he wrote 30 .NET applications in C# each day. I have gone through the initial few and plan to complete the list as and when I find time. He hasn't actually explained the code and the application logic in detail and that would surely be some task if you are doing 30 apps in 30 days (; You couldn't ask for more.

The source code for all the applications is available. So just download'em and dig through. There's no better way to learn than to dive-in and experiment.

author: TechTwaddle | posted @ Friday, November 20, 2009 5:53 AM | Feedback (0)

Windows Mobile 6.5 Gestures : Introduction (C++)


Found a nice article on Code Project about using gesture API's on Windows Mobile 6.5 devices.

Hit the link and give it a read. And off I go to try the program out.

Update:
Well, I gave the program a try and it works nicely. I have one concern however. When you double tap, you get a GID_SELECT message first and then GID_DOUBLESELECT, but what if I want to handle both messages differently? Like for example in a game where I want GID_SELECT and GID_DOUBLESELECT to do different things exclusively. I don't want the SELECT code executing when the user DOUBLESELECTs. Is this a valid concern?

author: TechTwaddle | posted @ Friday, November 20, 2009 5:38 AM | Feedback (0)

Windows Marketplace Now Available for Windows Mobile 6.0 and 6.1 "officially"


Windows Marketplace for mobile, which was up until now only available for Windows Mobile 6.5 users, is now officially made available for Windows Mobile 6.0 and 6.1 devices. This is great news since it adds almost the entire windows mobile user base to the marketplace equation in one scoop!

You can catch more details below:

Windows Marketplace for Windows Mobile 6.0 and 6.1

 

author: TechTwaddle | posted @ Monday, November 16, 2009 6:27 PM | Feedback (0)

Getting started with Windows Mobile Development : Managed Code


I stumbled across this series of posts by Maarten Struys and Dougturn on "Getting started with windows mobile development with Visual C#". I remember Joel too having mentioned it in one of his posts. I went through a couple of articles and was able to create a few basic applications in C#. I must mention that creating a basic application with your menus and a few controls takes no time at all in visual C#. The visual designer is nice, supports a lot more controls and takes care of things that you would usually have to write code for if you were developing in Win32/C++.

Here are the links to the series, and I suggest you read through them whenever you find time.

Part 1: Creating your first application

Part 2: Device Emulator and Device Emulator Manager

Part 3: Basic WinForm App development for Windows Mobile Devices

Part 4: Adding Custom Controls and Making Use of GPS Hardware

Part 5: Introduction to SQL Server CE

Part 6: Device Security and Application Deployment

Part 7: Mobile Web Development

 

author: TechTwaddle | posted @ Saturday, November 14, 2009 1:48 AM | Feedback (1)

Displaying a context menu in your application


Context menus really add to the user experience. You may decide to display a context popup menu when the user taps-and-holds or double-taps on the touch screen. In this post we will see how a few lines of code enable you to do just that.

While reading about popup menus I came across the WM_CONTEXTMENU message. According to the windows mobile documentation that I referred this message is sent to a window when the user right clicks on the window's client area. Since I haven't yet seen a windows mobile device which supports right click functionality, I decided to leave it at that. And for this demonstration I display my context menu whenever the user double clicks (or double taps) on the screen. Remember that for your window to recieve a WM_LBUTTONDBLCLK message when the user double clicks, you should set the CS_DBLCLKS style of your WNDCLASS structure when you do a RegisterClass(). Without this your window will not recieve the double click message.

If you are comfortable with the gesture api's, which Windows Mobile 6.5 supports, then you could use the GID_HOLD message. This message is sent when the user taps and holds on the screen for a specified amount of time.

When my main window recieves a WM_LBUTTONDBLCLK message, I call the following function:

//error checking omitted on purpose
POPUP_ITEMS pi[] = {
    {IDM_POPUP_ABOUT, TEXT("About")},
    {IDM_POPUP_EXIT, TEXT("Exit")}
};

int ShowContextMenu(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    POINT pt;
    pt.x = LOWORD(lParam);
    pt.y = HIWORD(lParam);

    ClientToScreen(hWnd, &pt);

    HMENU hMenu = CreatePopupMenu();

    for (int i=0; i< sizeof(pi)/sizeof(pi[0]); i++)
    {
        InsertMenu(hMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING | MF_ENABLED, pi[i].id, pi[i].szText);
    }

    return TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL);

}

The POPUP_ITEMS structure is defined to hold an integer and a string,

typedef struct _popup_items_
{
    int id;
    TCHAR szText[128];
} POPUP_ITEMS;

In the function, I first get the client co-ordinates of the point where the user double clicked and convert them to Screen co-ordinates. TrackPopupMenu() api, which displays the popup menu, expects the co-ordinates to be passed w.r.t the screen.

CreatePopupMenu() creates an empty menu. Use InsertMenu() api to add items into the menu and TrackPopupMenu() will display the popup menu.

When you set TPM_RETURNCMD flag in the call to TrackPopupMenu(), the function will return with the identifier of the menu item which the user selected. If the user clicks outside, without selecting anything, then the function simply returns zero. These functions are simple to use and the MSDN documentation will suffice. I have provided links to msdn above.

Finally, here is the video,


author: TechTwaddle | posted @ Friday, November 13, 2009 1:26 AM | Feedback (0)

How to change the text of a softkey menu?


To change the text of a softkey menu item, all you have to do is pretend that they are buttons. Well, they are specialized buttons in any case. So in order to change its property (in this case the 'text') you will have to use the TBBUTTONINFO structure along with TB_GETBUTTONINFO and TB_SETBUTTONINFO messages. Lets dive into the code:

Note: Error checking is omitted for obvious reasons.

    TCHAR szText[128] = TEXT("");
    TBBUTTONINFO tbi;
    ZeroMemory(&tbi, sizeof(tbi));

    tbi.cbSize = sizeof(tbi);
    tbi.dwMask = TBIF_TEXT | TBIF_COMMAND;
    tbi.pszText = szText;
    tbi.cchText = sizeof(szText);
    tbi.idCommand = IDM_MARK_UNMARK;

    SendMessage(g_hWndMenuBar, TB_GETBUTTONINFO, (WPARAM)IDM_MARK_UNMARK, (LPARAM)&tbi);

    if (!wcscmp(szText, L"Mark"))
    {
        wcscpy(szText, L"Unmark");
    }
    else
    {
        wcscpy(szText, L"Mark");
    }

    SendMessage(g_hWndMenuBar, TB_SETBUTTONINFO, (WPARAM)IDM_MARK_UNMARK, (LPARAM)&tbi);

So we fill up the TBBUTTONINFO structure and then send TB_GETBUTTONINFO message to the menu bar. After this call returns, szText will contain the text of the menu item. We switch the contents of szText and then send a TB_SETBUTTONINFO message. And the text on the menu item changes.

Couple of seasons back I was working on an application which let the user "Mark" and "Unmark" dates on a calendar control. It was for a smartphone, so I thought this technique is quite handy and just qualifies for a post.

Here is a video of it in action,





author: TechTwaddle | posted @ Monday, November 09, 2009 12:34 AM | Feedback (0)

Project Resistance for Windows Mobile and iPhone


Chris Tacke has undertaken "Project Resistance" and gives great insight on developing and deploying an application onto the Marketplace. Project Resistance is a simple utility application that allows the user to play with resistor color bands. Selecting a color band combination gives you the resistance in ohms and given a resistance in ohms it will show you the corresponding color band. You can follow and get more details here.

Another interesting thing is that Chris Tec is developing the same application for iPhone. This is great because, first, I don't know much about developing for iPhone, except that Objective-C looks weird, and second, it lets you compare the two platforms and find out how difficult or easy it is to get something done. You can get more details here.

Here is an excerpt from Chris Tec's blog to give you an idea:

"Unlike the Windows Mobile application which required a small amount of plumbing code to be developed in order to draw images with alpha transparency I was simply able to drag and drop the images onto my view within Interface Builder. The Cocoa Touch framework supports controls with transparency out of the box."

!

author: TechTwaddle | posted @ Tuesday, October 27, 2009 10:02 PM | Feedback (0)

Applications: Minesweeper approaches completion, slowly but steadily


So this weekend I got some time to push Minesweeper forward. You can now play a full game. Now that the basic game is up and running work needs to be done on other aspects. For now, here is a couple of clips:




and,



author: TechTwaddle | posted @ Sunday, October 25, 2009 7:02 AM | Feedback (0)

Applications: Getting device information (embedded exe, rapi and more)


I was working on this application which runs on the PC and gets information about the windows mobile device which is connected to the PC over active sync. Now there are a couple of ways in which you can do this:

1) Create a PC app which gets all the information using RAPI api's and displays it.

2) Create two binaries, one for the PC and one for the WinMob device. The PC app launches the WinMob app remotely using RAPI API's, the WinMob app runs and writes all the information it can gather into a file on the device. The PC app then remotely reads this file and displays it to the user. The let down is that you need to create/maintain two binaries but the advantage is that you are not limited to the RAPI api's, all device API's are at your disposal.

3) Create a PC app which uses the embedded exe approach. This is a bit loony but works (; And yes, this is what I used in my app.

Let me digress here for people who do not know about RapiConfig.exe. RapiConfig is tool that ships with the Windows Mobile SDK's and can be used to test out CSP's (Configuration Service Provider) by using provisioning XML's. RapiConfig works over Active Sync. So basically you run this tool from command line like:

C:\>RapiConfig /P config.xml

This command has the same effect as calling DMProcessConfigXML() API on the device with config.xml's contents.

And then I came across the DeviceInformation CSP. The DeviceInformation service provider, as the name gives it away, provides information about the device and it can also be used to set information but we won't go into that. So you give this service provider an XML like this:

<wap-provisioningdoc>
    <characteristic type="DeviceInformation">
       <parm-query name="OperatingSystem" />
       <parm-query name="OperatingSystemVersion" />
       <parm-query name="Product" />
       <parm-query name="ProductVersion" />
    </characteristic>
</wap-provisioningdoc>

and it spits out the response like this:

<wap-provisioningdoc>
    <characteristic type="DeviceInformation">
        <parm name="OperatingSystem" value="Microsoft Windows CE"/>
        <parm name="OperatingSystemVersion" value="Version 5.2 (Build 1235)"/>
        <parm name="Product" value="Windows Mobile® 6 Standard"/>
        <parm name="ProductVersion" value="CE OS 5.2.1235 (Build 17740.0.2.0)"/>
    </characteristic>
</wap-provisioningdoc>

So while developing this application I thought I could use some of RapiConfig. I shouldn't have to write everything from scratch. I'll just find out the SDK installation directory on the PC somehow, run this tool with my xml, parse the output xml and display it. But wait, what if the PC does not have the SDK installed. This simple application can't depend on that. And that is when I had this crazy idea of embedding RapiConfig.exe within my application (; I wrote up a small test app to find out if this approach would even work. It did. You can get the details here in my previous post.

So thats the way it works. The application first extracts the embedded RapiConfig exe and the xml file into the current directory where the app is running from. Then it runs RapiConfig passing it the extracted xml. After RapiConfig completes executing and terminates, it creates a RapiConfigOut.xml in the same directory. The application opens this output xml, parses it and displays the information to the user.

If no device is connected then RapiConfig keeps waiting for the device to connect. To prevent this I used a few RAPI api's in my application to find out if a device is connected using Active Sync, and only if it is, I launch RapiConfig exe. Otherwise, I display a message saying "Please make sure the device is connected.. blah bla"

A few points worth jotting down

(*) After extracting the RapiConfig exe, I was calling CreateProcess() on it to launch it:

wsprintf(lpCmdLine, L"/P %s", XML_FILENAME);
ret = CreateProcess(EXE_FILENAME, lpCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);

But this didn't work for me. The output XML was the exact same as the input xml, without any data. Launching the same extracted exe from command line worked! How was this possible? I tried a couple of things with SECURITY_ATTRIBUTES, inheriting handles etc but none worked. The documentation for CreateProcess() mentioned that the first parameter to it maybe be NULL, in that case lpCmdLine parameter should include the exe name. And when I gave this a try, it worked! So now you call CreateProcess() like below:

wsprintf(lpCmdLine, L"%s /P %s", EXE_FILENAME, XML_FILENAME);
ret = CreateProcess(NULL, lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &sui, &pi);


(*) Some while back I had tried to fiddle with RAPI. I had tried to launch an exe on device remotely from the PC. But it didn't work. Turns out I was calling CeRapiInit() incorrectly. I was calling it directly, not on any object but actually you need to call it on the IRapiSession interface. I should really be reading the documentation carefully before jumping to the code (;


Here are a few snapshots of the application, this is with craddled emulator.













Oh and the DeviceInformation doesn't give you the resolution of the device. I used CeGetSystemMetrics() to get that part of information. And if there is any other details that you would want on this app, please leave a comment.

Good day!

author: TechTwaddle | posted @ Thursday, October 22, 2009 11:09 PM | Feedback (2)

Applications: Appending text to a multiline Edit control


Today I was developing a small utility application where I needed to append some text to a multiline edit control. When I ran through the list of Edit control messages, I could not find any that could be used to append text. WM_SETTEXT was overwriting the previous contents. And doing a WM_GETTEXT first, appending to it and then WM_SETTEXT seemed like an overkill.

A little bit of searching led me to EM_REPLACESEL message. This message is used to replace the currently selected text in the edit control with the specified text but there's a bit more to it. If there is no selected text in the edit control then the specified text is inserted at the current caret position. Since what I was using was a read-only edit control this works for me but I am not sure if it will work in all cases. I wonder if we need a SETCARETPOS message. So anyways, here's how to append text in an edit control:

HWND hWndEdit = GetDlgItem(g_hDlg, IDC_EDIT_BOX);

SendMessage(hWndEdit, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)str);

author: TechTwaddle | posted @ Wednesday, October 21, 2009 12:46 AM | Feedback (0)