蛙蛙推荐:蛙蛙牌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 /
  {
0xb7b04070 0x45fc 0x4635 , /
    { 
0xb2 0x19 0x7a 0x17 0x2f 0x80 0x6b 0xee  }}

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",最后οnclick="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 " 0 0 );
    
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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值