Putting the web into the client
One of the components I'm putting into my client side application is the web browser control to display HTML data to the user. With everyone becoming familiar with how to surf the web it seems that some of the most intuitive interfaces can be put together using the web browser control. This way I can create a portal into the application and customize the text that appears in addition to trapping clicks and links to invoke menu commands.
Sounds cool... huh?
The web browser control that is provided with MFC is a wrapper to the Internet Explorer COM object. The basic implementation of adding web surfing ability to the client side application is easy. Of course, displaying static web pages is not what I want to do. Displaying static web pages is easy. I can even add an HTML resource to the application and just populate the control with that information. Well that's sort of what I want to do but it's only part of the problem.
My vision is to use the web browser control in several places. The easiest though, is as a small pane that will display some additional information about configuration (policy) settings. When a user clicks on an element in one pane, I want the HTML pane to display the setting selected, it's current value and a detailed description of what the element is capable of doing when configured.
So for this first test I want a simple little HTML page that makes things look nice for the administrator. However the class framework is implemented in such a way that it would load the page but not easily give me the text string that represents the HTML source that is being displayed. Would be nice, then I can just modify it and go to town. Instead, once the source is loaded I have to use another COM object to grab the HTML source, replace some of my keywords with the real data and then set the new source back into the second COM object to be displayed in the first. Thank you Microsoft.
Now I work on web stuff including CGI to provide dynamic data on the server to feed back to the client. That is trivial. Well now that I know how to do the modification of the HTML source at run time I can do some funky things.
void CDocumentHtml::OnNavigateComplete2(LPCTSTR strURL)
{
LPDISPATCH lpDispatch = NULL;
IHTMLDocument2* pHtmlDoc2;
lpDispatch = GetHtmlDocument();
HRESULT hr=lpDispatch->QueryInterface
(IID_IHTMLDocument2, (void**)
&pHtmlDoc2);
if ( pHtmlDoc2 != NULL && hr == S_OK )
{
BSTR bstrTxt;
CString strText;
IHTMLElement *pBodyElement;
int nLockState;
CMyDocument* pDoc = ( CMyDocument* )GetDocument();
PolicyElement* pElement = pDoc->GetPolicyByName( "NamePolicy" );
CString strResource;
if ( pElement == NULL )
{
pHtmlDoc2->Release();
return;
}
hr = pHtmlDoc2->get_body( &pBodyElement );
pBodyElement->get_innerHTML( &bstrTxt );
strText.Format( _T("%s"), bstrTxt );
strResource = _T( "banner.gif" );
strText.Replace( _T( "[image]" ), ( LPCTSTR )strResource );
pBodyElement->put_innerHTML( strText.AllocSysString() );
pBodyElement->Release();
}
pHtmlDoc2->Release();
CHtmlView::OnNavigateComplete2(strURL);
}
Of course that's not where it ends. Since the HtmlView COM wrapper wraps up Internet Explorer there are a lot of functions that need to be pre-empted. First is the context menu that appears when the user right-clicks on the web page. In this little description view there really isn't any need to allow the user to navigate back in forth or view properties on my HTML source. Since I'm using HTML freshly made when the user clicks on an element there is really no reason to allow the user to refresh the content. And finally me favorite, do I really need to give the adminstrator the option to print my small HTML content? I think not.
To prevent the user from pressing the accelerator keys to do a refresh or navigation use this code:
BOOL CDocumentHtml::PreTranslateMessage(MSG* pMsg)
{
if ( pMsg->message == WM_KEYDOWN )
{
return 0;
}
return CHtmlView::PreTranslateMessage(pMsg);
}
To disable the context menu put this in the HTML resource:
<BODY oncontextmenu="return false">
Note that this popular example code does not work:
PreTranslateMessage(MSG* pMsg) handler:
if ( pMsg->message == WM_RBUTTONDOWN )
{
MessageBox(NULL, "Sorry, the right-click is disabled", MB_OK);
return 0;
}
Well it works if you want to display a message box, since the loss of focus to the HTML window will cancel the menu. However if you don't want to display the message box this won't prevent the context menu from being shown.
|
|
This article explains why (links off site)
|
|
|
To customize the web browser control in its basic COM classes you need to do something similiar to what this knowledge base article explains:
|
|
Read the KB article (links off site)
|
|
|
The other down side to this approach is that I need to be creative with my HTML skills to add the shading, borders and images to make it look... well less boring. Yeah it's an administrator application but does it really have to look dull. The plan is to have people spend serious money for the awesomeness that are these tools.
To really get things looking cool here is how to use the res: protocol to display bitmap resources in the html page of a CHtmlView class.
res://<appname>.<exe|dll>/#2/#<resource id number>
Now since this is an ISC application to run on Windows, the default COM object that uses Internet Explorer is the right choice. Thanks to Microsoft wanting to rule the world I know that each windows desktop will have the core components for this object to work. I have seen on the web debates as to why people are using IE for this type of interface instead of something more powerful, say Mozilla. While I would prefer to use Mozilla and will probably do so for my own application development where similiar views will be use, keeping it simple is the best decision when targeting fortune 500 companies. These companies already have invested large amounts into Microsoft whether you like to believe that or not. The ROI I'm looking for here is to make the product easy to run from the start with out having to make the IT department run through hoops.
While doing some research on the web I found a person and/or group that is working on a Mozilla COM object to get more people off of the defacto giberish from Microsoft and on to a more powerful web tool. I've included a link to a web page that talks about that progress and how to use it in the MFC framework so it can be a drop in replacement.
|
|
The Mozilla Control (links off site)
|
|
|

