1. 程式人生 > >蛙蛙推薦:蛙蛙牌firefox外掛

蛙蛙推薦:蛙蛙牌firefox外掛

上次給大家演示了抓取IE核心瀏覽器的網頁,這次和大家一起寫一個抓取firefox頁面文字的例子。Firefox有自身的一套結構良好的外掛機制,但要深入開發Firefox外掛的話要了解javascript,XUL,XPCOM以及一些c++的基本常識,本貼算是給想開發Firefox外掛的朋友入門。

我們先來了解什麼是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(instring  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(
constchar*str) =0;

};

/* Use this macro when declaring classes that implement this interface. */#define NS_DECL_IWAWACOMP /
  NS_IMETHOD SendSysMessage(
constchar*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(
constchar*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(
constchar*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(
constchar*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(
constchar*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)目錄下新建一個[email protected]的檔案,用記事本開啟,輸入我們外掛的開發路徑,比如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>[email protected]</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
{
    
publicpartialclass Form1 : Form
    {
        
privateconstint WM_COPYDATA =0x004A;

        
public Form1()
        {
            InitializeComponent();
        }

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

        
protectedoverridevoid 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)]
        
publicstruct COPYDATASTRUCT
        {
            
public IntPtr dwData;
            
publicint cbData;
            [MarshalAs(UnmanagedType.LPWStr)] 
publicstring lpData;
        }

        
#endregion#region Nested type: handlerMessageDelegateprivatedelegatevoid handlerMessageDelegate(string message);

        
#endregion
    }
}

大概解釋一下,COPYDATASTRUCT用來接受WM_COPYDATA傳遞過來的資料,因為要傳遞寬字元,所以用UnmanagedType.LPWStr修飾,重寫WndProc方法可以有機會在第一事件捕獲本窗體收到的windows訊息並加以處理,我們在這裡截獲WM_COPYDATA訊息,用Marshal.PtrToStructure把收到的訊息轉換成c#的結構體,並把收到的資料進行url解碼,然後呼叫handlerMessage方法來處理,handlerMessage方法是一個簡化的winform多執行緒方案,如果InvokeRequired為true就呼叫BeginInvoke呼叫本身,否則執行給文字框直接賦值,這樣做是為了不讓介面執行緒把接受訊息的執行緒給hang住。


主要參考連結

其它參考連結

 

相關推薦

推薦firefox外掛

上次給大家演示了抓取IE核心瀏覽器的網頁,這次和大家一起寫一個抓取firefox頁面文字的例子。Firefox有自身的一套結構良好的外掛機制,但要深入開發Firefox外掛的話要了解javascript,XUL,XPCOM以及一些c++的基本常識,本貼算是給想開發Firefox外掛的朋友入門。 我們先來了解

強烈推薦240多個jQuery外掛

概述 jQuery 是繼 prototype 之後又一個優秀的 Javascript 框架。其宗旨是—寫更少的程式碼,做更多的事情。它是輕量級的 js 庫(壓縮後只有21k) ,這是其它的 js 庫所不及的,它相容  CSS3,還相容各種瀏覽器(IE 6.0+, FF 1

推薦教你配置linux+mysql+.net環境

三、安裝配置mysql 有了apt,安裝mysql也很簡單,下面一個命令搞定 sudo apt-get install mysql-server mysql伺服器大約有100多M,不過咱們的源的速度快,每秒100多K,我洗了澡出來就裝好了,中間需要輸入mysql root賬戶的密碼,別的啥也不用管,因為

推薦c#編寫網路電話

{         WaveFormat format =new WaveFormat();         //聲音的格式,通常使用WAVE_FORMAT_PCM來設定,         //因為PCM是比較常用的聲音格式。         format.FormatTag = WaveFormat

推薦教你文字聚類

{    //1、獲取文件輸入string[] docs = getInputDocs("input.txt");    if (docs.Length <1)    {        Console.WriteLine("沒有文件輸入");        Console.Read();        

[BZOJ3036]綠豆的歸宿DAG上DP+期望DP

分析: 其實這道題是可以正著DP的(即不需要在反圖上拓撲排序)(為什麼好多人都說不能?) 我們令f[i]表示從起點1出發到點i的期望距離,如果一些點能到達點i,那麼這些點中的每個點對f[i]的貢獻為f[j]*po[j],po[j]表示通過j到達i的概率。實際上,我們令p[i]表示從起點1出發能到達i的概率,

甲小戰記PHP2Java 排雷指南

(馬蜂窩技術原創內容,申請轉載請在公眾後後臺留言,ID:mfwtech ) 大家好,我是來自馬蜂窩電商旅遊平臺的甲小蛙,從前是一名 PHP 工程師,現在可能是一名 PHJ 工程師,以後...... 前陣子,我從大道訊息聽說公司商品訂單技術棧要推 Java。我是一個喜歡走在時代前列線上的人,凡是要做到領先。

推薦firefox元件廣告彈窗阻止外掛

推薦一個外掛,可以阻止廣告彈窗:https://addons.mozilla.org/en-us/firefox/addon/adblock-plus/ 煩人的廣告,把訪客當成了弱智一樣。雖然自己是一個站長,但是最反感去訪問某些網站,一進入,滑鼠不小心動了一下,就彈窗那種

分針網——每日推薦 各路神仙關於閉包概念不同解讀

閉包 寫在前面: 閉包是被講爛的內容,但是當我不了解的情況下,看過很多教程,聽過很多道理,還是無法完全理解閉包這個東西。所以想要寫一篇比較詳細,前端小白也能夠真正理解閉包概念的幹貨文章,本文參考很多閉包資料,希望能真正把閉包這個東西講清楚,

分針網——每日推薦 根據屏幕大小,加載不同大小的圖片

加載圖片 引言 今天要介紹的東西,很簡單,但是對於前端響應式的時候是個很重要的知識; 我們在用bootstrap這類前端框架時, 雖然頁面局部通過media query實現了,頁面始終無滾

強力推薦Atom入坑必備插件

格式化 方便 tom 一個 rip 設置 等等 依靠 同步 強力推薦:Atom入坑必備插件 Atom作為Javascript/CSS/HTML等前端編輯器利器,其強大功能依靠各種插件,以下是筆者在入坑階段,精挑細選總結出的必不可少的插件,熟悉運用這些插件,一定成噸提高生產效

java書籍推薦《Java SE 6 技術手冊》

rate rst tail right 5.1 important hid 新手 log Java SE 6 技術手冊 或 Java SE 6 技術手冊 Java SE 6 技術手冊 為什麼選擇用 Markdown?僅僅是單純把文件

好書推薦OpenSuse

-- 之前 org href css ets ces shadow stop   現在正值暑期,有大把的空閑時間,覺得有必要好好琢磨琢磨,進一步學習認識網站相關的東東。   之前,出於某種考慮,購買了一年的搬瓦工虛擬主機(vps),每月有500G的流量。單純使用Shadow

(轉)Android開發書籍推薦從入門到精通系列學習路線書籍介紹

成長 程序員 理論 targe base 官方 app als 自己的 Android開發書籍推薦:從入門到精通系列學習路線書籍介紹 轉自:http://blog.csdn.net/findsafety/article/details/52317506 很多時候我們都會

GitHub 萬星推薦黑客成長技術清單

安全 probable security 滲透 target fig 自己 質量 理論 GitHub 萬星推薦:黑客成長技術清單 導語:如果你需要一些安全入門引導,“Awesome Hacking”無疑是最佳選擇之一。 最近兩天,在reddit安全板塊和Twi

21ic編輯推薦從單片機開始的程序運行

決定 oda 單片機編程 使用率 映射 bios alloc 瓶頸 str 一直不清楚單片機中程序的執行過程,就是知道一個程序總是從一個main函數開始執行,然後把程序段存放在ROM裏面,動態數據存放在RAM裏面,而單片機的RAM資源又是及其的稀少,所以要省著用,但是到底怎

開源項目推薦e-example / Springboot+bootstrap + ……

gateway 環境變量 source cal 持久層 tap utf-8 war 持久 前言:   我想要找一個 springboot + bootstrap 的例子介紹,然後搜索到了這個開源項目。   所有能跑起來的項目都有研究價值,看看這個項目的文檔。目前正好滿足我想

書籍推薦《實戰Java虛擬機——JVM故障診斷與性能優化》下載

java實戰java虛擬機jvm本書詳細介紹Java虛擬機的基本原理和優化診斷方法。其中重點介紹Java虛擬機的體系結構、常用的虛擬機參數、Java虛擬機的垃圾回收原理、算法以及目前虛擬機所支持的各種垃圾回收器及其區別、特點和使用方法。在實踐和調優方面,重點介紹了Java的堆、棧分析方法,性能調優的一般思路、

育兒書籍推薦《雙向養育》

溝通 適合 優秀 -s ges font pan ima left 《雙向養育》 原書名:《Breakthrough parenting》 作者:傑恩·梅傑(Jayne A. Major) 之所以推薦該本育兒書籍,最開始的時候對各種琳瑯滿目的育兒書籍,找本優秀的

淺談商品推薦如何猜中用戶的心思?

維度 活動 不同 -i 鄰居 表示 找到 包括 一起 去商場前,你告訴自己今天只買T恤,出商場時,你還是拎了大包小包……導購員看你摸了摸連衣裙,讓你免費試穿,結果你這一穿就不願脫下了,而且一件接一件。導購猜測顧客喜歡什麽,推薦顧客試穿,滿足雙方各自的心理訴求來達成交易。電