How Microsoft Lost the API War – by Joel Spolsky

Came across another gem of an article by Joel Spolsky. It’s a pretty old article written in June of 2004, has lot of tidbits and I really enjoyed reading it, so much in fact that I read it twice! So hit the link below and give it a read if you haven’t already,

How Microsoft Lost the API War – Joel Spolsky

excerpt,
"I first heard about this from one of the developers of the hit game SimCity, who told me that there was a critical bug in his application: it used memory right after freeing it, a major no-no that happened to work OK on DOS but would not work under Windows where memory that is freed is likely to be snatched up by another running application right away. The testers on the Windows team were going through various popular applications, testing them to make sure they worked OK, but SimCity kept crashing. They reported this to the Windows developers, who disassembled SimCity, stepped through it in a debugger, found the bug, and added special code that checked if SimCity was running, and if it did, ran the memory allocator in a special mode in which you could still use memory after freeing it."

 

Applications: Some more marble fun!

Well, yesterday night I was watching a tutorial on XNA when I came across this neat little trick. It was a simple XNA application with a Windows Phone logo in it and whenever the user clicked on the device the logo would move towards the click point, and I couldn’t resist experimenting with the marble (;

The code is written in C# using CF3.5. Here is a video of the demo,

 

You probably noticed the motion of the marble towards the click point (destination). The marble starts off with a high velocity and slows down as it reaches its destination. This is achieved by making the speed of the marble a function of the distance between marble’s current position and the destination, so as the marble approaches the destination point, the distance between them reduces and so does the speed, until it becomes zero.

More on the code and the logic behind it in the next post. What I’d like to do next is, instead of making the marble stop at the click point, it should continue to move beyond it, bounce around the screen a few times and eventually come to a stop after a while. Let’s see how that goes.

Applications: How to create a custom dialog box for Windows Mobile 6 (native)

Ashraf, on the MSDN forum, asks,

Is there a way to make a default choice for the messagebox that happens after a period of time if the user doesn’t choose (Clicked ) Yes or No buttons.

To elaborate, the requirement is to show a message box to the user with certain options to select, and if the user does not respond within a predefined time limit (say 8 seconds) then the message box must dismiss itself and select a default option. Now such a functionality is not available with the MessageBox() api, you will have to write your own custom dialog box.

Surely, creating a dialog box is quite a simple task using the DialogBox() api, and we have been creating full screen dialog boxes all the while. So how will this custom message box be any different? It’s not much different from a regular dialog box except for a few changes in its properties. First, it has a title bar but no buttons on the title bar (no ‘x’ or ‘ok’ button on the title bar), it doesn’t occupy full screen and it contains the controls that you put into it, thus justifying the title ‘custom’.

So in this post we create a custom dialog box with two buttons, ‘Black’ and ‘White’. The user is given 8 seconds to select one of those colours, if the user doesn’t make a selection in 8 seconds, the default option ‘Black’ is selected. Before going into the implementation here is a video of how the dialog box works;

Custom dialog box

To start off, add a new dialog resource into your application, size it appropriately and add whatever controls you need to the dialog. In my case, I added two static text labels and two buttons, as below;

CustomDialog_rsrc

Now we need to write up the window procedure for this dialog, here is the complete function;

BOOL CALLBACK CustomDialogProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
    int wmID, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    static int timeCount = 0;

    switch(uMessage)
    {
        case WM_INITDIALOG:
            {
                SHINITDLGINFO shidi;

                memset(&shidi, 0, sizeof(shidi));

                shidi.dwMask = SHIDIM_FLAGS;
                //shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
                shidi.dwFlags = SHIDIF_SIPDOWN | SHIDIF_EMPTYMENU;
                shidi.hDlg = hDlg;
                SHInitDialog(&shidi);

                SHDoneButton(hDlg, SHDB_HIDE);

                timeCount = 0;

                SetWindowText(GetDlgItem(hDlg, IDC_STATIC_TIME_REMAINING), L"Time remaining: 8 second(s)");
                SetTimer(hDlg, MY_TIMER, 1000, NULL);

            }
            return TRUE;

        case WM_COMMAND:
            {
                wmID = LOWORD(wParam);
                wmEvent = HIWORD(wParam);

                switch(wmID)
                {
                    case IDC_BUTTON_BLACK:

                        KillTimer(hDlg, MY_TIMER);
                        EndDialog(hDlg, IDC_BUTTON_BLACK);
                        break;
                    case IDC_BUTTON_WHITE:
                        KillTimer(hDlg, MY_TIMER);
                        EndDialog(hDlg, IDC_BUTTON_WHITE);
                        break;
                }
            }
            break;

        case WM_TIMER:
            {
                if (wParam == MY_TIMER)
                {
                    WCHAR wszText[128];
                    memset(&wszText, 0, sizeof(wszText));

                    timeCount++;

                    //8 seconds are over, dismiss the dialog, select def value
                    if (timeCount >= 8)
                    {
                        KillTimer(hDlg, MY_TIMER);
                        EndDialog(hDlg, IDC_BUTTON_BLACK_DEF);
                    }

                    wsprintf(wszText, L"Time remaining: %d second(s)", 8-timeCount);

                    SetWindowText(GetDlgItem(hDlg, IDC_STATIC_TIME_REMAINING), wszText);
                    UpdateWindow(GetDlgItem(hDlg, IDC_STATIC_TIME_REMAINING));
                }

            }
            break;
        case WM_PAINT:
            {
                hdc = BeginPaint(hDlg, &ps);

                EndPaint(hDlg, &ps);
            }
            break;

    }

    return FALSE;
}

The MSDN documentation mentions that you need to specify the flag WS_NONAVDONEBUTTON, but I got an error saying that the value could not be found, so we can ignore this for now. Next up, while calling SHInitDialog() for your custom dialog, make sure that you don’t specify SHDIF_DONEBUTTON in the dwFlags member of the SHINITDIALOG structure, this flag makes the ‘ok’ button appear on the dialog title bar. Finally, we need to call SHDoneButton() with SHDB_HIDE flag to, well, hide the Done button. The ‘Done’ button is the same as the ‘ok’ button, so this step might seem redundant, and the dialog works fine without calling SHDoneButton() too, but it’s better to stick with the documentation (; So you can see that we have followed all these steps above, under WM_INITDIALOG. We also setup a few things like a variable to keep track of the time, and setting off a one second timer.

Every time the timer fires, we receive a WM_TIMER message. We then update the static label displaying the amount of time left to the user. If 8 seconds go by without the user selecting any option, we kill the timer and end the dialog with IDC_BUTTON_BLACK_DEF. This is just a #define’d integer value, make sure it’s unique. You’ll see why this is important. If the user makes a selection, either Black or White, we kill the timer and end the dialog with the corresponding selection the user made, that is, either IDC_BUTTON_BLACK or IDC_BUTTON_WHITE.

Ok, so now our custom dialog is ready to be used. I invoke the custom dialog from a menu entry in the main window as below,

case IDM_MENU_CUSTOMDLG:
    {
        int ret = DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CUSTOM_DIALOG), hWnd, CustomDialogProc);

        switch(ret)
        {
            case IDC_BUTTON_BLACK_DEF:
                SetWindowText(g_hStaticSelection, L"You Selected: Black (default)");
                break;
            case IDC_BUTTON_BLACK:
                SetWindowText(g_hStaticSelection, L"You Selected: Black");
                break;

            case IDC_BUTTON_WHITE:
                SetWindowText(g_hStaticSelection, L"You Selected: White");
                break;
        }

        UpdateWindow(g_hStaticSelection);
    }
    break;

So you see why ending the dialog with the corresponding value was important, that’s what the DialogBox() api returns with. And in the main window I update a static text label to show which option was selected.

I cranked this out in about an hour, and unfortunately don’t have time for a managed C# version. That will have to be another post, if I manage to get it working that is (;

How to: Show wait cursor in managed and native code

WaitCursor  Someone on the MSDN forum asked about how to show a wait cursor, like when your application is loading or performing some (background) task. It’s pretty simple to show the wait cursor in both managed and native code, and in this post we will see just how.

Managed Code (C#)

Set Cursor.Current to Cursors.WaitCursor, and call Cursor.Show(). And to come back to normal cursor, set Cursor.Current to Cursors.Default and call Show() again. Below is a button handler for a sample app that I made, (watch the video below)

private void button1_Click(object sender, EventArgs e)
{
    lblProgress.Text = "Downloading ether…";
    lblProgress.Update();

    Cursor.Current = Cursors.WaitCursor;
    Cursor.Show();

    //do some processing
    for (int i = 0; i < 50; i++)
    {
        progressBar1.Value = 2 * (i + 1);
        Thread.Sleep(100);
    }

    Cursor.Current = Cursors.Default;
    Cursor.Show();

    lblProgress.Text = "Download complete.";
    lblProgress.Update();
}

Native Code

In native code, call SetCursor(LoadCursor(NULL, IDC_WAIT)); to show the wait cursor; and SetCursor(LoadCursor(NULL, IDC_ARROW)); to come back to normal. The same button handler for native version of the app is below,

case IDC_BUTTON_DOWNLOAD:
    {
        HWND temp;

        temp = GetDlgItem(hDlg, IDC_STATIC_PROGRESS);
        SetWindowText(temp, L"Downloading ether…");
        UpdateWindow(temp);

        SetCursor(LoadCursor(NULL, IDC_WAIT));

        temp = GetDlgItem(hDlg, IDC_PROGRESSBAR);
        for (int i=0; i<50; i++)
        {
            SendMessage(temp, PBM_SETPOS, (i+1)*2, 0);
            Sleep(100);
        }

        SetCursor(LoadCursor(NULL, IDC_ARROW));

        temp = GetDlgItem(hDlg, IDC_STATIC_PROGRESS);
        SetWindowText(temp, L"Download Complete.");
        UpdateWindow(temp);
    }
    break;

Here is a video of the sample app running. First the managed version is deployed and the native version next,

Applications: Colliding Marbles in C Sharp

If you follow this blog, you know how much I love marbles. I was staying up for Microsoft’s It’s Time To Share event and I thought I’ll write up a C# version of Colliding Marbles. It’s a pretty straight forward port from the native version, the only major difference being in the drawing primitives. Video follows. The solution was created using Visual Studio 2008 and the source code is shared below.

Source Code: CollidingMarbles.zip [Shared on SkyDrive]

Video, 

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.

Extracting Icon from an executable (name)

Remember the Process Viewer that we worked on a few months back? I was wondering how to display the applications icons, the way task manager does. A small icon beside the application name gives it a pleasant look. So how do you extract the icon from an executable? Well, there’s an API for that (pun). ExtractIconEx() is the function we use to get a handle to the applications icon. It’s a simple API, just give it the full path to the executable and it returns an HICON (icon handle). So I went back to my Process Viewer and added a static label to display the icon. Here is the code:

HICON hIcon, hIc;
hIcon = ExtractIconEx(filename, 0, NULL, &hIc, 1);

if(!hIcon)
{
    hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));
}

SendMessage(g_hStaticIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
 

If the handle returned is NULL (for applications without user interface) then we display a default icon, the terminal. After getting the icon handle, we set it on the label using STM_SETIMAGE message.

Now to the interesting part. An application can contain quite many icons as resources, so how does the system know which icon to return? The answer is that the system chooses the icon whose resource identifier value is the smallest and returns it as the application icon. So if I have three icons in my application whose identifiers are defined as: (in Resourceppc.h)

#define IDI_ICON1                       103
#define IDI_ICON2                       104
#define IDI_ICON3                       105

then the resource IDI_ICON1 will be returned.

Here is another interesting bit, the static label (in the video below) was created using CreateWindow() as follows:

g_hStaticIcon = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_ICON |
                          
SS_REALSIZEIMAGE, x, y, 16, 16, hWndParent, 0, g_hInst, NULL);
 

Now a static image label will expand itself if the image being displayed on it is bigger than the label size. This is what you wouldn’t want, imagine some application icons displayed in 16×16 pixels while others in 32×32. So to prevent this automatic scaling of the label we use the SS_REALSIZEIMAGE flag in the CreateWindow() call. But according to MSDN, SS_REALSIZEIMAGE is listed under "Unsupported static control styles".

If you have seen the video below already, then you’ll notice that the gwes.exe icon appears larger. There could be two reasons, either all other application’s icons are getting scaled down to 16×16 and gwes.exe’s isn’t (wonder why), or there is no scaling happening and all other applications are returning 16×16 icons while gwes is returning a larger 32×32 icon (unlikely). Now if I remove the SS_REALSIZEIMAGE flag while creating the label then all the icons are displayed big (32×32)! This means that scaling down is indeed happening and SS_REALSIZEIMAGE, although listed under ‘Unsupported static control styles‘, still works. I am a little confused as to why this is happening, if you got a clue then do let know.

Here’s the video:  

 

Displaying the icons like I did above is just the proof. Next step would be to display the icons right beside the application name (who needs serial number!), got to look at list views and images. And hopefully the image scaling problem should resolve itself with list_view images.

 

Fun with menus! update on Part I

If you remember Fun with menus! Part I, then you’ll also remember that we were able to get two different popup menus on the left and the right softkeys. Morin Marco contacted me through the same post and via email, explaining that the code wasn’t working for him. We had a few mail exchanges and exchanges on the post too. It wasn’t clear why the same code wasn’t working for him, until he sent the screen shots of his problem. Turns out he was trying the code on the latest emulator, Windows Mobile 6.5.3. And when I installed the 6.5.3 emulator and ran the code, the result was the same. Here are a few screen shots of the same code running on different emulators:

On the 6.5 emulator

  
 

 On the 6.5.3 emulator

   

So from what we concluded, the functionality has been disabled by Microsoft on the latest emulator, which is a good thing because having popup menus on the left and the right softkeys wasn’t recommended by them in the first place. 

Update 1:
See this MSDN forum thread.