• 蛙蛙推荐:蛙蛙牌firefox插件


    上次给大家演示了抓取IE内核浏览器的网页,这次和大家一起写一个抓取firefox页面文本的例子。Firefox有自身的一套结构良好的插件机制,但要深入开发Firefox插件的话要了解javascript,XUL,XPCOM以及一些c++的基本常识,本贴算是给想开发Firefox插件的朋友入门。

    我们先来了解什么是XPCOM,并开发一个

    以下为引用(https://developer.mozilla.org/cn/XPCOM
    XPCOM(Cross Platform Component Object Model)是一种跨平台组件模型,是Mozilla技术的核心。其原理与微软的COM技术类似,但与COM不同的是,XPCOM是一种跨平台技术,并支持多种语言绑定(Language Bindings)。也就是说,我们可以使用C++、JAVA、JavaScript、Python、Ruby、Perl等语言来编写组件。而XPCOM的接口(Interface)是用一种叫做XPIDL的IDL(Interface Description Language)来定义的。

    XPCOM 自身提供了一套核心的组件和类,用于诸如内存管理,线程,基本数据结构(strings, arrays, variants)等 。但是大部分的XPCOM组件并不是这个核心库提供的,而是由很多第三方的平台(例如Gecko或者Necko)提供,或者由一个应用,甚至一个扩展提供。

    要想了解如何搭建MOZILLA开发环境,可以参考如下链接
    Windows Build Prerequisites
    我们下载MozillaBuildGecko SDK 1.8
    先安装MozillaBuild到D:\mozilla-build,后安装Gecko SDK 1.8到D:\dev\gecko-sdk,虽然整个过程没有用到MozillaBuild,但它是必须要安装的,否则后面运行regxpcom会出好多莫名其妙的错,(光解决这个问题就我就折腾了好几个晚上,希望大家少走弯路,只下载wintools.zip和gecko sdk就是不行,就得装MozillaBuild,这是先决条件。

    创建XPCOM组件要先定义一个接口文件,新建IWawaComp.idl,用记事本打开,输入如下内容

    #include "nsISupports.idl"
    [scriptable, uuid(b7b04070
    -45fc-4635-b219-7a172f806bee)]
    interface IWawaComp : nsISupports
    {
      
    void SendSysMessage(in string  str);
    };

    这是一个很简单的接口,只有一个方法SendSysMessage,接受一个string类型的参数,string是gecko的类型,不支持中文,要想用中文,可以用xpcom idl中的nsAString(在idl文件里要用AString表示,用nsAString会出错), wstring等支持unicode的字符串类型。因为我最终也没办法在js下把中文传给XPCOM,所以这里最终还是决定用string类型。b7b04070-45fc-4635-b219-7a172f806bee是一个GUID类型,可以用ultraedit或者vs.net自带的功能生成一个。所有的接口必须继承自nsISupports,因为要使用string类型,所以要包含以下nsISupports.idl文件,好多基本类型都在这里面定义。如果要用wstring或AString类型,要包含以下nsrootidl.idl文件。其它的地方都是固定的,你可以自己加一些接口方法或者修改什么的,这就是一个模板。

    中文问题:


    光解决中文的问题,我花了周末两天和两个晚上,最后才得到一个不太完美的方案,把过程分享一下。
    第一种思路是用scriptableunicodeconverter的ConvertFromUnicode方法把中文转换成unicode bytes,然后用window.btoa把unicode bytes转换成base64字符串,然后传给XPCOM,这样XPCOM的接口只用string类型就行,在XPCOM里再进行base64解码,再用MultiByteToWideChar来转换成wchar_t等宽字符类型。可惜scriptableunicodeconverter转换的bytes用window.btoa编码后的base64根本就无法再原样转回去,弄了好久,死活不行,可能gecko的这个方法对中文支持就是不行。所以这种思路最后没戏。
    第一种思路的代码如下

    function unicodeToBytes(content, charset) 
    {
        
    try
        {
            
    const cc = Components.classes;
            
    const ci = Components.interfaces;
            
    const unicodeConverter = cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(ci.nsIScriptableUnicodeConverter);
            unicodeConverter.charset 
    = charset;
            content 
    = unicodeConverter.ConvertFromUnicode(content);
            
    return content;
        }
        
    catch (err)
        {
            alert(err);
        }
    }
    var data 
    = unicodeToBytes("中文","utf-8"); 
    alert(window.atob(window.btoa(data))); 

    弹出来的是乱码,不知道咋解决,直接window.btoa("中文")也会出错
    第二种思路是把接口方法的参数定义成AString,然后在XPCOM的实现方法里用NS_StringGetData和WideCharToMultiByte来转换,结果NS_StringGetData在gecko 1.8下编译链接时老提示无法解析的外部符号,在gecko1.7下倒是能编译,可是无法注册在firefox 2.0下,最后也实在没办法,不了了只。关于这种思路来源于以下链接http://rogerfd.cn/?p=165
    相关讨论如下
    关于XPCOM开发的问题

    然后就要根据接口定义文件生成头文件和类型库文件(.xpt),先把D:\mozilla-build\moztools-180compat\bin目录下的libIDL-0.6.dll,glib-1.2.dll拷贝到D:\dev\gecko-sdk\bin目录下,然后执行如下命令
    D:\dev\gecko-sdk\bin\xpidl -m header -I ..\idl  IWawaComp.idl
    D:\dev\gecko-sdk\bin\xpidl -m typelib -I ..\idl  IWawaComp.idl
    第一行生成头文件,第二行生成类型库文件。如果执行的时候出错了,有可能是没安装mozillabuild,还不行的话就把geckosdk的那几个bin,lib,include等目录加入到系统环境变量PATH下。

    打开头文件,大概如下

    /*
     * DO NOT EDIT.  THIS FILE IS GENERATED FROM IWawaComp.idl
     
    */

    #ifndef __gen_IWawaComp_h__
    #define __gen_IWawaComp_h__


    #ifndef __gen_nsISupports_h__
    #include 
    "nsISupports.h"
    #endif

    /* For IDL files that don't want to include root IDL files. */
    #ifndef NS_NO_VTABLE
    #define NS_NO_VTABLE
    #endif

    /* starting interface:    IWawaComp */
    #define IWAWACOMP_IID_STR "b7b04070-45fc-4635-b219-7a172f806bee"

    #define IWAWACOMP_IID \
      {
    0xb7b040700x45fc0x4635, \
        { 
    0xb20x190x7a0x170x2f0x800x6b0xee }}

    class NS_NO_VTABLE IWawaComp : public nsISupports {
     
    public

      NS_DEFINE_STATIC_IID_ACCESSOR(IWAWACOMP_IID)

      
    /* void SendSysMessage (in string str); */
      NS_IMETHOD SendSysMessage(
    const char *str) = 0;

    };

    /* Use this macro when declaring classes that implement this interface. */
    #define NS_DECL_IWAWACOMP \
      NS_IMETHOD SendSysMessage(
    const char *str); 

    /* Use this macro to declare functions that forward the behavior of this interface to another object. */
    #define NS_FORWARD_IWAWACOMP(_to) \
      NS_IMETHOD SendSysMessage(
    const char *str) { return _to SendSysMessage(str); } 

    /* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
    #define NS_FORWARD_SAFE_IWAWACOMP(_to) \
      NS_IMETHOD SendSysMessage(
    const char *str) { return !_to ? NS_ERROR_NULL_POINTER : _to->SendSysMessage(str); } 

    #if 0
    /* Use the code below as a template for the implementation class for this interface. */

    /* Header file */
    class _MYCLASS_ : public IWawaComp
    {
    public:
      NS_DECL_ISUPPORTS
      NS_DECL_IWAWACOMP

      _MYCLASS_();

    private:
      
    ~_MYCLASS_();

    protected:
      
    /* additional members */
    };

    /* Implementation file */
    NS_IMPL_ISUPPORTS1(_MYCLASS_, IWawaComp)

    _MYCLASS_::_MYCLASS_()
    {
      
    /* member initializers and constructor code */
    }

    _MYCLASS_::
    ~_MYCLASS_()
    {
      
    /* destructor code */
    }

    /* void SendSysMessage (in string str); */
    NS_IMETHODIMP _MYCLASS_::SendSysMessage(
    const char *str)
    {
        
    return NS_ERROR_NOT_IMPLEMENTED;
    }

    /* End of implementation class template. */
    #endif


    #endif /* __gen_IWawaComp_h__ */

    下面被注释掉的部分是告诉你如何写接口的实现部分。
    然后用vc2005新建一个c++类库,不要MFC,ATL啥的,预编译头在打开项目后也把勾去掉,再把没用的std啥.h也都删了。把刚生成的IWawaComp.h放在头文件目录下。然后要设置一下项目的配置,先打开项目属性,做如下配置
    1、c++\常规\附加包含目录,输入如"D:\dev\gecko-sdk\include"
    2、c++\预处理器\预处理器定义里加入WAWAXPCOM_EXPORTS和XPCOM_GLUE
    3、c++\代码生成\运行时库 改成”多线程DLL
    4、链接器\附加库目录输入”"D:\dev\gecko-sdk\lib"“
    5、链接器\输入\附加依赖项 输入nspr4.lib、plc4.lib、plds4.lib、xpcomglue.lib

    再新建一个WawaComp.h头文件,内容如下

    #pragma once

    #ifndef _WAWA_COMPT_H_
    #define _WAWA_COMPT_H_

    #include 
    "IWawaComp.h"

    #define WAWA_COMP_CONTRACTID "@fetionmm.com/XPCOM/WawaComp;1"
    #define WAWA_COMP_CLASSNAME "WawaComp"
    #define WAWA_COMP_CID  {0xb7b04070, 0x45fc, 0x4635,{ 0xb2, 0x19, 0x7a, 0x17, 0x2f, 0x80, 0x6b, 0xee } }


    class WawaComp:public IWawaComp
    {
      
    public:
        NS_DECL_ISUPPORTS
        NS_DECL_IWAWACOMP
    };
    #endif

    前面是定义了一下组件的常量,WAWA_COMP_CONTRACTID是javascript创建XPCOM的时候用的字符串,后面会看到,WAWA_COMP_CLASSNAME是组件的类名,WAWA_COMP_CID是组件的唯一ID,如果你不会从GUID变成这种格式,其实就是把刚才生成的头文件里的IWAWACOMP_IID宏的值拷贝过来就行。剩下的部分基本都是固定格式,从生成的头文件里的注释部分直接拷过来就行。
    再新建一个WawaCompModule.cpp文件,这个是一个XPCOM的模块文件,是必须的。

    #include "nsIGenericFactory.h"
    #include 
    "WawaComp.h"

    NS_GENERIC_FACTORY_CONSTRUCTOR(WawaComp)

    static nsModuleComponentInfo components[] =
    {
        {
            WAWA_COMP_CLASSNAME, 
            WAWA_COMP_CID,
            WAWA_COMP_CONTRACTID,
            WawaCompConstructor,
        }
    };

    NS_IMPL_NSGETMODULE(
    "WawaCompModule", components)

    前两个include是必须的,下面一句是生成本组件,参数WawaComp就是组件的实现类,再往下是生命一个nsModuleComponentInfo数组,里面前三个都是在WawaComp.h里生命的几个常量,最后一个WawaCompConstructor是固定格式,就是类名加上Constructor。再最后一句是注册这个组件,第一个字符串是这个模块的名字,第二个参数是前面声明的数组。都是固定格式,如果要自己开发XPCOM的话,按格式改改就行了。

    再新建最后一个文件WawaComp.cpp
    代码如下

    /* MyComponent.cpp*/
    #include 
    "WawaComp.h"
    #include 
    <windows.h>
    #include 
    <tchar.h>

    NS_IMPL_ISUPPORTS1(WawaComp, IWawaComp)
    NS_IMETHODIMP WawaComp::SendSysMessage(
    const char *sText)
    {   
     DWORD dwSize 
    = MultiByteToWideChar (CP_ACP, 0, sText, -1, NULL, 0);
     wchar_t 
    *pwText;
     pwText 
    = new wchar_t[dwSize];
     MultiByteToWideChar(CP_ACP, 
    0, sText, -1, pwText, dwSize);

     HWND   hWnd   
    =   FindWindow(NULL,_T("WawaApp"));
     COPYDATASTRUCT cpd 
    = {SW_NORMAL, lstrlen(pwText)*2+2, pwText};
     SendMessage( hWnd, WM_COPYDATA, 
    0, (LPARAM) & cpd );
     delete []pwText;
      
    return NS_OK;
    }

    该文件是接口的实现文件,NS_IMPL_ISUPPORTS1一句是固定的,第一个参数是类名,第二个参数是接口名。下面就是SendSysMessage方法的实现了,该方法的签名也在前面生成的头文件的注释里复制过来,该方法返回类型是NS_IMETHODIMP类型,NS_OK表示成功。
    实现的代码很简单,主要是路是把多字节字符串用MultiByteToWideChar转换成宽字符字符串,然后找到标题为WawaApp的窗口,声明一个COPYDATASTRUCT的结构,把宽字符字符串放进去,最后用SendMessage方法向目标窗口发送WM_COPYDATA消息,完了再用delete把前面声明的宽字符字符串释放内存。
    MultiByteToWideChar的用法是固定的,第一次调用先得出目标字符串的长度,第二次调用是填充字符串,可以参考《windows核心编程》查看详细。COPYDATASTRUCT的第二个参数是lstrlen(pwText)*2+2,是因为一个宽字符站两个字节,所以要乘以2,完了字符串是以两个\0结尾,所以要加2。SendMessage是同步发送消息,这里没用SendMessageTimeout是怕超时后,目标进程还想读取本进程的COPYDATASTRUCT,有可能引起本进程崩溃,没有使用PostMessage是因为发了消息后对方没机会读取COPYDATASTRUCT的数据了。

    进程间通信:


    进程间通信有好多种方式,如果只传少量的字符串的话,可以用GlobalFindAtom,GlobalGetAtomName,GlobalDeleteAtom,GlobalAddAtom几个API来做到,不过我试验了下,这几个API传递的字符串好像有长度限制,最后放弃了。还有就是可以用内存映射文件,就是代码写的有些多,也没用;用命名管道或者socket也可以,但总感觉有些火箭穿蚊子,也没用。WriteProcessMemory也可以,感觉不优雅,太暴力,最后才选定了用WM_COPYDATA。
    编译后生成WawaXPCOM.dll,到这一步XPCOM就算开发完了。关于XPCOM的部署,很麻烦,firefox3.0以下,可以用install.js来在.xpi包里自动安装,参考如下链接
    http://blog.csdn.net/Xscarlet/archive/2007/07/23/1704450.aspx,但firefox3.0我测试了不行,貌似firefox3.0取消了对install.js的支持,那只能把.DLL和.XPT复制到firefox安装目录的components子目录下,然后删除C:\Documents and Settings\Administrator\Application Data\Mozilla\Firefox\Profiles\brm8mamm.dev目录下的xpti.dat和compreg.dat文件,然后重启firefox来重新自动注册XPCOM了。关于firefox下自动注册xpcom的正规方法,我费了半天劲也没找到。

    下面开始开发firefox插件

    先做准备工作,我用的是firefox2.0,firefox可以创建多个用户配置文件,用firefox -p运行,在对话框里新建配置文件dev,打开后再地址栏里输入about:config,修改如下选项
    javascript.options.showInConsole = true //把 JavaScript 的出错信息显示在错误控制台
    nglayout.debug.disable_xul_cache = true //禁用 XUL 缓存,使得对窗口和对话框的修改不需要重新加载 XUL 文件
    browser.dom.window.dump.enabled  = true //允许使用 dump() 语句向标准控制台输出信息
    javascript.options.strict        = true //在错误控制台中启用严格的 JavaScript 警告信息

    然后给firefox安装Extension Developer's Extension 插件,这样你修改了xpcom后运行菜单 工具\Extension Developer\ Reload all Chrome不用重启ff就可以测试插件了。我们在C:\Documents and Settings\Administrator\Application Data\Mozilla\Firefox\Profiles\brm8mamm.dev\extensions(Administrator是当前用户名,brm8mamm.dev可能和你的不一样,但结尾是你刚新建的firefox配置文件名dev)目录下新建一个wawaxpcom@fetionmm.com的文件,用记事本打开,输入我们插件的开发路径,比如E:\huhao\project\WawaFF\xpcom,这样firefox就会自动加载这个插件了,每次改动了文件只需Reload all Chrome就能测试。
    关于firefox插件开发环境搭建,参考如下链接
    http://www.ibm.com/developerworks/cn/web/wa-lo-firefox-ext/
    环境搭好了,先建立工作文件,在E:\huhao\project\WawaFF\xpcom里建立如下文件
    install.rdf
    chrome.manifest
    components
    components\IWawaComp.xpt
    components\WawaXPCOM.dll
    chrome
    chrome\skin
    chrome\content
    chrome\content\overlay.xul
    chrome\content\style.css
    chrome\content\wawa.js
    关于firefox插件的接口,参看如下链接
    http://www.lewislv.org/mozilla-ext/mozilla-ext.html#ch3_1_1
    其中skin文件,本例没有用到,我们先从overlay.xul开始吧,它是一个xul定义文件,XUL是一个界面描述语言,是XML格式的,用javascript和xul也能开发一些跨平台RIA应用。以下为引用
    XUL 是一个Mozilla使用XML来描述用户界面的一种技术,使用XUL你可以快速的创建出跨平台,基于因特网的应用程序。基于XUL技术的应用程序可以很方便的使用好看的字体、图形以及方便的界面布局,而且也更容易部署和定制。如果程序员已经熟悉了Dynamic HTML (DHTML),那学习XUL将是更容易的事,也可以更快的开发基于XUL的应用程序.
    来自https://developer.mozilla.org/cn/XUL
    我们的overlay.xul,如下

    <?xml version="1.0"?>
    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    <overlay id="wawaxpcom" 
             xmlns
    ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        xmlns:html
    ="http://www.w3.org/1999/xhtml" > 
    <script type="application/x-javascript"
            src
    ="chrome://wawaxpcom/content/wawa.js" />    
      
    <statusbar id="status-bar">
       
    <statusbarpanel id="statusbar_fs_sz" class="statusbarpanel-iconic"  onclick="collection(true);" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnElEQVQ4jcWTyw0DMQhEx24gJc2NItJBqtljOkgbiMZgD/Emq/VHjnzISMiSEWN4wgBww6pEZCMZAKaCZIjI9jEgGaoa7j4VqhrlQaTiEe5et/a8v8/Hq0rlnAEg5dXx/29QMzjm7qnw6DNoABvl2iO0TDrGfQbngkFXqYQ392CgM4P4qfJqBCCRhJlNF5kZSH4vlj/TRQeXqSXbATJtb4tQeT1wAAAAAElFTkSuQmCC" insertafter="statusbar-display" style="color:green" label="wawasoft" warning="true"/>
    </statusbar>
    </overlay>

    就是引入了一个wawa.js文件,然后再状态栏上家了一个图片panel,src属性指定图片的路径,不过我指了半天不会指,最后用base64来描述了一个小图片,反正也不大,就似乎把图片的bytes用base64字符串写在那里,微软的.mht格式也是把图片转成那样的base64字符串,还有邮件协议也是。要想让statusbarpanel显示图片的话,必须设置class="statusbarpanel-iconic",最后onclick="collection(true);" 表示点击这个图片出发collection函数,该函数在wawa.js里定义,一会儿看。关于XUL节点定义,可以查些资料看。
    再看下xul的样式,就是普通的CSS,大家应该 很熟悉,

    /*** XUL demonstration ***/
    /* the status bar */
    statusbar 
    {
        width
    : 100%;
        border
    : 1px inset -moz-dialog;
        margin
    : 4px;
        padding
    : 0px 4px;
    }
    #status 
    {
        
    }
    #status[warning] 
    {
        color
    : red;
    }

    就定义了基本的一些边框,外空白,内空白,警告颜色等信息。然后主要的东西在wawa.js里,如下

    function collection(isSelection)
    {
     
    try{
      
    var win = window.getBrowser().selectedBrowser.contentWindow;
      
    var doc = window.getBrowser().selectedBrowser.contentDocument;
      
    var sel = win.getSelection().QueryInterface(Components.interfaces.nsISelectionPrivate);
        
    var contentHTMLSel = sel.toStringWithFormat("text/html"00);
        
    var contentHTMLAll = doc.body.innerHTML;
        
      
    var wawaxpcom = Components.classes["@fetionmm.com/XPCOM/WawaComp;1"].getService();
      wawaxpcom 
    = wawaxpcom.QueryInterface(Components.interfaces.IWawaComp);
      
      
    var s = encodeURIComponent(contentHTMLSel);
      
    if(Selection)
       wawaxpcom.SendSysMessage(s);
      
    else
        wawaxpcom.SendSysMessage(
    "<h1>KK</h1>");
     }
    catch(err){alert(err)}
    }

    前面一些是获取网页上的html代码或者用户选定的部分HTML代码,中间一节是创建我们上面创建的XPCOM,可以看到那里用到了组件的类名,接口等信息,都是固定格式。完了再下面就是把html编码用encodeURIComponent进行编码后调用组件的SendSysMessage方法发出去,进行SendSysMessage编码的原因是考虑中文,中文直接传到XPCOM里有问题,上面说过了。
    值得注意的firefox本身就有好多xpcom可以使用,有访问网络的,unicode转换的,读写文件的,使用w32shell的等,很强大,在你动手写你自己的xpcom之前,最好先了解一下,免得做无用功。
    chrome.manifest定义了firefox插件的文件清单,内容如下
    content wawaxpcom chrome/content/
    overlay chrome://browser/content/browser.xul chrome://wawaxpcom/content/overlay.xul

    第一行表示的是主要内容,第二行表示要用到的界面XUL,一般就这样就行了,.css和.js不用列出来(不是太确认,有的也列出来了,不知道为啥,反正我的能用)。
    install.rdf是一个部署声明文件,不是ie的频道文件,但是XML格式的,如下

    <?xml version="1.0"?>
    <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
         xmlns:em
    ="http://www.mozilla.org/2004/em-rdf#">

      
    <Description about="urn:mozilla:install-manifest">
      
        
    <em:id>wawaxpcom@fetionmm.com</em:id>
        
    <em:name>wawaxpcom</em:name>
        
    <em:version>0.1.0</em:version>
        
    <em:description>WawaXPCOM</em:description>
        
    <em:creator>wawa</em:creator>
     
        
    <!-- Firefox -->
        
    <em:targetApplication>
          
    <Description>
            
    <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
            
    <em:minVersion>1.5</em:minVersion>
            
    <em:maxVersion>3.1.0.*</em:maxVersion>
          
    </Description>
        
    </em:targetApplication>

      
    </Description>

    </RDF>

    其中ec8030f7-c20a-464f-9b0e-13a3a9e97384是固定的,不是你的XPCOM的ID,这个表示firefox,其它的很明显,看节点名就行了,都是插件ingcheng,版本,适应的firefox版本等信息。
    最后把整个E:\huhao\project\WawaFF\xpcom目录压缩成一个zip文件,把后缀名改成.xpi格式,拖到firefox上就会提示安装了,安装后重启ff,右下角就会有一个向下的小箭头图标了,说明插件安装成功了。

    最后我们开发一个c#窗体程序来接受windows消息。


    新建一个c# windows程序,把默认窗体的Text属性改成WawaApp,因为在XPCOM里给WawaApp窗口发消息,所以要用改成这样,否则就得在XPCOM里用broadcastsystemmessage进行消息广播。在窗体上放一个TextBox准备显示收过来的数据。主要的代码如下

    using System;
    using System.Runtime.InteropServices;
    using System.Web;
    using System.Windows.Forms;

    namespace ShowWeb
    {
        
    public partial class Form1 : Form
        {
            
    private const int WM_COPYDATA = 0x004A;

            
    public Form1()
            {
                InitializeComponent();
            }

            
    private void handlerMessage(string message)
            {
                
    if (InvokeRequired)
                {
                    BeginInvoke(
    new handlerMessageDelegate(handlerMessage));
                }
                textBox1.Text 
    = message;
            }

            
    protected override void WndProc(ref Message m)
            {
                
    if (m.Msg == WM_COPYDATA)
                {
                    COPYDATASTRUCT dat 
    = (COPYDATASTRUCT) Marshal.PtrToStructure(
                                                              m.LParam, 
    typeof (COPYDATASTRUCT));
                    handlerMessage(HttpUtility.UrlDecode(dat.lpData));
                    
    return;
                }
                
    base.WndProc(ref m);
            }

            
    #region Nested type: COPYDATASTRUCT

            [StructLayout(LayoutKind.Sequential)]
            
    public struct COPYDATASTRUCT
            {
                
    public IntPtr dwData;
                
    public int cbData;
                [MarshalAs(UnmanagedType.LPWStr)] 
    public string lpData;
            }

            
    #endregion

            
    #region Nested type: handlerMessageDelegate

            
    private delegate void handlerMessageDelegate(string message);

            
    #endregion
        }
    }

    大概解释一下,COPYDATASTRUCT用来接受WM_COPYDATA传递过来的数据,因为要传递宽字符,所以用UnmanagedType.LPWStr修饰,重写WndProc方法可以有机会在第一事件捕获本窗体收到的windows消息并加以处理,我们在这里截获WM_COPYDATA消息,用Marshal.PtrToStructure把收到的消息转换成c#的结构体,并把收到的数据进行url解码,然后调用handlerMessage方法来处理,handlerMessage方法是一个简化的winform多线程方案,如果InvokeRequired为true就调用BeginInvoke调用本身,否则执行给文本框直接赋值,这样做是为了不让界面线程把接受消息的线程给hang住。


    主要参考链接


    基于Mozilla平台的扩展开发(续)----XPCOM组件篇
    实战 Firefox 扩展开发
    FireFox Extension 开发 Helloworld
    How to Build an XPCOM Component in Javascript
    Firefox 3 for developers
    【Firefox扩展】XPInstall的安装脚本浅析

    其它参考链接


    86件Firefox浏览器能而IE不能做的事
    http://blog.donews.com/demson/archive/2004/11/28/185689.aspx

    101件Firefox能而IE不能做的事
    http://www.qqread.com/surfing/x241103051_3.html

    Creating XPCOM Components
    http://www.mozilla.org/projects/xpcom/book/cxc/

    VC中自定义消息实现
    http://citycowboy.blog.sohu.com/82319571.html

    进程通信问题——RegisterWindowMessage和PostMessage
    http://topic.csdn.net/t/20030522/23/1821663.html

    在.NET中基于Windows消息的IPC实现
    http://www.cnblogs.com/wzd24/archive/2007/05/22/755013.html

    LPCTSTR、LPTSTR、_T和CString几种类型的区别
    http://topic.csdn.net/t/20020928/11/1060535.html

    如何获得字符串的长度?
    http://topic.csdn.net/t/20030105/20/1329194.html

    BSTR、char*和CString转换
    http://www.cnblogs.com/justin/archive/2005/03/24/125057.aspx

    用C#获得Autosuggest中数据
    http://www.winbile.net/bbs/forums/threads/1024219.aspx

    VC传给 C#的char*指针,C#中怎么使用
    http://www.itzhe.cn/article/20080229/97292.html

    利用XPCOM技术实现Firefox跨平台文件操作JavaScript类
    http://www.cnblogs.com/jessezhao/archive/2008/06/10/1216146.html

    用C++ 编写 Mozilla XPCom
    http://rogerfd.cn/?p=165

    创建C++ XPCOM组件
    http://zhouchengly.blogspot.com/2007/06/creating-c-xpcom-component-xpcom-step.html

    利用VC创建XPCOM组件
    http://hi.baidu.com/xzq2000/blog/item/30260ff4f75cbd6fddc474ac.html

    一步一步创建VC2005解决方案(转)
    http://www.cnblogs.com/rainbowzc/archive/2008/09/09/1287880.html

    用Visual Studio创建XPCOM组件
    http://blog.csdn.net/chinesejimmy/archive/2007/06/01/1634075.aspx

    How to build a binary XPCOM component using Visual Studio
    https://developer.mozilla.org/en/How_to_build_a_binary_XPCOM_component_using_Visual_Studio

    Firefox插件开发-技术和开发网站
    http://www.yuanma.org/data/2007/0730/article_2776.htm

    XPCOM
    https://developer.mozilla.org/cn/XPCOM

    A C++ Firefox component intercepting/operating HTML DOM
    http://www.codeproject.com/KB/library/firefox_component.aspx

    创建C++ XPCOM组件
    http://zhouchengly.blogspot.com/2007/06/creating-c-xpcom-component-xpcom-step.html

    怎样将char *转换为LPCWSTR ?
    http://topic.csdn.net/t/20030701/00/1975664.html

    VS2005中const char *转换为LPCWSTR的方法Unicode
    http://chenet.blogbus.com/logs/28070247.html

    在eclipse中动态开发Firefox扩展
    http://xinsync.xju.edu.cn/index.php/archives/2135

    技巧: 使用 Firefox 3.0 Extensions 中新的微格式 API
    http://www.ibm.com/developerworks/cn/xml/x-tipffoxmicroapi/index.html?ca=drs-cn-0630

    用C++ 编写 Mozilla XPCom
    http://rogerfd.cn/?p=165

    XPCOM LINUX下的组件开发技术
    http://blog.csdn.net/wangweixing2000/archive/2007/09/03/1770576.aspx

    关于XPCOM开发的问题
    http://topic.csdn.net/u/20081110/10/e3d1b8d2-2c30-4ff7-b712-0c4951b18e37.html

     

  • 相关阅读:
    OpenCV学习(7)--
    OpenCV学习(6)--更多形态转化、Hit-or-Miss变换、Hit-or-Miss变换、图像金字塔
    Linux基本操作
    设计模式
    利用Python进行数据分析:【Matplotlib】
    利用Python进行数据分析:【Pandas】(Series+DataFrame)
    利用Python进行数据分析:【NumPy】
    利用Python进行数据分析:【IPython】
    数据结构与算法(C/C++版)【排序】
    《操作系统》学习笔记
  • 原文地址:https://www.cnblogs.com/onlytiancai/p/wawa_firefox_plus.html
Copyright © 2020-2023  润新知