Utilizing Pocket IE Functionality in Mobile Applications

Most PDAs come with prewired Internet Explorer. Its versions may be different, or a vendor may decide that its device doesn’t need it al all. But, when it does exist, it’s just natural to use its capabilities, isn’t it? In this article, we will discuss how to do it on different types of PDA and WinCE flavors.

Using HtlmControl

Even on very old devices with OS Palm Size PC 2.11, you have htmlview.dll (and respectively, htmlview.lib). This stuff is continuing to appear on all Pocket PC devices, such as PPC 2000, PPC 2002, and so forth. Well, not all devices with 1/4 VGA screens are from the “Pocket PC” family, but we will discuss them later in this article. Coming back to HtmlControl, below are the steps you need to complete to obtain browser functionality:

  • Include htmlctrl.h to your project
  • Initialize the HTML control by calling the InitHTMLControl function
  • Create a window for the HTML control by calling the CreateWindow function with DISPLAYNAME as a window class name parameter
  • Handle WM_NOTIFY messages for NM_HOTSPOT and NM_INLINE_IMAGE codes
  • Link your application with htmlview.lib

As you may guess, there is nothing too complicated here. The stuff that is not mentioned above is downloading data from Web sites according to links and displaying images on the screen. And besides, don’t expect any support for JScript, frames, and analogous features. HTML Control provides just basic browser functionality. All the rest is up to you.

But, that’s enough theory. Let’s take a look at a simple code sample to illustrate HTML Control usage. Below are parts of a sample project. For simplicity, the HTML Control object is inherited from CStatic class.

// Initialize HTML Control
BOOL CHtmlCtrlApp::InitInstance()
{
     InitHTMLControl(AfxGetInstanceHandle());
     CHtmlCtrlDlg dlg;
     m_pMainWnd    = &dlg;
     int nResponse = dlg.DoModal();
     return FALSE;
}

// Create Html Control Window and make some initialization
void CHtmlView::CreateHtmlWindow(CRect& rect)
{
     DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
     CString sInfo;

     m_hwndHtml = ::CreateWindow (DISPLAYCLASS,//DISPLAYCLASS,
                                  NULL,
                                  dwStyle,
                                  rect.left,
                                  rect.top,
                                  rect.right,
                                  rect.bottom,
                                  m_hWnd,
                                  0,
                                  AfxGetInstanceHandle(),
                                  NULL);

     ::SetWindowLong(m_hwndHtml,GWL_ID,12321);
     ::SetFocus (m_hwndHtml);
     ::SendMessage(m_hwndHtml,WM_SETTEXT,0,(LPARAM)(LPCTSTR)_T(""));
}
// Handle notification messages
LRESULT CHtmlView::WindowProc(UINT message, WPARAM wParam,
                              LPARAM lParam)
{
   switch(message)
   {
   case WM_NOTIFY:
      NM_HTMLVIEW * pnmHTML = (NM_HTMLVIEW *) lParam;
      LPNMHDR pnmh = (LPNMHDR) &(pnmHTML->hdr);

      switch(pnmh->code)

      {
      case NM_HOTSPOT:
         OnLink(pnmHTML->szTarget);
      break;
      case NM_INLINE_IMAGE:
           OnInlineImage(pnmHTML->szTarget,pnmHTML->dwCookie);
      }
   }

   return CStatic::WindowProc(message, wParam, lParam);
}

// Download html page from selected target site
void CHtmlView::OnLink(const CString &strHref)
{
   TCHAR *szHtml = NULL;

   // Here you actually put the code to download HTML page into
   // szHtml
   ...

   // And finally command HTML Control to show it
   ::SendMessage(m_hwndHtml, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)NULL);
   ::SendMessage(m_hwndHtml, DTM_ADDTEXTW, FALSE,
                (LPARAM)(LPCTSTR)szHtml);
   ::SendMessage(m_hwndHtml, DTM_ENDOFSOURCE, 0, 0);
}

// Loading images
void CHtmlView::OnInlineImage(const CString &strHref, DWORD dwCookie)
{
   // Here handle image loading
   ...
   // Set image if all is OK
   if ( bImageLoadedOK )
   {
   INLINEIMAGEINFO imageInfo;
   imageInfo.dwCookie    = dwCookieValue;
   imageInfo.bOwnBitmap  = FALSE;
   imageInfo.hbm         = (HBITMAP)(*pBitmap);
   CSize size            = pBitmap->GetBitmapDimension();
   imageInfo.iOrigWidth  = size.cx;
   imageInfo.iOrigHeight = size.cy;
   ::SendMessage(m_hwndHtml, DTM_SETIMAGE, 0, (LPARAM)
                (INLINEIMAGEINFO*)&imageInfo);
   }
   // Otherwise, send failure message
   else
      ::SendMessage(m_hwndHtml, DTM_IMAGEFAIL, 0, (LPARAM)
                   (LPINLINEIMAGEINFO)dwCookieValue);
}

...
// And finally ...
BOOL CHtmlCtrlDlg::OnInitDialog()
{
   ...
   // m_htmlView is pointer to CHtmlView class
   if (m_htmlView->SubclassDlgItem(IDC_HTMLVIEW,this))
   {
      // do some initialization if needed
   }
   ...
}

Well, the code above initiates and creates CHtmlView object, and creates HtmlView window. By calling the SubclassDlgItem function, it’s connected to the Static control’s window. Thus, that’s a convenient way to use a placeholder in the Resource editor. After a HTML Control window is created, it is able to display HTML pages. Also, it receives notifications when the user taps on links or some image should be shown. All details regarding downloading pages or images are ommited in this sample, so you may implement it as is more comfortable for you. For images, you may think about some kind of cache, to avoid odd network traffic for the same data. The following picture presents the resulting output of this sample:

IWebBrowser2 interface

For PDA devices running Windows CE.NET (not from Pocket PC family), e.g. Fujitsu iPAD, there is an opportunity to use the IWebBrowser2 interface. That’s good news because this interface takes care of a lot of things. If you have used it on a PC, you’ll feel pretty comfortable here. A code snippet below shows how to create an instance of IWebBrowser2:

...
#include <exdisp.h>
// an instance of IWebBrowser2
IWebBrowser2 *m_pBrowserApp;
...
void CBrowser::Init(CRect rect,CWnd *pWnd)
{
   //Create the control window
   if(!CreateControl(CLSID_WebBrowser, NULL, WS_VISIBLE|WS_CHILD,
      rect,pWnd,AFX_IDW_PANE_FIRST))
   {
      m_pBrowserApp=NULL;
      DestroyWindow();
   }
   LPUNKNOWN lpUnk = GetControlUnknown();
   HRESULT hr = lpUnk->QueryInterface(IID_IWebBrowser2, (void**)
           &m_pBrowserApp);
   if(!SUCCEEDED(hr))
   {
      m_pBrowserApp = NULL;
      DestroyWindow();
   }
}

With this interface, you get most of a desktop browser’s functionality. “Most”—because of regular WinCE restrictions. If you need to capture events from a browser, you may implement the DWebBrowserEvents2 interface. There are a lot of articles on the Web about IWebBrowser-related stuff, so I will not enter into these issues. In any case, you life is easy enough in such an environment.

Conclusions

Using either HTML Control or IWebBrowser2, you may make your applications much more powerful and attracive. Have fun!

About the Author

Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers’ lives in the mobile jungles a little bit simpler.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read