MobileA Better Approach to WinCE Forms, Part 2

A Better Approach to WinCE Forms, Part 2

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

In the last installment, you saw an approach to forms display which works quite well on HPC and PC Pro devices. However, on a PPC device (or for a really long form on the larger devices), we’d run out of screen real estate before we got all of the controls displayed. You may be wondering “What happens if you create and initialize more controls than fit on the screen?” It depends. Sometimes nothing really bad happens, other than the fact that you can’t see all of the controls in the bands. You can’t scroll them into view, though, and to be useful, bands and their controls must be visible. Here is one way you can handle forms that have more than a single screen’s worth of bands. This form in the PagedBands example organizes controls into sets of pages, through which the programmer controls navigation.

As you can see, PagedBands is builds on the DataBands example. For this reason, we won’t dissect the entire application. Instead, we’ll focus on the significant changes. First, let’s look at how we change the window title to let the user know which page of a multi page form they are viewing. Initially we set the window title to show that we are on page 1.

// load the app title from 
// the string table
LoadString( hInstance, 
            IDS_APP_TITLE, 
            szAppName, 
            sizeof(szAppName));
//append page# / of pages
wsprintf( szTitle, 
          TEXT("%s%s%i"), 
          szAppName, TEXT("-1/"),
          dim(structCmdBarInit) / NUM_CTRL_BANDS );
//create the window using this title string
hWnd = CreateWindow( szWindowClass, 
                     szTitle, WS_VISIBLE,
                     0, 0, CW_USEDEFAULT, 
                     CW_USEDEFAULT, 
                     NULL, NULL, hInstance, 
                     NULL);

In the PagedBands example, the total number of bands is an even multiple of the total number of pages. If this weren’t the case, we’d need to take this into account when calculating the number of pages. Here’s a code fragment that calculates the number of pages in a more general way.

iPartialPage = ( (dim(structCmdBarInit) % NUM_CTRL_BANDS) > 0 )? 1 : 0;
 iNumPages = dim(structCmdBarInit) / NUM_CTRL_BANDS + iPartialPage;

This fragment uses the modulus operator to see if there is a non zero remainder when you divide the total number of bands by the number of bands per screen. If there is, we add one page.

Though it appears to the user that they are “flipping through” the pages of the form, in reality, the previous CommandBands control must be destroyed and a new one created whenever there is a page change. This requires a few modifications to the CreateDataBands() function. Specifically, we have to add command bar buttons to navigate the form pages and we have to reset the window title to reflect the current page.

// Add menu to band 0 --wahoo
hwndBand = CommandBands_GetCommandBar (hwndCB, 0);
CommandBar_InsertMenubar (hwndBand, hInst, IDM_MENU, 0);

idBitmap = (int)LoadBitmap(hInst, MAKEINTRESOURCE(IDB_PREV_NEXT));
CommandBar_AddBitmap(hwndBand, NULL, idBitmap, 2, 0, 0);

//If there's only one page, here's how to 
// hide the next/prev buttons
iNumPages = dim(structCmdBarInit) / NUM_CTRL_BANDS;
if( dim(structCmdBarInit) % NUM_CTRL_BANDS)
{
      iNumPages++;
}

if( iNumPages == 1 )
{
      tbCmdButtons[0].fsState = TBSTATE_HIDDEN;
      tbCmdButtons[1].fsState = TBSTATE_HIDDEN;
}
//Add the buttons
i = CommandBar_AddButtons(hwndBand, 
                  sizeof(tbCmdButtons)/sizeof(TBBUTTON), tbCmdButtons);

First, we load the images for the “Next” and “Previous” buttons, and we add it to the CommandBar. We check to see if there is more than one page worth of fields for this form. If not, we set the navigation button’s initial state to TBSTATE_HIDDEN, which keeps them from becoming visible. Otherwise, they retain the TBSTATE_ENABLED, which is specified in the global structure, tbCmdButtons. This step is not necessary to the case at hand, but is included in the example because it could be very useful for dynamically composed forms. Finally, we add the buttons to the menu band of the CommandBands control.

When the user taps one of the navigation buttons, we get a WM_COMMAND message. This is an excerpt from the message switch in WndProc() that handles the button messages:

// switch the menu selections:
switch (wmId)
{
   //move backward one band page and reinit
    case IDM_VIEWPREVPAGE:
          iCurTopBand -=4;
          if(iCurTopBand < 0)
          {
              iCurTopBand = dim(structCmdBarInit) - NUM_CTRL_BANDS;
          }
          hwndCB = GetDlgItem( hWnd, IDC_BAND_BASE_ID );
          DestroyWindow( hwndCB );
          CreateDataBands(hWnd);
       break;

   //move forward one band page and reinit
    case IDM_VIEWNEXTPAGE:
          iCurTopBand +=4;
          if(iCurTopBand >= dim(structCmdBarInit))
         {
             iCurTopBand -= dim(structCmdBarInit);
          }
          hwndCB = GetDlgItem( hWnd, IDC_BAND_BASE_ID );
          DestroyWindow( hwndCB );
          CreateDataBands(hWnd);
       break;

The real work of the message handling code is to calculate the new value of iCurTopBand. This global variable is used as the index to the structure array that contains initialization information for the fields. When we get a page turning command from the user, we either add or subtract the number of field in a page from iCurTopBand. If we go beyond the beginning or end of the page range when we do this, then we add or subtract the total number of fields. This has the effect of allowing continuous rollover of pages in either direction.

Looking Ahead

Net time we’ll look at one more technique for displaying long forms, without using paging or tabbed dialogs. In the next example, you’ll learn how to create command bands that embed moveable, resizable controls.

The Source Code

Download the source code: PageBands.zip

About the Author

Nancy Nicolaisen is a software engineer who has designed and implemented highly modular Windows CE products that include features such as full remote diagnostics, CE-side data compression, dynamically constructed user interface, automatic screen size detection, entry time data validation.

In addition to writing for Developer.com, she has written several books including Making Win 32 Applications Mobile. She has also written numerous articles on programming technology for national publications including Dr. Dobbs, BYTE Magazine, Microsoft Systems Journal, PC Magazine; Computer Shopper, Windows Sources and Databased Advisor.

# # #

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories