Rich UI vs User Experience

John Montgomery and Jon Udell are having a discussion about AJAX and rich internet applications. Montgomery is trying to determine what all the fuss over AJAX is about. He played with some toolkits and is unimpressed. Why? He doesn’t see how AJAX can compete with Winforms/Webforms on user experience. John says:

Mostly, Jon’Â’s posts got me to thinking about why we (that’Â’s you and me -– Web users) are OK with degraded user experiences. I mean, for years we had great desktop applications to do things like calendaring and email and even mapping software. Then came the initial Web, where HTML 3.2 and some JavaScript meant that Web apps just couldn’Â’t be as nice as local apps. And now we’Â’re all very excited about things like Evite, Gmail, and Google maps. But compare Google Maps to Streets and Trips, which I did recently, and the experience with S&T is much better. Same with Outlook vs. Gmail (usually, anyway). Heck, most people read blogs through a Web browser, not an aggregator, even though aggregators are much more efficient.

So why do we let ourselves settle?

I think he is confusing user experience for rich widgets. Web-based applications can achieve a high level of user experience and usability without the need for complex widgets. Good web applications are simple, small and well focused to the task at hand. In fact, I always use the web versions of the applications he lists over the desktop versions.

As John points out, the web-style hyperlink approach, with few options and everything laid out in front of the user, is easy to learn and use. To me, this increases user experience, not degrade it. John also points out that content is more plentiful in web-based applications and users like getting content. So much so that he feels users are willing to give up a great UI if they can get great content. Why does a user want a great UI at all? Seems to me that users only really care about content (or data). I think usability experts like Nielsen and Cooper would say a great UI is a UI that allows users to complete tasks without getting in the way. The UI should not be centerstage.

Udell’s posts point out that AJAX systems have a tendency to allow users access to content they want in ways the web-UI did not anticipate. Also seeming to confirm my suspicion that users don’t care much for flashy UI’s, but graviate to applications that make it easy to extract and manipulate content. WebDAV and SOAP are not low-hurdle technologies, XmlHttpRequest seems to be. AJAX is a methodology for enhancing web application functionality, not for replicating desktop applications. People don’t want desktop applications running in the browser, didn’t Java teach us that?

XML File Formats in Office 12

Brian Jones, program manager on the Word team posted news about the new XML file formats in Office 12. I have posted a few times on XML file formats, so I am interested in what Office is doing. Some interesting points:

  • Full fidelity. As good as the binary format.
  • Compressed. Lots of file parts stored in a structured ZIP archive, similar to OpenDocument
  • Fully documented. Whitepapers, documentation and XSD schemas.
  • Robust. A lot less likely to get a corrupt file that can’t have pieces recovered.

IMO, the above points could be true for any product using an XML package format, but the fact that Office is doing it means millions of users can escape the data roach motel.

Scoble has more on Channel 9 as well as his own blog. Jones plans to link to whitepapers as soon as they become available on MSDN.

Granted, Office is following OpenDocument here, but this is a really good thing.

MSHTML Hosting – Drawing On WebBrowser

Hosting the WebBrowser in your application makes it easy to create slick-looking textual UI’s. HTML is a fairly expressive markup language and the results can be very professional with little difficulty. The graphical side is a little less impressive. Thankfully, SVG and VML (native support in the WebBrowser control) go a long way to fill the gap. Both have capabilities that blow away good old Win32 GDI drawing. Even so, there may be times that you wish you could grab an HDC for the WebBrowser control and start drawing on it. The WebBrowser control actually has a system built into it that allows you to do just that.

IHTMLPainter is part of a system in MSHTML called Binary Behaviors. Behaviors can do lots of cool stuff. Painters are a special kind of behavior called a rendering behavior. IHTMLPainter::Draw is called by MSHTML before or after the HTML content is rendered allowing you to draw below or above the content. MSHTML passes an HDC into method that you can use with any GDI or GDI+ drawing function. Basically, behaviors are COM objects that you implement and are associated with HTML elements, either in the HTML itself using CSS or progammatically using addBehavior. The MSDN has a nice tutorial on creating a rendering behavior that includes sample code.

XML Services In Desktop Applications

It’s pretty fair to say that I’d like to change the way I write desktop applications. I am tired of the UI framework lockin that comes with traditional desktop development. I’ve posted a couple times about using DHTML+SVG to create a desktop application UI. I have been working on prototypes in DHTML+SVG, as well as Laszlo (server-less deployment is now available) and Xamlon (they have a cool new flash-based system in addition to the .NET system).

I am now focusing my attention on non-UI parts of desktop applications and how Web-like techniques could be applied. Desktop applications, large ones specifically, are usually composed of subsystems that are exposed to the user via a host client. IMO, it’s important to componentize these subsystems and get them to interact in a way that does not tightly couple them together. Sounds a lot like the definition of a Web service. One way of doing this in C++ is using abstract base classes as interfaces. I am beginning to find this method too object-oriented for my tastes. The sheer number of interfaces required to support the subsystem can be quite large. Interfaces usually cause a language lockin as well. C++ abstract base classes cannot be used very easily by other languages, unless your willing to completely wrap your interfaces with proxy code.

I am leaning more towards an XML services approach. Each subsystem would have a single entry point which would dispatch XML messages (in a RESTful sorta way) throughout the rest of the subsystem. This approach feels just like Web-based services and has the same kind of benefits. Just about any language can immediately start using the subsystem with minimal effort. The subsystem’s dispatch entry point could be made HTTP-aware and suddenly gain the benefits of a true Web service:

  • Subsystems can be put on different machines.
  • HTTP techniques can be used to increase scalability and robustness.
  • Many different and special-use clients can be created which leverage the subsystem.

The kind of subsystems I am referring to include parsers, graph renders, expression evaluators, report generators, data converters and data analysis systems. These are examples of systems that should be made well-defined islands and have great potential for reuse. Instead, they are locked up into the UI client and can not be integrated into other solutions.

MSHTML Hosting – More Tricks

Here are a couple miscellaneous tips for using the WebBrowser while in design (edit) mode.

Setting Focus In Design Mode

With the WebBrowser control in design mode, there are times that focus (and the blinking cursor) are not set correctly. For example, with focus in the editor, ALT+TAB away from your application, and then back again. Focus may not be set back into the editor. Here is a simple way to fix it. Put this code in an event or message handler that gets called when your application is re-activated:


IHTMLDocument2* pHTMLDoc2 = ...;
IHTMLWindow2* pWindow = 0;
pHtmlDoc2->get_parentWindow(&spWindow);
if (pWindow) {
  pWindow->focus();
  pWindow->Release();
}

Unselecting Current Selection

IHTMLTxtRange has a method to easily select a range of text, but there is no simple method to unselect an existing text selection. Here is a simple way to do it:


IHTMLDocument2* pHTMLDoc2 = ...;
IHTMLSelectionObject* pSelection = 0;
pHTMLDoc2->get_selection(&pSelection);
if (pSelection) {
  IDispatch* pDispRange = 0;
  pSelection->createRange(&pDispRange);

  IHTMLTxtRange* pTxtRange = 0;
  pDispRange->QueryInterface(IID_IHTMLTxtRange, (void**)&pTxtRange);
  if (pTxtRange) {
    VARIANT_BOOL bSuccess;
    pTxtRange->execCommand(CComBSTR(L"Unselect"), VARIANT_FALSE, CComVariant(), &bSuccess);
    pTxtRange->Release();
  }
  pDispRange->Release();
  pSelection->Release();
}

SVG & DHTML Applications

I have been tinkering a lot lately with the concept of writing DHTML-based desktop applications running in a custom web browser. The custom browser would be made to look like the host shell of a standard Windows application with normal menus and toolbars. One of the pieces missing from DHTML applications in the past has been the lack of a graphics rendering system. Scalable Vector Graphics (SVG) fills this hole nicely. In fact, SVG will create graphics that rival any graphics library, desktop or otherwise. If you have not played with SVG, you owe it to yourself to have a look.

Besides static graphic rendering, SVG also builds on all the dynamic concepts in DHTML. SVG elements can have attached event handlers for mouse and keyboard events, among others. Javascript can be used to handle any of the events. SVG elements can also be animated very easily.

Currently, SVG is supported in MSHTML/WebBrowser via ActiveX viewers from Adobe and Corel. Mozilla/Firefox browsers will have native support sometime in 2005.

I think it is also worth mentioning the MSHTML/WebBrowser does support a native graphic markup language called Vector Markup Language (VML), which predates SVG and is very similar in design. If you want to natively support graphics (No ActiveX), you should consider VML.

MSHTML Hosting – Editing Tricks

Show Table Borders

This is a little feature like you find in MS Word. It will display table invisible borders in light gray color so you can see the structure of the table even if borders are turned off. The feature only works when the WebBrowser is in design mode. Since it’s an IOleCommandTarget editing command ID, it’s quite simple to use:


IHTMLDocument2* pDoc = ...;

// Turn on editor mode
pDoc->put_designMode(CComBSTR(L"on"));

// Execute some commands
IOleCommandTarget* pCmdTarget = 0;
hr = pDoc->QueryInterface(IID_IOleCommandTarget, (void**)&pCmdTarget);
if (SUCCEEDED(hr)) {
  pCmdTarget->Exec(&CGID_MSHTML, IDM_SHOWZEROBORDERATDESIGNTIME,
                   OLECMDEXECOPT_DONTPROMPTUSER, CComVariant(true), NULL);
  pCmdTarget->Release();
}

Note the MSDN lists editing ID’s separately from regular ID’s.

Use DIV for Paragraph Breaks

Normally, when you press ENTER in design mode, WebBrowser will insert a paragraph tag, <P>, as a break. This can create large amounts whitespace between paragraphs since <P> tags are rendered with more padding than a simple line break. You can setup a CSS class or a style change the padding or you could tell WebBrowser to use <DIV> tags instead. There are two ways I know of to get WebBrowser to use <DIV> tags:

MSHTML Hosting – More Editing

Previously I talked about exposing the HTML editor hiding inside the WebBrowser control. I also talked about IOleCommandTarget and how you can control formatting and layout features of the editor. It won’t take long before you discover that the IOleCommandTarget command ID’s are somewhat limited. At some point, you will need to insert specialized text or HTML at the current cursor location or replacing the current selection. Luckily for us, there is an easy way to do it: IHTMLTxtRange.

I talked about IHTMLTxtRange in a previous post. It is useful for finding text or getting the text of the current selection. It can also do the reverse: It can insert text or HTML at the current cursor location or selection using the pasteHTML method. Here’s a simple example:


IHTMLDocument2* pDoc = ...;

IHTMLSelectionObject* pSelection = 0;
HRESULT hr = pDoc->get_selection(&pSelection);
if (SUCCEEDED(hr)) {
   IDispatch* pDispRange = 0;
   hr = pSelection->createRange(&pDispRange);
   if (SUCCEEDED(hr)) {
      IHTMLTxtRange* pTextRange = 0;
      hr = pDispRange->QueryInterface(IID_IHTMLTxtRange, (void**)&pTextRange);
      if (SUCCEEDED(hr)) {
         CComBSTR sText = L"This is <b>better</b> text";
         pTextRange->get_pasteHTML(sText);
         pTextRange->Release();
      }
      pDispRange->Release();
   }
   pSelection->Release();
}

pDoc->Release();

In the above example, the selection may have selected text or it may just be a cursor location. The HTML overwrites any selected text. Otherwise, it’s inserted at the cursor location.

Overall, IHTMLTxtRange is a very useful interface. I have used it for implementing spell check, find/replace and inserting complex HTML. Just to be clear, IHTMLTxtRange works when design mode is off or on. The WebBrowser control does not need to be in edit mode to call pasteHTML.

Hello JavaScript

Coming from a C++ background, I found JavaScript very comfortable when I started doing DHTML programming. I was impressed with some of the things it could do with properties and functions. Other dynamic languages, Python and Ruby for example, have been getting lots of press lately while JavaScript has been quietly powering the Web.

That seems to be changing. I am reading a lot more about JavaScript. This is due in large part to Google’s GMail and Suggest (how it works). These are great examples of what can be done with DHTML and created a lot of buzz. The JavaScript Weblog posted a summary of predictions that seem to be shared by others.

Go JavaScript!