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,

 

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,