SQHMTree

An ActiveX control for browsing the HTML structure of a page open in HoTMetaL

Introduction

SQHMTree is an ActiveX control for viewing and browsing the structure of an open HoTMetaL document. These notes describe how to create SQHMTree, and how to embed it in the HoTMetaL Resource Manager.

We used Microsoft Visual C++ 5.0 to create SQHMTree, but the steps are the same for Visual C++ 6.0. We assume readers have a basic understanding of how to use Visual C++ and HoTMetaL.

Create a new project

  1. In Visual C++, choose New from the File menu.
  2. A tabbed dialog is displayed; click on the Projects tab.
  3. In the Projects tab:
    1. Select MFC ActiveX ControlWizard.
    2. Enter SQHMTree as the Project name.
    3. Click on OK.
  4. The MFC ActiveX Control Wizard is displayed. In the Page 1 of 2 dialog, make the following choices:
  5. Click on Next>.
  6. In the Page 2 of 2 dialog, make the following choices:
  7. Click on Finished.

Add the HoTMetaL interfaces to the SQHMTree project

We made SQHMTree an automation client of HoTMetaL so that it can efficiently manipulate HoTMetaL objects (such as Document, DOMNode, etc.). SQHMTree needs to have the information about the server (HoTMetaL) objects' properties and methods. We made this information available to SQHMTree by creating dispatch classes from HoTMetaL's type library and adding them to SQHMTree project:

  1. Choose Class Wizard... from the View menu.
  2. Click on the Class Info tab.
  3. Click on the Add Class button and choose From a type library... from the pop-up menu.
  4. Browse to the HoTMetaL installation directory and open the file hmpro6.tlb (or hmpro6.exe).
  5. In the Confirm Classes dialog, select all the classes (you can use Shift-Click to do this).
  6. Click on OK.
  7. Click on OK in the MFC Class Wizard dialog.

Design CMyTreeCtrl

CMyTreeCtrl is derived from a standard MFC class: CTreeCtrl. It contains the hierarchical structure of an .html document. A left mouse click on a tree item will cause HoTMetaL to move the insertion point of the current document to the beginning of the node represented by the tree item that was clicked on.

  1. Right-click on SQHMTree classes in the Class View tab and choose New Class... from the pop-up menu.
  2. Add a class named CMyTreeCtrl into SQHMTree project, and specify it is derived from CTreeCtrl:
    1. Enter CMyTreeCtrl as the class name.
    2. Choose CTreeCtrl from the Base class list.
  3. Add a context menu m_menu to CMyTreeCtrl. m_menu contains the menu item to refresh the tree.
    1. In the Class View tab, right-click on CMyTreeCtrl and choose Add Member Variable... from the pop-up menu.
    2. Enter CMenu as the Variable type
    3. Enter m_menu as the Variable name
    4. Append the menu item to it inside the constructor of CMyTreeCtrl (located in the file MyTreeCtrl.cpp). The code is written as follows:
      CMyTreeCtrl::CMyTreeCtrl() { 
          m_menu.CreatePopupMenu();
          m_menu.AppendMenu( MF_STRING, ID_REFRESH_TREE,__T("Refresh") ); 
      }
      
  4. Add three message handlers: OnLButtonDown(), OnRButtonDown(), and OnRefreshTree() to CMyTreeCtrl: OnLButtonDown() informs HoTMetaL when it should move its insertion point; OnRButtonDown() displays the context (pop-up) menu; OnRefreshTree() forces the control to refresh its contents, based the active HoTMetaL document.
    1. In the Class View tab, right-click on CMyTreeCtrl and choose Add Windows message Handler... from the pop-up menu.
    2. Choose WM_LBUTTONDOWN from the list on the left and click on Add Handler.
    3. Do the same for WM_RBUTTONDOWN.
    4. Create the resource symbol ID_REFRESH_TREE for the menu item Refresh and add the message handler for it (created inside the constructor of CMyTreeCtrl): the handler is named OnRefreshTree( ) and should be created in the file MyTreeCtrl.cpp. The code is written as follows:
      void CMyTreeCtrl::OnRefreshTree()
      {
        DeleteAllItems();
        CWaitCursor dummy;
        LoadXMLDocElements();
      }
      
  5. Add method LoadXMLDocElements(),which loads the elements of the active HoTMetaL document.
    1. In the Class View tab, right-click on CMyTreeCtrl and choose Add Member Function... from the pop-up menu.
    2. Enter LoadXMLDocElements() for the Function Declaration
    3. Enter BOOL for the function type.
    4. The function code is written as follows (in the file MyTreeCtrl.cpp):
      BOOL CMyTreeCtrl::LoadXMLDocElements() {
           // Connect to HoTMetaL
           COleException e;
           _Application xmetalApp;
           if (!xmetalApp.CreateDispatch(XMETALAPP_GUID, &e)) {
                ::AfxMessageBox(IDS_ERR_DISPATCH);
                return S_FALSE;
           }
           _Document xmetalDoc = xmetalApp.GetActiveDocument( ); 
             
           // If not document open, display stub
           if (!xmetalDoc ) {
                // Insert a empty root item when no active document is open
                SetNoDocument(); 
                   
                 return S_FALSE;
            }     DOMNode domEle = xmetalDoc.GetDocumentElement( );     
           // If no document element available, display stub
           if (!domEle ) {
                                          
                // Insert a empty root item when no active document is open           
                TV_INSERTSTRUCT      tvstruct;
                tvstruct.hParent =      NULL;
                tvstruct.hInsertAfter = TVI_SORT;
                tvstruct.item.iImage = 0;
                tvstruct.item.iSelectedImage = 0;
                tvstruct.item.pszText = __T("(empty)"); 
                tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE 
                                                | TVIF_TEXT | TVIF_PARAM;
                InsertItem( &tvstruct );
                     
                return S_FALSE;
           }     
           // Insert the element names into the tree, starting with the root
           int index = 0;
           InsertElement( NULL, domEle, index );     
           // Enable "Refresh" context menu      
           m_menu.EnableMenuItem( ITEM_REFRESH_TREE, TRUE );     
           // Expand the tree to the first level
           Expand(GetRootItem(), TVE_EXPAND);     
           return TRUE;
      }
      

Design the ActiveX control CSQHMTreeCtrl

CSQHMTreeCtrl is the ActiveX control generated by the wizard. We need to do some modifications:

  1. Add a member variable m_tree, which is an object of class CMyTreeCtrl.
    1. In the Class View tab, right-click on CMyTreeCtrl and choose Add Member Variable... from the pop-up menu.
    2. Enter CMyTreeCtrl as the Variable type
    3. Enter m_tree as the Variable name
  2. Override the OnCreate() method; inside this method we create m_tree and initialize it.
    1. In the Class View tab, open SQHMTree classes
    2. Right-click on CSQHMTreeCtrl
    3. Choose Windows Message Handler from the pop-up menu
    4. Find WM_CREATE in the list on the left, and double-click on it.
    5. See the supplied source code for the body of OnCreate().
  3. Override the OnSize( ) method; inside this method, we resize m_tree to the full size of CSQHMTreeCtrl whenever CSQHMTreeCtrl's size changes. The steps for doing this are basically the same as for creating OnCreate(): when you create the Windows Message Handler, choose WM_SIZE. The code for the method is as follows:
    void CSQHMTreeCtrl::OnSize(UINT nType, int cx, int cy)
    {
         COleControl::OnSize(nType, cx, cy);
         m_tree.MoveWindow( 0, 0, cx, cy );
    }
    
  4. Refer to the supplied Visual C++ project for the remaining code and resources required for the project.

Embed the SQHMTree control in HoTMetaL

After successfully compiling the project, we now embed this control in HoTMetaL, and use it as a tool to navigate the structure of the active HoTMetaL document:

  1. Create a folder (for example, treeView ) under the Assets folder in the HoTMetaL installation folder.
  2. Create a HTML file named fxindex.htm under treeView . By default, when an asset folder is selected, HoTMetaL looks for a file named fxindex.htm under this folder, and opens it in the Resource Manager browser window. To enable SQHMTree to be correctly opened in the browser, the content of fxindex.htm might look like:
    <HTML>
      <HEAD>
      <TITLE>Document Tree View</TITLE> 
        <LINK REL="STYLESHEET" HREF="fxindex.css"> 
      </HEAD> 
      <BODY> 
        <OBJECT CLASSID="clsid:94402467-597A-11D3-BB28-006097043CC8" 
            ID="TreeView" WIDTH="100%" HEIGHT="100%" BORDER="3D" 
            ALIGN="left" HSPACE="0%" VSPACE="0%"> 
        </OBJECT> 
      </BODY> 
    </HTML>
    
  3. Create a style sheet file named fxindex.css in the treeView folder:
    BODY { 
      margin-top: 0pt; 
      margin-left: 0pt; 
      margin-right: 0pt; 
      margin-bottom: 0pt; 
    } 
    

Since the SQHMTree control has its own scroll bar, you may want to disable the Resource Manager scroll bar. To do so, you only need to create an empty file named noscrollbar.txt in the treeView folder.