HTML -- The MFC-Way...



Click here for a larger image.

Environment: VC6 SP5, NT4 SP6, dao350 (mdac_typ20), IE5.5

Introduction

When I develop an application, I always search for nice skins; it sells, you know. I found an article on MSDN from Paul DiLasca, here, in which he describes how to use CHtmlView as a part of the application (in this example, as an About-Box). The advantages are clear: easy professional design, nice effects (Marquee, Overscreen...), resizeable forms, display JPGs and GIFs, and so on.

The disadvantage is that you need Internet Explorer® on your system. To demonstrate this technology, I wrote a small program named "Personal Knowledge Base." In this program you can collect files, store them compressed in the database, and with some explaining, add text and keywords for searching. I have tested the program with all my downloads from CodeGuru...

NOTE: It's DAO350 !!! If the application can't open a database, please install mdac_typ20.exe.

Now let's go...

How to Realize an Interaction between the Shown HTML Content and the Logic in the Application

  1. Bring the HTML code inside your EXE: Modify your resource file like this:
  2. //in PKG.rc
    START.HTML        HTML    DISCARDABLE     "res\\start.html"
    BG.GIF            HTML    DISCARDABLE     "res\\bg.gif"
    TITLE.GIF         HTML    DISCARDABLE     "res\\title.gif"
    CONT.HTML         HTML    DISCARDABLE     "res\\cont.html"
    BIN.HTML          HTML    DISCARDABLE     "res\\bin.html"
    LSTHEADER.HTML    HTML    DISCARDABLE     "res\\lstheade.htm"
    LST.HTML          HTML    DISCARDABLE     "res\\lst.html"
    

    It's important to use real file names as resource names so the browser can find them. Note that all files I need for the HTML pages are imported in this way.

    Note: I don't know why, but my Visual Studio crashes sometimes while importing HTML files. It's better that you edit your Resource File manually.

  3. Load and show these resources in the HtmlView:
  4. void CYourHtmlView::OnInitialUpdate()
    {
        LoadFromResource(_T("start.html"));    //that's all
    }
    

    But you have to give your browser a little help to find the content by adding the following code at the top of your HTML file:

    <BASE url="res://PKB.exe/start.html">
    

    This tells the browser that the current "directory" is res://PKB.exe.

  5. Interaction between your application and the browser: To access the content of your browser directly, you have to import the IE Typelibrary like this in your stdafx.h:
  6. #pragma warning(disable:4192)
    #pragma warning(disable:4049)
    #import "C:\WINNT\system32\mshtml.tlb"
    
    1. The program changes the content of your HTML page dynamically (DHTML): All the elements you want to change must have an unique id. After the document is loaded completely, you can access each element like this:
    2. //in derived CHtmlView-Class
      MSHTML::IHTMLDocument2Ptr pDoc(GetHtmlDocument());
      MSHTML::IHTMLElementPtr e(pDoc->Getall()->item
                               (_T("someElement")));
      e->PutinnerText(_T("someText"));
      //or
      e->PutinnerHTML(_T("<b>someText</b>"));
      

      To get elements inside frames, look in the source for the function ProcessContentPage. (It's a little bit tricky to find exactly the point when all frames are completely loaded.)

    3. Catch an event in the HTML page to interact with your code: Here, Paul DiLasca is my "hero." I customized his idea a little bit, so that it's pretty easy to invent new commands to be "sent" from JavaSript code to your application. Let's see an example of the JavaScript code:
    4. function onSomeButtonClicked()
      {
          document.location.href="app:buttonPressed";
          //or my way
          document.location.href="app:1000";
          //the number corresponds with a #define in my
          //C++ code
      }
      

      Paul DiLasca invented a pseudo-protocol called "app:". Now you can catch this "event" when you override CHtmlView::OnBeforeNavigate2. The rest is simple. Here is my code:

      void CRightView::OnBeforeNavigate2(LPCTSTR lpszURL,
                       DWORD nFlags,
                       LPCTSTR lpszTargetFrameName,
                       CByteArray& baPostedData,
                       LPCTSTR lpszHeaders,
                       BOOL* pbCancel)
      {
          if(!_strnicmp(BROWSER_TO_APP, lpszURL, strlen
                       (BROWSER_TO_APP)))
          {
              *pbCancel=TRUE;    //important to cancel the
                                 //navigation !!!
              ProcessBrowerCmds(lpszURL + strlen
                               (BROWSER_TO_APP));
          }
          CHtmlView::OnBeforeNavigate2(lpszURL, nFlags,
                     lpszTargetFrameName, baPostedData,
                     lpszHeaders, pbCancel);
      }
      
      BOOL CRightView::ProcessBrowerCmds(const char* lpszCmd)
      {
          BOOL bRet=FALSE;
        int iCmd=atoi(lpszCmd);
        switch(iCmd)
        {
          default:
            ASSERT(FALSE);
            //some code here...
            break;
      
            case CMD_OPEN_DOC:
              //some code here...
              break;
      
            case CMD_ADD_DOC:
              //some code here...
              break;
      
            case CMD_SAVE_DOC:
              //some code here...
              break;
      
            case CMD_DEL_DOC:
              //some code here...
              break;
      
            case CMD_CONTEXTMENU:
              //some code here to exchange the standard
              //explorer context menu with your own menu
              //(look in cont.html for more details)
              break;
          }
          return bRet;
      }
      

It's like programming in Visual Basic®...........

PS: Have look on the macros in the CDaoUti Class. I think they can be useful for your work with DAO.

Acknowledgements:

Thanks, Paul DiLasca, for your ideas. I used a lot of code thar was downloaded from this site. Thanks, all, particularly to Tadeusz Dracz for his class CZipArchive!!!

Downloads

Download demo project - 184 Kb
By the way, the user for the demo is "system", no password...
Download source - 634 Kb


Comments

  • Multiple views and multiple tabs

    Posted by Legacy on 01/26/2004 12:00am

    Originally posted by: Ajay Sonawane

    I am using CHtmlView class to implement the internet browser in a tab control. The tabs in tab control are created dynamically when the user clicks on a link.It means that the new page will be opened in a new tab...So that user can easly navigate between these tabs.For this purpose , I am creating the objects of CHtmlView class and attaching it to tab.
    My problem is that when I call the method GoBack()
    And GoForward()..It Doesn't work.I think that the there might be some problem in History.
    Can anyone help me for this proble..?

    Reply
  • Runtime Error on Line 374 of PKB.CPP

    Posted by Legacy on 11/16/2002 12:00am

    Originally posted by: Neville Franks

    Hi Thomas,
    When I run PKB I get a Msg Box with:
    "Modul:[path]\pkb.cpp / line 374
    Msg: Unknown error 0x800A0BD4
    Can't start your application. The workgroup information file is missing or opened exclusively by another user".

    I've traced this down in the Debugger to:
    _DBEngine::CreateWorkspace() which fails.

    I'm running WinXP and have compiled against DAO350.DLL

    This happens in your Demo Download and when I build from the source.

    I've very interested in the techniques you've put together for accessing MSHTML. Maybe a simpler article without DAO would have been better. Thanks for the article.

    Reply
  • Why reinventing the wheel?

    Posted by Legacy on 11/13/2002 12:00am

    Originally posted by: Fabian

    The best skinning tool you will find is from far ActiveSkin (from www.softshape.com). It allows you to skin any window of your own. To even skin the default Windows dialogs (eg: MessageBox, Open/Save, BrowseForFolder, ChooseColor, etc) I used a plug-in from http://www.smartbrainsoftware.com (SkinBoxer).
    This is very nice. Give it a shot!

    Reply
  • Use Class Wizard for Command IDs

    Posted by Legacy on 11/06/2002 12:00am

    Originally posted by: Boaz Harrosh

    Just a small addition:

    So you don't need to maintain the big switch-on-command by hand, you could do the following:
    - Create an unused MENU resource in your MFC project
    - With class-wizard (or its derivative in vc.net) handle the Menu command.
    - (Note that the menu need not be displayed)
    - Change the ProcessBrowerCmds member to:
    BOOL CRightView::ProcessBrowerCmds(const char* lpszCmd)
    {
    BOOL bRet=FALSE;
    int iCmd=atoi(lpszCmd);
    AfxGetMainWnd()->OnCmdMsg(iCmd ,0 ,NULL ,NULL) ;
    }
    - This way commands get routed as a menu so it can be handled in any window
    - TO the HTML gurus out-there. How can we transform the resource.h constant definitions to something includable in an HTML? Maybe XML/XSL? or CSS?

    Nice job. With some extra work in this direction who needs .NET forms.
    One could take one of the Open-Source HTML Editors out there and have an automatic code generator like in .NET.

    Reply
  • GREAT IDEA

    Posted by Legacy on 11/05/2002 12:00am

    Originally posted by: denis flotat

    What a great idea to merge HTML technology with MFC/doc view documents to enable better GUI interface.
    Until now, i didn't imagine to use CHtmlView in a context different than developing my own html browser.
    Modifying resources allows to personalize GUI application in an easy way and give a real interest to web based applications.
    GREAT JOB.
    Your sample is very nice.

    Reply
  • IE versions & manageability

    Posted by Legacy on 11/04/2002 12:00am

    Originally posted by: anonymous coward

    It's not that bad turning an application to a browser. After all the whole Windows OS somehow turned into a browser. Anyway I kinda can't get rid of the feeling that something went terribly wrong - is an OS supposed to be a browser ? But, hey, nice design sells, doesn't it ? Who cares about the few crashes a day ;) Ok, now seriously - I wouldn't do that because of one thing - MS IE versions. There are quite many and I can imagine the management nightmare (C:Why does not your stupid app work on my computer? P:AAAAH you've got IE ver. X, you have to get ver. Y. etc... use your imagination)

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

Top White Papers and Webcasts

  • Cisco and Intel have harnessed flash memory technology and truly innovative system software to blast through the boundaries of today's I/O-bound server/storage architectures. See how they are bringing real-time responsiveness to data-intensive applications—for unmatched business advantage. Sponsored by Cisco and Intel® Partnering in Innovation

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today makes data protection a must-have, as we live in a data-driven society -- the digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join Seagate Cloud …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds