Windows Phone 7 Series – Tools and Resources (updated)

  Unless you’ve been living in the caves of Lascaux for the past couple of days, you probably know what’s happening in the world of Windows Phone. Microsoft unveiled the developer tools required to develop applications and games for Windows Phone 7 at MIX10 a couple of days back. Silverlight and XNA being the major frameworks, no big surprise there. And the best news of all is that all the development tools are free! So if you are planning to develop apps for Windows Phone 7, read on.

The first place, or more appropriately hub, for you is the Windows Phone Developer Portal. It has most of the information you need to get you started. Now there is a ton of information available at other places too. In this post, I take time to put all the information that I found useful at one place, and I’ll keep updating this as and when I find new stuff.
 

Setting up the development environment

1. Install Windows Phone Developer Tools CTP (Community Technology Preview)
This will install Visual Studio 2010 Express, Silverlight, XNA 4.0 framework and emulator for Windows Phone 7. It also installs a few support tools.

2. Expression Blend 4 for Windows Phone:
    – Install Expression Blend 4 beta
    – Install Expression Blend Add-in Preview for Windows Phone
    – Install Expression Blend SDK Preview for Windows Phone

Installing the above tools should set your machine up for development. I installed the tools on my Windows Vista SP1 machine and the process went smoothly without running into any major hitch. Note that the tools won’t install on Windows XP, read the release notes of the CTP.

Resources and Documentation

1. Microsoft Windows Phone 7 Series Developer Training Kit

2. Programming Windows Phone 7 Series by Charles Petzold. Contains few chapters only. Gives a good preview.

3. MSDN documentation for Windows Phone 7 Development

4. A sample chapter from Learning Windows Phone Programming [PDF] by Yochay Kiriaty and Jaime Rodriguez. Complete book will be available at a later time.

5. Windows Phone 7 Developer Forum – where you can ask questions and problems you run into and the experts are there to help you.

6. For Silverlight visit silverlight.net and for XNA game development, the XNA Creators Club is the place to go, also make sure you follow Michael Klutcher’s and Shawn Hargreaves’ blog.

7. And finally the MIX’10 website. Most of the sessions will be available for download later (some are already available). Click on the Windows Phone tag to get all the session details and downloads.
 

If you are completely new to Silverlight and XNA (like me), and C# makes some sense to you then I suggest you go through the Developer Training Kit. It gives a good start and ramps you up pretty quickly.

Update:

8. Windows Phone FAQ’s
FAQ’s by Jaime Rodriguez, Dan Reagan, Rob Miles

9. Reddit entry for Windows Phone 7. Contains good links to blog posts and tutorials.

Transparency and AlphaBlending (Update: with source code)

In this post we’ll look at the AlphaBlend() api and how it can be used for semi-transparent blitting. AlphaBlend() takes a source device context and a destination device context (DC) and combines the bits in such a way that it gives a transparent effect. Follow the links for the msdn documentation.

So lets take a image like,

and AlphaBlend() it on our window. The code to do so is below, (under the WM_PAINT message of WndProc)

HBITMAP hBitmap=NULL, hBitmapOld=NULL;
HDC hMemDC=NULL;
BLENDFUNCTION bf;

hdc = BeginPaint(hWnd, &ps);

hMemDC = CreateCompatibleDC(hdc);

hBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
hBitmapOld = SelectObject(hMemDC, hBitmap);

bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 80; //transparency value between 0-255
bf.AlphaFormat = 0;   

AlphaBlend(hdc, 0, 25, 240, 100, hMemDC, 0, 0, 240, 100, bf);

SelectObject(hMemDC, hBitmapOld);

DeleteDC(hMemDC);
DeleteObject(hBitmap);

EndPaint(hWnd, &ps);
 

The code above creates a memory DC (hMemDC) using CreateCompatibleDC(), loads a bitmap onto the memory DC and AlphaBlends it on the device DC (hdc), with a transparency value of 80. The result is:

Pretty simple till now. Now lets try to do something a little more exciting. Lets get two images involved, each overlapping the other, giving a better demonstration of transparency. I am also going to add a few buttons so that the user can increase or decrease the transparency by clicking on the buttons. Since this is the first time I played around with GDI apis, I ran into something that everybody runs into sometime or the other, flickering. When clicking the buttons the images would flicker a lot, I figured out why and used something called double buffering to avoid flickering. We will look at both my first implementation and the second implementation just to give the concept a little more depth and perspective.

A few pre-conditions before I dive into the code:

hBitmap and hBitmap2 are handles to the two images obtained using LoadBitmap(), these variables are global and are initialized under WM_CREATE

– The two buttons in the application are labeled Opaque++ (make more opaque, less transparent) and Opaque– (make less opaque, more transparent)

DrawPics(HWND hWnd, int step=0); is the function called to draw the images on the screen. This is called from under WM_PAINT and also when the buttons are clicked. When Opaque++ is clicked the ‘step‘ value passed to DrawPics() is +20 and when Opaque– is clicked the ‘step‘ value is -20. The default value of ‘step‘ is 0. The value of ‘step‘ specifies the amount by which you want to change the transparency.

Now lets take a look at my first implementation:

//this funciton causes flicker, cos it draws directly to screen several times
void DrawPics(HWND hWnd, int step)
{
    HDC hdc=NULL, hMemDC=NULL;
    BLENDFUNCTION bf;
    static UINT32 transparency = 100;

    //no point in drawing when transparency is 0 and user clicks Opaque–
    if (transparency == 0 && step < 0)
        return;

    //no point in drawing when transparency is 240 (opaque) and user clicks Opaque++
    if (transparency == 240 && step > 0)
        return;
   
    hdc = GetDC(hWnd);

    //create a memory DC
    hMemDC = CreateCompatibleDC(hdc);

    //while increasing transparency, clear the contents of screen
    if (step < 0)
    {
        RECT rect = {0, 0, 240, 200};
        FillRect(hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
    }

    SelectObject(hMemDC, hBitmap2);

    BitBlt(hdc, 0, 25, 240, 100, hMemDC, 0, 0, SRCCOPY);
   
    SelectObject(hMemDC, hBitmap);

    transparency += step;

    if (transparency >= 240)
        transparency = 240;

    if (transparency <= 0)
        transparency = 0;

    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = transparency;
    bf.AlphaFormat = 0;   
   
    AlphaBlend(hdc, 0, 75, 240, 100, hMemDC, 0, 0, 240, 100, bf);

    DeleteDC(hMemDC);
    ReleaseDC(hWnd, hdc);
}
 

In the code above, we first get the window DC using GetDC() and create a memory DC using CreateCompatibleDC(). Then we select hBitmap2 onto the memory DC and Blt it on the window DC (hdc). Next, we select the other image, hBitmap, onto memory DC and AlphaBlend() it over window DC. As I told you before, this implementation causes flickering because it draws directly on the screen (hdc) several times. The video below shows what happens when the buttons were clicked rapidly:

Well, the video recording tool I use captures only 15 frames per second and so the flickering is not visible in the video. So you’re gonna have to trust me on this, it flickers (;

To solve this problem we make sure that the drawing to the screen happens only once and to do that we create an additional memory DC, hTempDC. We perform all our drawing on this memory DC and finally when it is ready we Blt hTempDC on hdc, and the images are displayed in one go. Here is the code for our new DrawPics() function:

//no flicker
void DrawPics(HWND hWnd, int step)
{
    HDC hdc=NULL, hMemDC=NULL, hTempDC=NULL;
    BLENDFUNCTION bf;
    HBITMAP hBitmapTemp=NULL, hBitmapOld=NULL;
    static UINT32 transparency = 100;

    //no point in drawing when transparency is 0 and user clicks Opaque–
    if (transparency == 0 && step < 0)
        return;

    //no point in drawing when transparency is 240 (opaque) and user clicks Opaque++
    if (transparency == 240 && step > 0)
        return;
   
    hdc = GetDC(hWnd);

    hMemDC = CreateCompatibleDC(hdc);
    hTempDC = CreateCompatibleDC(hdc);

    hBitmapTemp = CreateCompatibleBitmap(hdc, 240, 150);
    hBitmapOld = (HBITMAP)SelectObject(hTempDC, hBitmapTemp);

    //while increasing transparency, clear the contents
    if (step < 0)
    {
        RECT rect = {0, 0, 240, 150};
        FillRect(hTempDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
    }

    SelectObject(hMemDC, hBitmap2);

    //Blt hBitmap2 directly to hTempDC
    BitBlt(hTempDC, 0, 0, 240, 100, hMemDC, 0, 0, SRCCOPY);
   
    SelectObject(hMemDC, hBitmap);

    transparency += step;

    if (transparency >= 240)
        transparency = 240;

    if (transparency <= 0)
        transparency = 0;

    bf.BlendOp = AC_SRC_OVER;
    bf.BlendFlags = 0;
    bf.SourceConstantAlpha = transparency;
    bf.AlphaFormat = 0;   
   
    AlphaBlend(hTempDC, 0, 50, 240, 100, hMemDC, 0, 0, 240, 100, bf);

    //now hTempDC is ready, blt it directly on hdc
    BitBlt(hdc, 0, 25, 240, 150, hTempDC, 0, 0, SRCCOPY);

    SelectObject(hTempDC, hBitmapOld);

    DeleteObject(hBitmapTemp);
    DeleteDC(hMemDC);
    DeleteDC(hTempDC);

    ReleaseDC(hWnd, hdc);
}
 

This function is very similar to the first version, except for the use of hTempDC. Another point to note is the use of CreateCompatibleBitmap(). When a memory device context is created using CreateCompatibleDC(), the context is exactly one monochrome pixel high and one monochrome pixel wide. So in order for us to draw anything onto hTempDC, we first have to set a bitmap on it. We use CreateCompatibleBitmap() to create a bitmap of required dimension (240×150 above), and then select this bitmap onto hTempDC. Think of it as utilizing an extra canvas, drawing everything on the canvas and finally transferring the contents to the display in one scoop. And with this version the flickering is gone, video follows:

 

If you want the entire solutions source code then leave a message, I will share the code over SkyDrive.

Update: I have shared the source code of this application on SkyDrive. The solution was created using Visual Studio 2008 and has been tested on Windows Mobile 6 Professional Emulator. The link follows,

Source Code: AlphaBlending.zip

 

Applications: Using the System Clipboard in Windows Mobile

Recently, someone on the MSDN forum asked about using ‘Cut, Copy and Paste’ operation in their application and I thought it makes for a worthy post. Using the system clipboard is pretty easy. This article has everything you need know. Basically, the clipboard operations are performed in the following order:

Copy
1. Open Clipboard
2. Empty Clipboard’s contents
3. Set the Clipboard’s data
4. Close Clipboard

Paste
1. Open Clipboard
2. Check if Clipboard data is available
3. Get the Clipboard data
4. Close Clipboard

Cut operation is the same as Copy but you also delete the data from the source. It is upto your application to do that.

The sample application that I built handles only ‘text’ clipboard data and consists of two multiline edit boxes, the top one serving as the source and the bottom as destination for all clipboard operations. Lets look at how the application works, and then we’ll look at the code:

For Copy, Paste and Cut, the following handlers are called:

//DoCopy
void DoCopy(HWND hDlg)
{
    BOOL ret;
    HWND hTemp;
    TCHAR *pData = NULL;
    int size = 0;

    hTemp = GetDlgItem(hDlg, IDC_EDIT_TOP);

    _ASSERT(hTemp != NULL);
    if (!hTemp)
        return;

    //get the size of text in the edit box
    size = SendMessage(hTemp, WM_GETTEXTLENGTH, 0, 0);

    pData = (TCHAR*)LocalAlloc(LPTR, size*sizeof(TCHAR) + 1);

    _ASSERT(pData != NULL);
    if (!pData)
        return;

    SendMessage(hTemp, WM_GETTEXT, (WPARAM)size+1, (LPARAM)pData);

    ret = OpenClipboard(hDlg);

    _ASSERT(ret != 0);
    if (ret == 0)
        return;

    EmptyClipboard();

    if (!SetClipboardData(CF_UNICODETEXT, pData))
    {
        _ASSERT(FALSE);
    }

    CloseClipboard();
}

//DoPaste
void DoPaste(HWND hDlg)
{
    BOOL ret;
    TCHAR *pData = NULL;

    ret = OpenClipboard(hDlg);
    _ASSERT(ret != 0);
    if (ret == 0)
        return;

    ret = IsClipboardFormatAvailable(CF_UNICODETEXT);
    if (ret == 0)
    {
        CloseClipboard();
        return;
    }

    pData = (TCHAR*)GetClipboardData(CF_UNICODETEXT);

    if (pData)
    {
        SendMessage(GetDlgItem(hDlg, IDC_EDIT_BOTTOM), WM_SETTEXT, 0, (LPARAM)pData);
    }

    CloseClipboard();
}

//DoCut
void DoCut(HWND hDlg)
{
    DoCopy(hDlg);

    SendMessage(GetDlgItem(hDlg, IDC_EDIT_TOP), WM_SETTEXT, 0, (LPARAM)(TEXT("")));
}

The code is simple enough to understand. All the Clipboard functions can be found here.