自動填表的IE面板插件
簡介
IE的面板實際就是嵌入到IE瀏覽器中的子窗體。面板有兩種顯示模式,一種是垂直顯示在瀏覽器的左側,一種是水平顯示在瀏覽器的下方。IE瀏覽器內置提供了很多的標準面板,如收藏夾和搜索面板這些是垂直的面板,而每日提示和討論面板則是水平的面板。
此外我們還可以通過實現COM組件來添加我們自己的瀏覽器面板到IE中。當我們的面板COM組件注冊后,它會被添加到瀏覽器的查看菜單的瀏覽器欄的子菜單下。當用戶選中該菜單項后,該面板就會顯示在瀏覽器中。
實現面板COM組件
接下來我們將實現類似于IE內置的收藏夾的一個面板,不過它不是用來收藏網址的,而是用來運行程序的。下面是它的示意圖:
同所有的COM組件一樣,面板組件首先要實現IUnknown 和IClassFactory接口,不過Borland提供了TComObject類,這個類已經實現了前面兩個接口,我們因此就不需要再重造輪子了,只要從TComObject類繼承就可以了。
首先選擇菜單File | New | ActiveX | Com Object命令,創建一個TDelphiBand的COM組件框架
然 后我們就需要實現IDeskBand,IObjectWithSite和IPersistStreamInit或者IPersistStream接口了。 其中IPersistStreamInit和IPersistStream接口可以用來保存面板的各種狀態和信息,IPersistStreamInit 和IPersistStream接口相比就是多了一個InitNew的方法,這個方法可以用來初始化面板組件的狀態。在本文中,由于不涉及信息的保存,因 此這個接口的方法的實現大部分都是直接返回E_NOTIMPL表示該方法沒有被實現。除了GetClassID方法,當系統調用這個方法的時候,我們需要 返回COM組件的GUID標識符。
function TDelphiBand.GetClassID(out classID: TCLSID): HResult;
begin
classID := CLSID_DelphiBand;
Result := S_OK;
end;
IObjectWithSite接口,顧 名思義這個接口就是一個嵌入在COM容器中的組件需要實現的接口,當用戶選中一個瀏覽器面板的時候,IE這個COM容器會調用面板組件的 IObjectWithSite的SetSite方法,這個方法傳遞過來的punkSite參數就是COM容器的IUnknown接口,通過這個接口我們 可以獲得IE提供的各個COM接口,進而可以調用IE提供的所有功能。這個方法的一般實現是:
1、 如果方法傳過來的punkSite參數為nil,表示面板組件正在被隱藏釋放。這時方法的返回結果必須為S_OK。
2、 如果punkSite參數不為nil,則通過punkSite獲得我們所需要的COM接口(如IE的IWebBrowser接口),并將其保存起來。
下面是SetSite方法的實現代碼:
function TDelphiBand.SetSite(const pUnkSite: IUnknown): HResult;
begin
if Assigned(pUnkSite) then begin
//獲得IInputObjectSite接口,并保存起來,后面會用它通知瀏覽器
//面板焦點的變化情況
Site := pUnkSite as IInputObjectSite;
//通過調用GetWindow來獲得父窗體的句柄,并保存
(pUnkSite as IOleWindow).GetWindow(ParentWnd);
//獲得IE的IWebBrowser2接口
(Site as IServiceProvider).QueryService(IWebbrowserApp, IWebbrowser2, IE);
end;
Result := S_OK;
end;
IObjectWithSite還有一個GetSite方法也需要實現,方法的定義如下:
function GetSite(const riid: TIID; out site: IUnknown): HResult; stdcall;
其中我們需要返回在 SetSite方法中保存的Site接口,然后從site接口獲得riid參數所需要的接口,如果Site接口為nil,方法的返回的HResult需要 設定為E_Fail,表示調用失敗。如果Site接口支持riid指定的接口的話,我們就返回S_OK表示成功,如果Site接口不為nil,但是也不支 持riid的接口的話,我們就返回E_NOINTERFACE,表示無法獲得riid對應的接口。代碼實現如下:
function TDelphiBand.GetSite(const riid: TIID; out site: IUnknown): HResult;
begin
if Assigned(Site) then Result := Site.QueryInterface(riid, site)
else Result := E_FAIL;
end;
接下來的IDeskBand接口就是我們面板組件所要實現的核心接口了。它包括下面這些方法。
function GetBandInfo(dwBandID, dwViewMode: DWORD; var pdbi: TDeskBandInfo):
HResult; stdcall;
function ShowDW(fShow: BOOL): HResult; stdcall;
function CloseDW(dwReserved: DWORD): HResult; stdcall;
function ResizeBorderDW(var prcBorder: TRect; punkToolbarSite: IUnknown;
fReserved: BOOL): HResult; stdcall;
function GetWindow(out wnd: HWnd): HResult; stdcall;
function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
其中ContextSensitiveHelp方法是用來提供上下文幫助支持的,未來簡單起見,這里我們不提供上下文支持,所以簡單返回E_NOTIMPL就可以了。而ResizeBorderDW 方法系統也從來不會調用,因此我們也返回E_NOTIMPL。
獲得面板的顯示信息
對于GetWindow方法來說,我們需要返回要嵌入到IE中的子窗體的句柄,以便容器用來顯示。下面是GetWindow方法的實現:
function TDelphiBand.GetWindow(out wnd: HWnd): HResult;
begin
//如果還沒有創建面板窗體,則創建
if not Assigned(BandForm) then
begin
//父窗體是先前在SetSite方法中獲得的父窗體
BandForm := TBandForm.CreateParented(ParentWnd);
//將IE賦值給面板界面的相應變量
BandForm.IE:=IE;
End;
//返回子窗體的句柄
Wnd := Bandform.Handle;
SavedWndProc := Bandform.WindowProc;
//替換默認的窗體消息過程
Bandform.WindowProc := BandWndProc;
Result := S_OK;
end;
此外,因為面板對象是以子窗體的形式顯示,它還必須實現窗口消息過程。這里我們使用BandWndProc過程替換了窗體默認的消息處理過程,BandWndProc的實現如下:
procedure TDelphiBand.BandWndProc(var Message: TMessage);
begin
//當我們的窗體的子控件,如編輯框獲得焦點后,系統會發WM_ParentNotify消息給
//我們的窗體,這時要通知瀏覽器我們面板獲得了焦點,這樣IE才會將快捷鍵發送給
//我們的窗體
if (Message.Msg = WM_PARENTNOTIFY) then
begin
Hasfocus:=True;
FocusChange(True);
end;
//然后調用保存的原有窗體消息過程來處理
SavedWndProc(Message);
end;
FocuseChanged方法用來通知瀏覽器焦點的變化情況,實現如下:
procedure TDelphiBand.FocusChange(bHasFocus: Boolean);
begin
//調用先前保存的IInputObjectSite的OnFocusChangeIS方法通知瀏覽器
//焦點變化。
if (Site <> nil) then Site.OnFocusChangeIS(Self, bHasFocus);
end;
系統獲得子窗體的同時,因 為IE本身對子窗體的顯示區域是有一定限制的,所以它還需要知道面板窗體的某些屬性,如最大顯示尺寸、最小顯示尺寸、改變大小時的尺寸變化幅度等信息,這 些信息它是通過調用面板組件的IDeskBand接口的GetBandInfo方法來獲得的。下面是GetBandInfo方法的聲明:
function GetBandInfo(dwBandID, dwViewMode: DWORD; var pdbi: TDeskBandInfo):HResult;
其中dwBandID參數是面板的標識符,這個標識符是COM容器賦予的,我們需要保存這個ID。dwViewMode表示面板的顯示模式:
DBIF_VIEWMODE_FLOATING |
浮動面板 |
DBIF_VIEWMODE_NORMAL |
水平面板 |
DBIF_VIEWMODE_TRANSPARENT |
面板是透明的 |
DBIF_VIEWMODE_VERTICAL |
面板是垂直面板 |
pdbi參數則是一個TDESKBANDINFO 結構,結構定義如下:
DESKBANDINFO = packed record
dwMask: DWORD;
ptMinSize: TPointL;
ptMaxSize: TPointL;
ptIntegral: TPointL;
ptActual: TPointL;
wszTitle: array[0..255] of WideChar;
dwModeFlags: DWORD;
crBkgnd: COLORREF;
end;
下表是關于結構中各個成員的詳細說明:
dwMask |
指定被請求的面板信息的掩碼,是下面參數的組合。 |
DBIM_MINSIZE |
請求面板最小尺寸信息 |
DBIM_MAXSIZE |
請求面板最大尺寸信息 |
DBIM_INTEGRAL |
請求面板尺寸改變的幅度信息 |
DBIM_ACTUAL |
請求面板默認尺寸信息 |
DBIM_TITLE |
請求面板標題信息 |
DBIM_MODEFLAGS |
請求dwModeFlags參數代表的額外的面板顯示信息 |
DBIM_BKCOLOR |
請求面板背景色信息 |
ptMinSize |
返回面板最小尺寸,最小寬度保存在x成員,最小高度保存在y成員 |
ptMaxSize |
返回面板最大尺寸,最大高度放在y成員中,x成員不被使用。如果最大高度沒有限制,應該將y賦值為-1 |
ptIntegral |
返回面板尺寸改變幅度,垂直改變幅度放在y中,x不使用。如果dwModeFlags不包含DBIMF_VARIABLEHEIGHT,這個信息被忽略。 |
ptActual |
返回面板的默認尺寸。x保存寬度,y保存高度,容器會盡量使用這個尺寸來顯示面板,但不保證一定使用這個尺寸。 |
wszTitle |
返回面板的標題 |
dwModeFlags |
返回下面顯示方式的組合 |
DBIMF_NORMAL |
缺省的顯示模式 |
DBIMF_VARIABLEHEIGHT |
面板的高度可以被改變。 |
DBIMF_DEBOSSED |
面板采用下陷的樣式來顯示 |
DBIMF_BKCOLOR |
面板將以crbkgnd指定的顏色作為自己的背景色 |
crBkgnd |
背景色 |
當系統調用GetBandInfo方法后,我們只要根據系統請求返回相應的面板信息就可以了,代碼實現如下:
function TDelphiBand.GetBandInfo(dwBandID, dwViewMode: DWORD; var pdbi: TDeskBandInfo): HResult;
begin
//保存面板ID,以便后面使用
BandId := dwBandID;
//如果請求最小尺寸,則窗體的最小寬度是窗體設計時的寬度
if (pdbi.dwMask or DBIM_MINSIZE) <> 0 then
begin
pdbi.ptMinSize.y := Bandform.width;
pdbi.ptMinSize.x := -1;
end;
//最大尺寸無限制
if (pdbi.dwMask or DBIM_MAXSIZE) <> 0 then
begin
pdbi.ptMaxSize.x := -1;
pdbi.ptMaxSize.y := -1;
end;
//大小改變幅度都為1
if (pdbi.dwMask or DBIM_INTEGRAL) <> 0 then
begin
pdbi.ptIntegral.x := 1;
pdbi.ptIntegral.y := 1;
end;
//默認尺寸為窗體設計尺寸,注意我們這里的面板是垂直面板,因此x對應的高度
//y對應的是寬度
if (pdbi.dwMask or DBIM_ACTUAL) <> 0 then
begin
pdbi.ptActual.x := Bandform.Height;
pdbi.ptActual.y := bandform.Width;
end;
//面板的寬度可調
if (pdbi.dwMask or DBIM_MODEFLAGS) <> 0 then
begin
pdbi.dwModeFlags := DBIMF_VARIABLEHEIGHT;
end;
//忽略背景色的設置,因為Delphi的窗體背景色是VCL自己畫的,不使用
//Windows默認顏色
if (pdbi.dwMask or DBIM_BKCOLOR) <> 0 then
begin
pdbi.dwMask := pdbi.dwMask and (not DBIM_BKCOLOR);
end;
//返回面板的標題,注意返回的字符串必須是Unicode的
if (Pdbi.dwMask and DBIM_TITLE) = DBIM_TITLE then
begin
FillChar(pdbi.wszTitle, SizeOf(Caption) + 1, ' ');
StringToWideChar(Caption, @pdbi.wszTitle, Length(Caption) + 1);
end;
Result := NOERROR;
end;
當面板需要顯示或隱藏的時候系統會調用IDeskBand接口的ShowDW方法通知面板改變窗體的顯示狀態,方法的fShow布爾參數表示需要顯示還是隱藏窗體,代碼實現如下:
function TDelphiBand.ShowDW(fShow: BOOL): HResult;
begin
Hasfocus:=fShow;
FocusChange(fShow);
Result := S_OK;
end;
注意當顯示或隱藏的時候,我們還需要調用FocusChange方法通知瀏覽器焦點發生了變化。
當IE需要關閉面板時,會調用IDeskBand的CloseDW方法,這時我們需要銷毀面板窗體,代碼實現如下:
function TDelphiBand.CloseDW(dwReserved: DWORD): HResult;
begin
if BandForm <> nil then BandForm.Destroy;//為什么不是調用Free?
Result := S_OK;
end;
用戶輸入支持
實現了上面三個接口方法的的面板還是僅僅能夠用來顯示信息,如果我們需要在面板中提供一些編輯框,允許用戶輸入Email信息的話,那么還必須實現IInputObject接口。IInputObject接口有下面三個方法:
function UIActivateIO(fActivate: BOOL; var lpMsg: TMsg): HResult; stdcall;
function HasFocusIO: HResult; stdcall;
function TranslateAcceleratorIO(var lpMsg: TMsg): HResult; stdcall;
Internet瀏覽器會在面板被激活和失活時調用UIActivateIO方法通知面板對象,這時面板應該調用SetFocus獲得焦點。方法的fActivate表示是激活還是失活的狀態,代碼實現如下:
function TDelphiBand.UIActivateIO(fActivate: BOOL; var lpMsg: TMsg): HResult;
begin
Hasfocus:=fActivate;
if HasFocus then Bandform.SetFocus;
Result := S_OK;
end;
當瀏覽器想要知道目前是哪個子窗體獲得了焦點的時候,它會調用HasFocusIO方法,如果我們的面板獲得了焦點,那么就應該返回S_OK,否則返回S_False。代碼實現如下:
function TDelphiBand.HasFocusIO: HResult;
begin
Result:=Integer(not HasFocus);//S_OK對應的常數為0,所以要not 一下
end;
最后一個TranslateAcceleratorIO方法允許面板處理鍵盤快捷鍵消息,代碼實現如下:
function TDelphiBand.TranslateAcceleratorIO(var lpMsg: TMsg): HResult;
begin
if (lpMsg.WParam <> VK_TAB) then begin
TranslateMessage(lpMSg);
DispatchMessage(lpMsg);
Result := S_OK;
end
else Result := S_FALSE;
end;
右鍵菜單支持
另 外如果我們還想在面板中顯示一個右鍵菜單以便用戶能夠快速的調用一些命令的話,如顯示一個關于窗口等。我們還需要實現IContextMenu接口。當 IE需要返回右鍵菜單項的時候,它會調用面板的IContextMenu接口的QueryContextMenu方法,這里我們向菜單添加了一個關于菜 單,下面是實現代碼:
function TDelphiBand.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast, uFlags: UINT): HResult;
begin
//添加關于菜單
InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst , 'About...');
//返回添加的菜單數目
Result := 1;
end;
當菜單處于高亮狀態時,IE會調用菜單接口的GetCommandString方法獲得上下文相關幫助,并顯示在瀏覽器的狀態條上,這里我們簡單返回NOERROR,表示沒有相關幫助就可以了。
function TDelphiBand.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult;
begin
Result := NOERROR;
end;
最后,當用戶點擊了菜單后,IE會調用菜單接口的InvokeCommand來實現菜單命令,我們只要簡單地顯示一個關于對話框就可以了。
function TDelphiBand.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
begin
//如果是被程序調用,則退出
if (HiWord(Integer(lpici.lpVerb)) <> 0) or (LoWord(lpici.lpVerb) > 0) then
begin
Result := E_FAIL;
Exit;
end;
case LoWord(lpici.lpVerb) of
0: Showmessage('IE瀏覽器面板組件演示程序1.0');
end;
Result := NO_ERROR;
end;
程序界面
COM組件基本完成之后,就該設計我們的界面的功能了。現在瀏覽很多網站時都要填寫登錄界面或者其它一些注冊 信息,非常煩瑣,所以下面我就要寫一個自動填表的工具。界面非常簡單,先放一個TCoolbar,然后放上一個列表框和一個保存按鈕和一個填表按鈕,自動 填表的過程如下:
1. 當用戶填寫完表單信息后,點擊保存按鈕,COM組件會從頁面上獲取填寫的表單信息,并將其保存到一個配置文件中。
2. 等用戶下回再訪問該頁面時,選中被保存的表單,然后點擊加載,COM組件就會自動填寫上次保存的信息。
3. 考慮到很多網站的都要求輸入密碼,為了讓用戶在提交時,能看清填寫的被*號遮蔽的密碼,向導在加載表單時,會截獲提交按鈕的事件,在用戶點擊提交按鈕時,會顯示一個消息框,顯示填寫的密碼內容。
下面是保存表單的代碼:
//
保存頁面表單內的值
procedure TBandForm.ActionSaveExecute(Sender: TObject);
var
HtmlDocument: IHTMLDocument2;
HtmlForms: IHTMLElementCollection;
HtmlForm: IHTMLFormElement;
FormName: WideString;
ItemIndex, ItemName: OleVariant;
InputElement: IHTMLInputElement;
I: Integer;
InputName, InputValue:
string;
begin
HtmlDocument := IE.Document
as IHTMLDocument2;
//
目前只能處理頁面的第一個表單
HtmlForms := HtmlDocument.forms;
if HtmlForms.Length =
0
then
Exit;
HtmlForm := HtmlForms.item(
0,
0)
as IHTMLFormElement;
//
獲得表單的名稱
FormName := trim(HtmlForm.Get_name);
if (FormName =
'')
or FIniFile.SectionExists(FormName)
then
while True
do
begin
FormName := Trim(InputBox(
'
輸入表單名稱
',
'
請輸入表單名稱
',
''));
if FormName =
''
then
begin
ShowMessage(
'
表單名稱不能為空,請重新輸入
');
continue;
end;
if FIniFile.SectionExists(FormName)
then
begin
ShowMessage(
'
表單名稱重復,請重新輸入
');
continue;
end;
break;
end;
for I :=
0
to HtmlForm.Length -
1
do
begin
ItemIndex :=
0;
ItemName := I;
if Supports(HtmlForm.item(ItemName, ItemIndex), IHTMLInputElement,
InputElement)
then
if (InputElement.type_ =
'text')
or (InputElement.type_ =
'password')
then
begin
InputName := InputElement.Name;
InputValue := InputElement.Value;
FIniFile.WriteString(FormName, InputName, InputValue);
end;
end;
//
更新
ini
文件
FIniFile.UpdateFile;
//
更新界面列表框的內容
FiniFile.ReadSections(lbForms.Items);
end;
保存表單內容時,首先通過IE獲得頁面的DOM接口IHtmlDocument,然后通過HtmlDocument.forms
方法獲得表單域的集合,為了簡單起見,這里我們只處理頁面中的第一個表單的
IHtmlFormElement
接口。通過表單接口,獲得表單名稱,接著遍歷表單內的
Input
元素,獲得輸入元素的名稱及值并將其寫入配置文件。注意這里我們只處理了簡單的文本輸入框和密碼輸入框(通過判斷頁面元素的
type_
屬性),至于下拉框等頁面元素則不考慮。
下面則是加載表單的內容的代碼:
procedure TBandForm.ActionLoadExecute(Sender: TObject);
var
Section:
string;
HtmlDocument: IHTMLDocument2;
HtmlForms: IHTMLElementCollection;
HtmlForm: IHTMLFormElement;
FormName: WideString;
Name, Index: OleVariant;
ItemIndex, ItemName: OleVariant;
InputElement: IHTMLInputElement;
I, J: Integer;
InputName, InputValue:
string;
begin
if lbForms.ItemIndex<
0
then Exit;
//
加載表單內容
Section := lbForms.Items[lbForms.ItemIndex];
HtmlDocument := IE.Document
as IHTMLDocument2;
//
只能設定第一個表單的內容
HtmlForms := HtmlDocument.forms;
if HtmlForms.Length =
0
then
Exit;
HtmlForm := HtmlForms.item(
0,
0)
as IHTMLFormElement;
for I :=
0
to HtmlForm.Length -
1
do
begin
ItemIndex :=
0;
ItemName := I;
if Supports(HtmlForm.item(ItemName, ItemIndex), IHTMLInputElement,
InputElement)
then
if (InputElement.type_ =
'text')
or (InputElement.type_ =
'password')
then
begin
InputName := InputElement.Name;
InputValue := InputElement.Value;
InputElement.Set_Value(FIniFile.ReadString(Section, InputName, InputValue));
end
else if (InputElement.type_=
'submit')
then
(InputElement
as IHtmlElement).OnClick:=OleVariant(Self
as IDispatch);
end;
end;
加載表單的過程類似,從配置信息中讀取表單內容,并通過
IHtmlInputElement
接口的
Set_Value
方法設定相應的值,不同的地方在于判斷輸入元素的類型,如果是
submit
提交類型的按鈕,則截獲按鈕的
OnClick
事件,以便顯示自動填表功能所填寫的密碼值。為了截獲的頁面元素的
OnClick
事件,必須提供一個
IDispatch
接口用來處理點擊事件。
IDispatch
定義了四個方法,其中只有
Invoke
方法是必須的,其它方法直接返回
E_NotImpl
就可以了,下面就是窗體的
Invoke
方法:
function TBandForm.Invoke(
DispID: Integer;
const IID: TGUID;
LocaleID: Integer; Flags: Word;
var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HResult;
var
Strings:TStringList;
begin
Strings:=TStringList.Create;
try
FiniFile.ReadSectionValues(lbForms.Items[lbForms.ItemIndex], Strings);
ShowMessage(Strings.Text);
Result:=S_OK;
finally
Strings.Free;
end;
end;
COM組件的注冊
實現完COM組件的功能后,剩下的就是注冊到系統中以便IE加載了,面板COM組件首先要把自己的GUID寫到注冊表中HKEY_CLASS_ROOT下,下面是具體的注冊表項:
HKEY_CLASSES_ROOT
CLSID
{面板組件的CLSID GUID}
(Default) = 顯示在查看|瀏覽器欄的菜單文本
InProcServer32
(Default) = DLL路徑
ThreadingModel= Apartment
同時面板還要在IE的注冊表項下填寫下面信息:
HKEY_LOCAL_MACHINE
Software
Microsoft
Internet Explorer
Toolbar
{面板組件的CLSID GUID}
最后,對于IE垂直面板來說,我們還要注冊COM組件的類別:
HKEY_CLASSES_ROOT\CLSID\<面板GUID>\
Implemented Categories\{00021493-0000-0000-C000-000000000046}
要注意的是從IE5開始,注冊一個新的面板,需要刪除下面的注冊表項,迫使IE重建緩存來識別新的面板。
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\
Component Categories\{00021493-0000-0000-C000-000000000046}\Enum
下面是DeskBand類工廠的實現代碼:
TDelphiBandFactory = class(TComObjectFactory)
private
procedure AddKeys;
procedure RemoveKeys;
public
procedure UpdateRegistry(Register: Boolean); override;
end;
procedure TDelphiBandFactory.UpdateRegistry(Register: Boolean);
begin
inherited UpdateRegistry(Register);
if Register then AddKeys else RemoveKeys;
end;
procedure TDelphiBandFactory.AddKeys;
var S: string;
begin
S := GUIDToString(CLSID_DelphiBand);
with TRegistry.Create do
try
//刪除注冊表項,迫使IE重建緩存,發現新面板
DeleteKey('Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\
PostSetup\Component Categories\' + VerticalBand + '\Enum');
RootKey := HKEY_CLASSES_ROOT;
if OpenKey('CLSID\' + S, True) then
begin
WriteString('', '&Delphi Band');
CloseKey;
end;
if OpenKey('CLSID\' + S + '\InProcServer32', True) then
begin
WriteString('ThreadingModel', 'Apartment');
CloseKey;
end;
if OpenKey('CLSID\' + S + '\Implemented Categories\' + VerticalBand, True)
then CloseKey;
finally
Free;
end;
end;
procedure TDelphiBandFactory.RemoveKeys;
var S: string;
begin
S := GUIDToString(CLSID_DelphiBand);
with TRegistry.Create do
try
RootKey := HKEY_CLASSES_ROOT;
DeleteKey('CLSID\' + S + '\Implemented Categories\' + VerticalBand);
DeleteKey('CLSID\' + S + '\InProcServer32');
DeleteKey('CLSID\' + S);
Closekey;
finally
Free;
end;
end;
initialization
TDelphiBandFactory.Create(ComServer, TDelphiBand, CLSID_DelphiBand, '', Caption, ciMultiInstance);
end.
注冊組件之后,啟動IE,打開隨書光盤中的LoginForm.html,然后啟動面板程序,執行加載和保存功能,界面示意圖:
最后
實際上面板對象不僅僅可以應用在IE中,外殼的任務條的快捷方式工具條實際上也是面板組件,也可以采用本文提到的類似的技術來實現,除了要填寫的注冊表項內容不同外,其它大同小異,因此這里就不贅述了,有興趣的朋友直接察看MSDN就可以了。
參考文獻:
1、 Peter Larsen寫的IE面板組件例子的代碼。
2、 MSDN。
原文:http://www.codesky.net/article/doc/200801/2008011681208862.htm
《Android高薪之路:Android程序員面試寶典 》http://book.360buy.com/10970314.html
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining
posted on 2010-10-02 21:25 銀河使者 閱讀(2165) 評論(0) 編輯 收藏 所屬分類: delphi