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.

Using the ‘Open File’ and ‘Save File’ dialogs, GetOpenFileName and GetSaveFileName APIs

Recently, someone on the MSDN forum asked if there are any built-in ‘Open File’ and ‘Save File’ dialogs available in the Windows Mobile platform. The answer, of course, is yes. The APIs that get the task done are GetOpenFileName() and GetSaveFileName(). These APIs allow the user to select directories or files for opening or saving. I wrote a small application to demonstrate how to use these APIs. The application has a multiline edit control and menu options for opening or saving text files (see video at the end). When you open a text file, the files contents are shown on the edit control, and saving to a file writes the contents of the edit control to a user selected text file. Pretty simple.

First, lets take a look at GetOpenFileName() API, the DoOpenFile() method in the application reads the contents of the file and writes it to the edit control, here is the function: (error checking is left out, as usual)

1. Get the full path to the file
2. Read the contents of the file into a buffer
3. Convert the buffer into wide char
4. Display the wide chars on the edit control

BOOL DoOpenFile(HWND hDlg)
{
    TCHAR   szFile[MAX_PATH] = TEXT("\0");
    char    *szFileContent = NULL;
    OPENFILENAME   ofn;
    HANDLE hFile = INVALID_HANDLE_VALUE;
    DWORD dwFileSize = 0, bytesToRead = 0, bytesRead = 0;
   
    memset( &(ofn), 0, sizeof(ofn));
    ofn.lStructSize   = sizeof(ofn);
    ofn.hwndOwner = hDlg;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFilter = TEXT("Txt (*.txt)\0 *.txt\0");  
    ofn.lpstrTitle = TEXT("Open File");
    ofn.Flags = OFN_EXPLORER;

    //get the filename the user wants to open
    if (GetOpenFileName(&ofn))
    {
        //ofn.lpstrFile contains the full path to the file, get a handle to it
        hFile = CreateFile(ofn.lpstrFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

        if (hFile == INVALID_HANDLE_VALUE)
            return FALSE;

        //get file size in bytes
        dwFileSize = GetFileSize(hFile, NULL);

        szFileContent = (char*)malloc(dwFileSize+1);
       
        memset(szFileContent, 0, dwFileSize+1);

        //read the files contents into a buffer
        if (ReadFile(hFile, szFileContent, dwFileSize, &bytesRead, NULL))
        {
            TCHAR *wszTemp = NULL;
            HWND hEdit = NULL;

            wszTemp = (TCHAR*)malloc(bytesRead*sizeof(TCHAR));

            //convert the chars in buffer to wide chars
            mbstowcs(wszTemp, szFileContent, bytesRead);
            hEdit = GetDlgItem(hDlg, IDC_EDIT);

            //set the content of edit control
            SetWindowText(hEdit, wszTemp);

            free(wszTemp);
        }

        //free resources
        free(szFileContent);
        CloseHandle(hFile);
    }

    return TRUE;
}

The APIs and the OPENFILENAME structure are explained well in the MSDN documentation, so I am not going to repeat the same things here. Follow the links.

The DoSaveFile() method in the application allows the user to save the contents of edit control into a file, here is the code:

1. Get the full path to the file
2. Read the contents of edit control into a wide char buffer
3. Convert the wide char into char (multibyte string)
4. Write the chars to the file

BOOL DoSaveFile(HWND hDlg)
{
    TCHAR   szFile[MAX_PATH] = TEXT("\0");
    OPENFILENAME   ofn;
    HANDLE hFile = INVALID_HANDLE_VALUE;
   
    memset( &(ofn), 0, sizeof(ofn));
    ofn.lStructSize   = sizeof(ofn);
    ofn.hwndOwner = hDlg;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFilter = TEXT("Text (*.txt)\0*.txt\0");  
    ofn.lpstrTitle = TEXT("Save File As");
    ofn.Flags = OFN_HIDEREADONLY;
    ofn.lpstrDefExt = TEXT("txt");

    //get the filename the user wants to save to
    if (GetSaveFileName(&ofn))
    {
        HWND hEdit = NULL;
        DWORD dwTextLen = 0, bytesWritten = 0;
        TCHAR *wszEditText = NULL;
        char *szEditText = NULL;

        //ofn.lpstrFile contains the full path of the file, get a handle to it
        hFile = CreateFile(ofn.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

        if (hFile == INVALID_HANDLE_VALUE)
            return FALSE;

        hEdit = GetDlgItem(hDlg, IDC_EDIT);

        //get the text length of the edit controls contents
        dwTextLen = GetWindowTextLength(hEdit);

        wszEditText = (TCHAR*)malloc((dwTextLen+1)*sizeof(TCHAR));

        memset(wszEditText, 0, (dwTextLen+1)*sizeof(TCHAR));

        //read edit controls contents into buffer
        GetWindowText(hEdit, wszEditText, dwTextLen+1);

        szEditText = (char*)malloc(dwTextLen+1);
       
        //convert the wide char read from edit control to char
        wcstombs(szEditText, wszEditText, dwTextLen);

        //save the contents into file
        if (WriteFile(hFile, szEditText, dwTextLen, &bytesWritten, NULL))
        {
        }

        //free resources
        free(wszEditText);
        free(szEditText);
        CloseHandle(hFile);
    }
   
    return TRUE;
}

Here is a video demo of how things work,  

 

Fun with menus Part II, Radio Menu Items and CheckMenuRadioItem()

Previously – Fun with menus – Part I

A few days back I set about trying to get radio items into menus. This is helpful if you want only one of the items in the menu to be active at a time, say, for e.g. a "Select Level" popup menu which has "Level 1", "Level 2" and "Level 3" subitems and only one of them needs to be shown as active or currently selected. You get the idea. No? Here, this pic should help,

Radio Menu Items 

A bit of searching led me to the CheckMenuRadioItem() API, and I thought, this is simple. I just need to get the handle to the popup menu, and pass the identifier of the subitem I want selected. And done. Turns out ‘get the handle to the popup menu‘ part isn’t very straight forward.

For future references in this post, here is the menu bar and the popup menu that I used in the resource script (refer pic above)

the menubar,
IDR_MENU SHMENUBAR DISCARDABLE
BEGIN
    IDR_MENU_POPUP,
    2,
    I_IMAGENONE, IDM_OK, TBSTATE_ENABLED, TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE, IDS_OK, 0, NOMENU,
   
    I_IMAGENONE, IDR_MENU_POPUP, TBSTATE_ENABLED, TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE,
    IDS_MENU, 0, 0,
END

the popup menu,
IDR_MENU_POPUP MENU DISCARDABLE
BEGIN
    POPUP "Menu"
    BEGIN
        MENUITEM "Toolbox..",    IDM_MENU_TOOLBOX
        POPUP "Speed"
        BEGIN
            MENUITEM "8x",        IDM_MENU_8X
            MENUITEM "16x",        IDM_MENU_16X
            MENUITEM "32x",        IDM_MENU_32X
        END
        MENUITEM "Settings..",    IDM_MENU_SETTINGS
        MENUITEM SEPARATOR
        MENUITEM "Exit",        IDM_MENU_EXIT
    END
END

 

What I did wrong

I looked up the functions available with menus and it seemed easy, LoadMenu(), GetSubMenu() and CheckMenuRadioItem() should do the trick, so here is the handler for the menuitem ‘8x‘, under WM_COMMAND; the handler tries to set ‘8x‘ as the current selection,

case IDM_MENU_8X:
    {
        HMENU hMenu = NULL, hSubMenu = NULL, hSubSubMenu = NULL;

        //handle to the menu bar
        hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU_POPUP));

        if (hMenu)
        {
            TCHAR szText[128] = TEXT("");
            int i = -1;

            //handle to the menu "Menu"
            hSubMenu = GetSubMenu(hMenu, 0);

            MENUITEMINFO mii;

            ZeroMemory(&mii, sizeof(mii));
            mii.cbSize = sizeof(MENUITEMINFO);
            mii.fMask = MIIM_TYPE;
            mii.fType = MFT_STRING;
            mii.dwTypeData = szText;
            mii.cch = 127;
            i = GetMenuItemInfo(hSubMenu, 1, TRUE, &mii); // mii.dwTypeData = "Speed"

            ZeroMemory(&mii, sizeof(mii));
            mii.cbSize = sizeof(MENUITEMINFO);
            mii.fMask = MIIM_TYPE;
            mii.fType = MFT_STRING;
            mii.dwTypeData = szText;
            mii.cch = 127;

            //handle to the menu "Speed"
            hSubSubMenu = GetSubMenu(hSubMenu, 1);

            i = GetMenuItemInfo(hSubSubMenu, 1, TRUE, &mii); //mii.dwTypeData = "16X"

            i = CheckMenuRadioItem(hSubSubMenu, IDM_MENU_8X, IDM_MENU_32X, IDM_MENU_8X, MF_BYCOMMAND);
        }
    }
    break;
 

GetMenuItemInfo() api and MENUITEMINFO structure were used while debugging, just to make sure that the menu handles that I was getting were the right ones. All API calls LoadMenu(), GetSubMenu() and CheckMenuRadioItem() were successful, from the return values at least. There was one problem however, the radio item ‘dot’ never showed up. Then I tried to experiment a bit with getting menu handles by position, the result still the same. When I ran out of tricks to pull, I tried to set the radio menu using SetMenuItemInfo(), and a few random variations of GetSubMenu() by menu identifier and by position etc. Darn thing never showed up! It all meant one thing only, there must be something wrong with the menu handles themselves, even though they were valid.

The right way

So next I looked up the samples that ship with the SDK and found a CECamera sample that made use of radio menu items. From what I could tell, it looked like LoadMenu() isn’t the right way to get a handle to the main popup menu. Under WM_CREATE message when you are setting up the application and creating the menu bar using SHCreateMenuBar(), you also do the following,

            if (!SHCreateMenuBar(&mbi))
            {
                g_hWndMenuBar = NULL;
            }
            else
            {
                g_hWndMenuBar = mbi.hwndMB;
 

                //get a handle to the main popup menu
                g_hMainMenu = (HMENU)SendMessage(mbi.hwndMB, SHCMBM_GETSUBMENU, 0, IDR_MENU_POPUP);

                //set the default selection to 8x
                hSubMenu = GetSubMenu(g_hMainMenu, 1);
                CheckMenuRadioItem(hSubMenu, IDM_MENU_8X, IDM_MENU_32X, IDM_MENU_8X, MF_BYCOMMAND);
            }

 

So you send a message to the main menubar window, asking for the popup menu handle using SHCMBM_GETSUBMENU. g_hMainMenu and hSubMenu are both HMENU types. When the application showed up ‘8x‘ was selected by default. The handlers for 16x and 32x set themselves as the current selection, so under WM_COMMAND we have,

case IDM_MENU_8X:                   
    hSubMenu = GetSubMenu(g_hMainMenu, 1);
    CheckMenuRadioItem(hSubMenu, IDM_MENU_8X, IDM_MENU_32X, IDM_MENU_8X, MF_BYCOMMAND);
    break;

case IDM_MENU_16X:
    hSubMenu = GetSubMenu(g_hMainMenu, 1);
    CheckMenuRadioItem(hSubMenu, IDM_MENU_8X, IDM_MENU_32X, IDM_MENU_16X, MF_BYCOMMAND);
    break;

case IDM_MENU_32X:
    hSubMenu = GetSubMenu(g_hMainMenu, 1);
    CheckMenuRadioItem(hSubMenu, IDM_MENU_8X, IDM_MENU_32X, IDM_MENU_32X, MF_BYCOMMAND);
    break;
 

It worked. Video follows,

 

RSS Readers, Aggregators.. whats that again?

I am surprised by the number of people I meet who don’t know or have not heard about RSS Readers or Aggregators. So when I ask them "How do you keep track of news and blogs you follow?", they say "Well, I go to that website and check for updates". And I say to myself, "yes, the dinosaurs used to do the same".

So the timing of this Wired article couldn’t have been better,
How To Consume News Media