Using The CE HTML Viewer Control To Create Powerful, Customized Presentations

In this final lesson of the series, you complete the our RAPI application by setting up to present data on the CE side of the connection. You create linkage between systems using an application on the CE side, MyHTMLViewer, which hosts an HTML viewer control.

The HTML viewer control is a tool that I consider to be a "gestalt" item. It enables a great many application strategies that are really much more than the sum of their parts. Though this application (like the rest of the exclusively CE-side code in this article series) is written in Win32, it could very easily be written in MFC for Windows CE. The code for implementing the HTML Viewer on the CE side is fairly spare, so the impact wouldn't be unconscionable, especially if the application were downloaded from the desktop side on demand and then deleted at the end of the invoked processing.

Table 1: Source Files for the MyHTMLViewer Example

Source File Name Header File Name Usage Listing Included
MyHtmlViewer.cpp MyHtmlViewer.h Implements HTML Viewer and displays downloaded file Yes
MyHtmlViewer.rc Resource.h Contains Application resources No
StdAfx.cpp StdAfx.h Standard Application Frameworks Support No

How The My HTMLViewer Application Works

There are two jobs you handle in MyHTMLViewer: You create the control, and then you populate it with data from the file you downloaded using the DesktopRAPIInvoker application. First, take a look at the creation of the control, which you do in response to the WM_CREATE message.

After you handle the normal CE window creation processing, you explicitly load the library that implements the HTML viewer control. You load using a global variable initialized with the name of the DLL. Here's the declaration, which appears at the top of the source file:

TCHAR const c_szHTMLControlLibrary[] = TEXT("htmlview.dll");

The reason that you didn't just link this library at compile time is that the HTML Viewer control isn't part of the core Windows CE system definition, so it may not be present on every platform. Explicit loading allows you to test for success before continuing with initialization processing.

After you load the HTML Viewer DLL, you initialize the control with a call to InitHTMLControl().

     hwndCB = CommandBar_Create(hInst, hWnd, 1);
     CommandBar_InsertMenubar(hwndCB, hInst, IDM_MENU, 0);
     CommandBar_AddAdornments(hwndCB, 0, 0);

            g_hInstHTMLCtrl = LoadLibrary(c_szHTMLControlLibrary);

With the library loaded and the control initialized, you are ready to create the HTML Viewer control. You do this with a call to CreateWindow(), passing DISPLAYCLASS as the class name parameter. Notice also, that when you create the HTML Viewer window, you set its upper edge just below the bottom of the command bar.

GetClientRect( hWnd, &rc ); +=CommandBar_Height(hwndCB);

hwndHtml = CreateWindow(DISPLAYCLASS, NULL,
                        WS_CHILD | WS_VISIBLE |
                        WS_VSCROLL | WS_CLIPSIBLINGS,
                        rc.left,, rc.right - rc.left,
                        rc.bottom -,
                        hWnd, (HMENU)IDC_MYHTMLVIEWER,
                        hInst, NULL);

You give the HTMLViewer control the initial focus with a call to SetFocus(), and you send the control the DTM_ENABLESHRINK. This message toggles the image display state of the control so that it sizes images to allow them to be displayed in the control at its current size. You follow this initialization with a call to your local function, PopulateHTMLViewer().

   PostMessage(hwndHtml, DTM_ENABLESHRINK, 0, g_bMakeFit);

You populate the control with text using the simple expedient of opening your downloaded file, clearing the control of preexisting content and then passing the file contents to the control.

void PopulateHTMLViewer()
   DWORD dwFileSize, dwHighWord, dwBytesWritten;
   PBYTE pbFileBuff;
   HANDLE hFile;
   BOOL bOk;

//Open the HTML file.
   hFile = CreateFile (TEXT("MyHTMLViewerText"), GENERIC_READ ,
                       FILE_SHARE_READ, NULL, OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL, NULL);
   //get the file size
   dwFileSize = GetFileSize(hFile, &dwHighWord );

   //buffer the file
   pbFileBuff = (PBYTE)LocalAlloc( LPTR, dwFileSize );
   if( !pbFileBuff )
      { return; }

   //read the file into the buffer
   ReadFile( hFile,(LPVOID)pbFileBuff, dwFileSize, &dwBytesWritten, NULL);

   //close the handle
   CloseHandle( hFile );

   //send html formatted text to the control
   bOk = SendMessage( hwndHtml, WM_SETTEXT, 0, (LPARAM)TEXT("") );
   SendMessage( hwndHtml, DTM_ADDTEXTW , 0, (LPARAM)pbFileBuff );
   //send end of source message
   SendMessage( hwndHtml, DTM_ENDOFSOURCE  , 0, 0 );

   //delete the buffer


Notice that you clear the control before adding the new content by sending the WM_SETTEXT message. This isn't strictly necessary in this case, but is included in the example as it is one of the few messages that is useful for the communicating with the HTML Viewer that is not prefixed "DTM_". Here is a list of HTML Viewer Control messages, along with their meanings and parameter settings.

Table 2: HTML Viewer Control Window Messages and Their Meanings

Message & Meaning wParam lParam
DTM_ADDTEXT: Add MBCS text (WPARAM) (BOOL) bPlainText; TRUE : Add plain text, FALSE: Add HTML; (LPARAM) (LPSTR) szText
DTM_ADDTEXTW: Add Unicode Text (WPARAM) (BOOL) bPlainText; TRUE : Add plain text, FALSE: Add HTML (LPARAM)(LPWSTR) szwText;
DTM_SETIMAGE: Associates a bitmap with an image 0 (LPARAM)(LPINLINEIMAGEINFO) lpInlineImageInfo
DTM_ENDOFSOURCE: Signal end of addition of content 0 0
DTM_ANCHOR: Jump to anchor named by MBCS string 0 (LPARAM)(LPSTR) szAnchor;
DTM_ANCHORW: Jump to anchor named by Unicode string 0 (LPARAM)(LPWSTR) szwAnchor;
DTM_ENABLESHRINK: Toggle "size to image" 0 0
DTM_IMAGEFAIL: Control can't load image identified by dwCookie 0 (LPARAM)(DWORD) dwCookie
DTM_SELECTALL: Select all the text in the current page 0 0

That's pretty much it. Note that any data that can be rendered by a simple HTML parser may be displayed in the HTMLViewer control. Maps, diagrams, digital imagery, and so forth could just as easily have been in your data file. No matter what sort of data you're downloading, always check for adequate space on the CE side before trying to send it. Also, to the extent possible, clean up after your application by removing any downloaded data that isn't absolutely necessary to preserve after the application terminates.

Looking Ahead

You may wonder what you could look ahead to, in the last lesson of a long series like this one. Here's what I hope: I hope you are looking ahead to the delight and satisfaction of creating new kinds of applications, alive with the spirit and promise of Windows CE's decentralized style of computing. Go forth, and prosper!

About the Author

Nancy Nicolaisen

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, and entry time data validation. In addition to writing for and CodeGuru, she has written several books, including Making Win 32 Applications Mobile.



  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date