例子:编写CyberArticle HTML处理插件

建立工程

建立过程的操作,请参考例子:编写一个CyberArticle普通插件 (Visual C++)。在这里,我们把工程名命名为MyCAHtmlPlugin1。

增加COM组件

同样,请参看例子:编写一个CyberArticle普通插件 (Visual C++),增加一个COM组件,组件名CAHtmlPlugin1。

找到并修改CAHtmlPlugin1.h文件

这是COM组件class定义文件。斜体部分为增加的内容:
 
// CAHtmlPlugin1.h : Declaration of the CCAHtmlPlugin1 

#pragma once 
#include "resource.h" // main symbols 

#include "MyCAHtmlPlugin1.h" 

/* 
* 包含必要的头文件。如果CyberArticle没有安装在C:\Program Files\Wizissoft\CyberArticle\,请修改下面相应的包含路径。 
*/ 
#include "C:/Program Files/Wizissoft/CyberArticle/developers/interface/include/CyberArticleHtmlPluginInterface.h" 
#include <atlstr.h> 


#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) 
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms." 
#endif 



// CCAHtmlPlugin1 

class ATL_NO_VTABLE CCAHtmlPlugin1 : 
    public CComObjectRootEx<CComSingleThreadModel>, 
    public CComCoClass<CCAHtmlPlugin1, &CLSID_CAHtmlPlugin1>, 
    public IDispatchImpl<ICAHtmlPlugin1, &IID_ICAHtmlPlugin1, &LIBID_MyCAHtmlPlugin1Lib, /*wMajor =*/ 1, /*wMinor =*/ 0> 
    , public ICAHtmlPlugin 
{ 
public: 
    CCAHtmlPlugin1() 
    { 
    } 

DECLARE_REGISTRY_RESOURCEID(IDR_CAHTMLPLUGIN1) 


BEGIN_COM_MAP(CCAHtmlPlugin1) 
    COM_INTERFACE_ENTRY(ICAHtmlPlugin1) 
    COM_INTERFACE_ENTRY(IDispatch) 
    COM_INTERFACE_ENTRY_IID(IID_ICAHtmlPlugin, ICAHtmlPlugin) 
END_COM_MAP() 



    DECLARE_PROTECT_FINAL_CONSTRUCT() 

    HRESULT FinalConstruct() 
    { 
        return S_OK; 
    } 

    void FinalRelease() 
    { 
    } 

public: 
private: 
    CString m_strURL; 

public: 
    //ICAHtmlPlugin 
    virtual HRESULT STDMETHODCALLTYPE Init(ICAHtmlTool* pTool); 
    virtual HRESULT STDMETHODCALLTYPE Exit(); 
    virtual HRESULT STDMETHODCALLTYPE get_PluginFlags(long* pnFlags); 
    virtual HRESULT STDMETHODCALLTYPE put_HtmlFlags(long nFlags); 
    virtual HRESULT STDMETHODCALLTYPE Config(); 
    virtual HRESULT STDMETHODCALLTYPE OnTag(BSTR bstrTag, BSTR* pbstrResult, VARIANT* pvAdditionalResourceURLs); 
    virtual HRESULT STDMETHODCALLTYPE OnText(BSTR bstrText, BSTR* pbstrResult); 
    virtual HRESULT STDMETHODCALLTYPE OnProgress(long nProgress); 
    virtual HRESULT STDMETHODCALLTYPE OnBeforeProcessNode(ICANode* pNode); 
    virtual HRESULT STDMETHODCALLTYPE OnAfterProcessNode(); 
    virtual HRESULT STDMETHODCALLTYPE OnBeforeProcessHtml(BSTR bstrURL, BSTR bstrHtml, BSTR* pbstrResult); 
    virtual HRESULT STDMETHODCALLTYPE OnAfterProcessHtml(BSTR bstrHtml, BSTR* pbstrResult); 
    virtual HRESULT STDMETHODCALLTYPE get_Order(long* pnOrder); 

}; 

OBJECT_ENTRY_AUTO(__uuidof(CAHtmlPlugin1), CCAHtmlPlugin1) 

找到并修改CAHtmlPlugin1.cpp文件

斜体部分为增加的内容:
 
// CAHtmlPlugin1.cpp : Implementation of CCAHtmlPlugin1 

#include "stdafx.h" 
#include "CAHtmlPlugin1.h" 


// CCAHtmlPlugin1 


HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::Init(ICAHtmlTool* pTool) 
{ 
    /* 
    插件初始化 
    */ 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::Exit() 
{ 
    /* 
    插件退出 
    */ 
    return S_OK; 
} 

HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::get_PluginFlags(long* pnFlags) 
{ 
    if (!pnFlags) 
        return E_INVALIDARG; 
    // 
    /* 
    获得插件属性 
    */ 
    *pnFlags = 0; 
    // 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::put_HtmlFlags(long nFlags) 
{ 
    /* 
    设置插件属性 
    */ 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::Config() 
{ 
    /* 
    配置插件 
    */ 
    return E_NOTIMPL; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnTag(BSTR bstrTag, BSTR* pbstrResult, VARIANT* pvAdditionalResourceURLs) 
{ 
    /* 
    处理HTML Tag 
    */ 
    return S_FALSE; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnText(BSTR bstrText, BSTR* pbstrResult) 
{ 
    /* 
    处理HTML里面的文字 
    */ 
    return S_FALSE; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnProgress(long nProgress) 
{ 
    /* 
    进度改变,nProgress: 0-100 
    */ 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnBeforeProcessNode(ICANode* pNode) 
{ 
    /* 
    开始处理文章 
    */ 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnAfterProcessNode() 
{ 
    /* 
    处理文章结束 
    */ 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnBeforeProcessHtml(BSTR bstrURL, BSTR bstrHtml, BSTR* pbstrResult) 
{ 
    /* 
    开始处理HTML文件 
    */ 
    //记录HTML的网址 
    m_strURL = bstrURL; 
    // 
    return S_FALSE; 
} 
ptrdiff_t WizStrStrI_Pos(const CString& strText, const CString& strFind, ptrdiff_t nBegin = 0); 

HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::OnAfterProcessHtml(BSTR bstrHtml, BSTR* pbstrResult) 
{ 
    /* 
    处理HTML文件结束 
    */ 
    if (!pbstrResult) 
        return E_INVALIDARG; 
    // 
    //查找html标记,并在后面增加注释行,记录保存的原始网址 
    CString strHtml(bstrHtml); 
    int nPos = int(WizStrStrI_Pos(strHtml, _T("<html"))); 
    if (-1 != nPos) 
    { 
        nPos = strHtml.Find('>', nPos); 
    } 
    // 
    strHtml.Insert(nPos + 1, CString(_T("\r\n<!-- saved by CyberArticle from url=")) + m_strURL + _T(" -->\r\n")); 
    // 
    *pbstrResult = strHtml.AllocSysString(); 
    // 
    return S_OK; 
} 
HRESULT STDMETHODCALLTYPE CCAHtmlPlugin1::get_Order(long* pnOrder) 
{ 
    /* 
    返回HTML处理顺序 
    */ 
    if (!pnOrder) 
        return E_INVALIDARG; 
    // 
    *pnOrder = 1000; 
    // 
    return S_OK; 
} 

// 
/* 
辅助函数,用来在一个字符串内,查找字串。忽略大小写。 
*/ 
ptrdiff_t WizStrStrI_Pos(const CString& strText, const CString& strFind, ptrdiff_t nBegin) 
{ 
    LPCTSTR lpszText = strText; 
    LPCTSTR lpszFind = strFind; 
    // 
    LPCTSTR lpszRet = StrStrI(lpszText + nBegin, lpszFind); 
    if (!lpszRet) 
        return -1; 
    // 
    return lpszRet - lpszText; 
} 

找到并修改MyCAHtmlPlugin1.cpp

这个文件主要用来注册COM组件(斜体部分为增加的内容)
 
// MyCAHtmlPlugin1.cpp : Implementation of DLL Exports. 


#include "stdafx.h" 
#include "resource.h" 
#include "MyCAHtmlPlugin1.h" 

/* 
* 包含必要的头文件。如果CyberArticle没有安装在C:\Program Files\Wizissoft\CyberArticle\,请修改下面相应的包含路径。 
*/ 
#include "C:/Program Files/Wizissoft/CyberArticle/developers/interface/include/CyberArticleHtmlPluginHelper.h" 


class CMyCAHtmlPlugin1Module : public CAtlDllModuleT< CMyCAHtmlPlugin1Module > 
{ 
public : 
    DECLARE_LIBID(LIBID_MyCAHtmlPlugin1Lib) 
    DECLARE_REGISTRY_APPID_RESOURCEID(IDR_MYCAHTMLPLUGIN1, "{6342CBE6-CAEA-4ECA-8A45-42756BD03EC1}") 
}; 

CMyCAHtmlPlugin1Module _AtlModule; 


#ifdef _MANAGED 
#pragma managed(push, off) 
#endif 

// DLL Entry Point 
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) 
{ 
    hInstance; 
    return _AtlModule.DllMain(dwReason, lpReserved); 
} 

#ifdef _MANAGED 
#pragma managed(pop) 
#endif 




// Used to determine whether the DLL can be unloaded by OLE 
STDAPI DllCanUnloadNow(void) 
{ 
    return _AtlModule.DllCanUnloadNow(); 
} 


// Returns a class factory to create an object of the requested type 
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) 
{ 
    return _AtlModule.DllGetClassObject(rclsid, riid, ppv); 
} 


// DllRegisterServer - Adds entries to the system registry 
STDAPI DllRegisterServer(void) 
{ 
    // registers object, typelib and all interfaces in typelib 
    HRESULT hr = _AtlModule.DllRegisterServer(); 
    // 
    if (SUCCEEDED(hr)) 
    { 
        CyberArticleRegisterHtmlPlugin(CLSID_CAHtmlPlugin1, _T("向文章中添加网址URL")); 
    } 
    // 
    return hr; 
} 


// DllUnregisterServer - Removes entries from the system registry 
STDAPI DllUnregisterServer(void) 
{ 
    CyberArticleUnregisterHtmlPlugin(CLSID_CAHtmlPlugin1); 
    // 
    HRESULT hr = _AtlModule.DllUnregisterServer(); 
    return hr; 
} 

编译并测试插件

然后编译整个工程。如果出现错误,请检查相应的代码。
 
在浏览器内保存网页,将保存对话框切换到高级界面,然后选择插件tab,就可以看到我们增加的插件:
 

 
保存网页的时候,将会保存网页。

调试插件:

Html插件的调试比较困难。
 
如果插件可以用于该插件可以用于文章批量处理功能(具有HPF_PROCESS_HTML_TOOL属性)。怎可以将CyberArticle.exe设置为调试程序。在CyberArticle里面使用文章批量处理功能,就可以调试插件了。