国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Delphi開發(fā)ActiveX控件之一步到位

Delphi開發(fā)ActiveX控件之一步到位

原文:Ray Konopka 翻譯:陳省

 

Delphi ActiveX 框架

 

Delphi ActiveX 框架(DAX)使我們能夠很容易的通過轉(zhuǎn)換向?qū)?/span>Delphi本身的控件(VCL)出發(fā)創(chuàng)建ActiveX,而不需要你具備很多的COM知識(shí),生成的ActiveX可以應(yīng)用在VC、 VB等不同的開發(fā)環(huán)境中,避免重復(fù)開發(fā),實(shí)現(xiàn)真正的代碼重用。

 

創(chuàng)建ActiveX涉及到生成一個(gè)VCLCOM封裝,封裝類繼承于TActiveXControl 實(shí)現(xiàn)了一個(gè)對(duì)Delphi控件的引用參考。DelphiVCL控件要想能夠轉(zhuǎn)換為ActiveX控件,必須是繼承于TWinControl。這是因?yàn)?/span>COM封裝和VCL控件之間的通訊需要一個(gè)窗口句柄,只有TWincontrol的子類才有句柄。

 

封裝類通過屬性和方法向其他的對(duì)象公開了Delphi控件的功能。同時(shí)它也負(fù)責(zé)創(chuàng)建管理和銷毀嵌入的VCL控件。COM封裝類通常還負(fù)責(zé)響應(yīng)控件產(chǎn)生的事件,并提交給ActiveX 控件容器。

 

聽起來好像有點(diǎn)復(fù)雜,幸好Delphi提供了ActiveX控件向?qū)Э梢詷O大的簡(jiǎn)化過程讓我們把一個(gè)最常見的TListBox控件轉(zhuǎn)化成ActiveX。首先選File|New|ActiveX,如下圖。

 

 

然后選擇ActiveX Control項(xiàng),顯示一個(gè)對(duì)話框,第一步是選則VCL的類名,VCL類名下拉框中列出了全部TWinControl的子類(不包括使用RegisterNonActiveX函數(shù)注冊(cè)的控件)從列表我們可以看到TListBox,但你找不到TLable,因?yàn)?/span>TLabel繼承于TGraphicControl,當(dāng)然象那種TTimer的非可視控件更是沒有了。如下圖所示:

 

當(dāng)我們選好了類名,向?qū)?huì)自動(dòng)給其他編輯框添上缺省值。這里我們使用它的缺省值,同時(shí)選中ActiveX Control Options的三個(gè)選項(xiàng),然后點(diǎn)OK

 

ActiveX 控制選項(xiàng)

 

上圖顯示了全部可以選的ActiveX控制選項(xiàng),Include Design-Time License選項(xiàng)表明設(shè)計(jì)時(shí)許可證將被創(chuàng)建,除非用戶有許可證,否則它可以防止控件在設(shè)計(jì)環(huán)境中被非法使用,。如果選擇了這個(gè)選項(xiàng),向?qū)?huì)產(chǎn)生一個(gè)LIC文件,里面包含了許可證信息。用戶必須有這個(gè).LIC文件才能在開發(fā)環(huán)境中使用相應(yīng)的ActiveX控件。Include Version Information選項(xiàng)使你可以在項(xiàng)目中添加象版權(quán)說明、版本號(hào)等版本信息。具體版本信息的設(shè)定可以在創(chuàng)建好項(xiàng)目后,選Project|Options然后切換到Version-Info頁來進(jìn)行。(注意: 盡管版本信息是一個(gè)可選的選項(xiàng),但如果你打算在Visual Basic 4.0及以上中使用Delphi生成的ActiveX控件,你必須選定它)Include About Box選項(xiàng)表明你是否為ActiveX控件創(chuàng)建一個(gè)關(guān)于對(duì)話框。關(guān)于對(duì)話框是一個(gè)獨(dú)立的窗體單元,你可以編輯它來顯示你需要的版本信息或其他信息。關(guān)于信息是通過在開發(fā)環(huán)境中點(diǎn)擊About 屬性來調(diào)用的。

 

生成單元文件

 

一切設(shè)定好后,點(diǎn)OK按鈕。向?qū)紫葎?chuàng)建一個(gè)ActiveX Library 項(xiàng)目。接著創(chuàng)建一個(gè)實(shí)現(xiàn)單元,來實(shí)現(xiàn)原生的Delphi控件的COM封裝。封裝類是TActiveXControl一個(gè)簡(jiǎn)單的子類,然后是類型庫和類型庫接口單元(類型庫實(shí)際上是一個(gè)二進(jìn)制文件里面定義數(shù)據(jù)類型、接口、方法以及ActiveX Library要公開的對(duì)象。類型庫接口單元包含了對(duì)應(yīng)于類型庫中的信息Pascal的聲明)。最后是許可證文件,關(guān)于對(duì)話框和源碼文件。

 

編譯和注冊(cè)ActiveX控制

 

現(xiàn)在我們可以編譯ActiveX Library 項(xiàng)目來生成包含ActiveX控件的OCX文件。我們可以直接調(diào)用Run|Register Sever來注冊(cè)ActiveX Sever。然而在做之前,我建議保存全部的項(xiàng)目文件。如果你沒有先保存項(xiàng)目文件,那么儲(chǔ)存在注冊(cè)表中的路徑就是你當(dāng)前的路徑而不一定是你的項(xiàng)目的真正路徑。

 

注冊(cè)后我們就可以在Visual Basic等程序中使用Delphi生成的ActiveX控件了,如下圖示意:

 

 

ActiveX 轉(zhuǎn)換過程中的問題

 

雖然ListBoxX控件使我們能在Visual Basic中使用TListBox很多功能。但ListBoxX控件并沒有實(shí)現(xiàn)TListBox的全部功能。比如,TListBoxOnDrawItem的事件定義在ListBoxX中是找不到的?;叵胍幌略?/span>Delphi里我們經(jīng)常使用OnDrawItem事件來支持用戶自繪畫功能。沒有了這個(gè)事件,ActiveX版本的ListBox就無法支持這一特性即使Style屬性設(shè)定為lsOwnerDrawFixed

 

要理解為什么這個(gè)事件沒有出現(xiàn)在ActiveX中,我們需要研究一下事件類型,特別是要研究一下傳遞給事件的參數(shù)類型。OnDrawItem聲明為TDrawItemEvent類型,定義如下:

 

TDrawItemEvent = procedure( Control: TWinControl;

                            Index: Integer; Rect: TRect;

                            State: TOwnerDrawState) of object;

 

我們看到OnDrawItem 事件處理函數(shù)接受4個(gè)參數(shù)。其中第三個(gè)參數(shù)阻止了事件出現(xiàn)在ActiveX Control中。因?yàn)?/span>OLE自動(dòng)化不知道如何整理(marshallTRect類型的數(shù)據(jù)。

 

原因在于ActiveX 控制實(shí)際上是小型的OLE自動(dòng)化服務(wù)器。包含 ActiveX控件的ActiveX 容器使用自動(dòng)化來和控件通訊。因此要想使一個(gè)屬性、方法或事件出現(xiàn)在ActiveX版本的控制中,全部參數(shù)和返回類型必須是自動(dòng)化兼容的。表1列出了全部的兼容類型。

 

 

雖然在這個(gè)表中我們沒有列出但ActiveX轉(zhuǎn)換向?qū)н€可以正確處理TColor, TFont, TPicture, and TStrings屬性。Color 屬性可以很容易轉(zhuǎn)換因?yàn)樗鼘?shí)際上就是一個(gè)整數(shù)類型。然而對(duì)于其他屬性類型,Delphi提供了一個(gè)定制的接口來處理對(duì)應(yīng)的Delphi屬性。比如,IStrings 接口提供了處理TStrings屬性的途徑。

 

同時(shí),一個(gè)屬性是自動(dòng)化兼容的并不意味著它就一定會(huì)出現(xiàn)在ActiveX 控件中,向?qū)Р粫?huì)轉(zhuǎn)化對(duì)ActiveX無意義的屬性、方法或事件。下列屬性就沒有被轉(zhuǎn)化,比如:Height, HelpContext, Hint, Left, Name, ParentFont, ParentShowHint, PopupMenu, ShowHint, TabOrder, Tag, Top, and Width等。

 

此外,有兩種特殊類型的屬性向?qū)б膊粫?huì)轉(zhuǎn)化。對(duì)象引用和數(shù)據(jù)明了屬性。對(duì)象引用(就是指Delphi的某個(gè)屬性對(duì)應(yīng)于一個(gè)對(duì)象,比如TTableDatasource實(shí)際上是引用了另外一個(gè)對(duì)象TDataSource)在Delphi里是通過指針來實(shí)現(xiàn)的因此是自動(dòng)化不兼容的。此外, ActiveX本身也沒有提供一個(gè)標(biāo)準(zhǔn)的方式來使一個(gè)控件同容器中的其他控件相關(guān)聯(lián)。而數(shù)據(jù)明了屬性DataSourceDataField沒有被映射到ActiveX控件中去是因?yàn)?/span>Delphi實(shí)現(xiàn)的數(shù)據(jù)明了采用了完全不同于ActiveX 的機(jī)制。當(dāng)然如果非常想利用Delphi中好用的數(shù)據(jù)庫控件,這也是可以的,但需要一些額外的工作,這已經(jīng)超出了本文的范圍,將不在這里介紹。必須指出的是ActiveX的數(shù)據(jù)控件和Delphi的數(shù)據(jù)控件是不一樣的。這也就是為什么沒有一個(gè)Delphi的數(shù)據(jù)明了控件出現(xiàn)在ActiveX轉(zhuǎn)換向?qū)У念惷斜碇械木壒省?/span>

 

正確的轉(zhuǎn)換的關(guān)鍵

 

到目前為止ListBoxX其他特性都沒問題,我們也可以把Style變成lsOwnerDrawFixed, 但是沒有OnDrawItem事件我們無法改變它的外觀顯示。讓我們?cè)囈环N不同的方法,這就是定義一個(gè)自動(dòng)化兼容的接口來實(shí)現(xiàn)自繪畫的外觀(Owner-Draw.例如我們可以創(chuàng)建一個(gè)新的事件OnColorItem使我們能改變每一個(gè)列表項(xiàng)的顏色。

 

添加新事件

 

添加新的事件到ActiveX中需要修改類型庫中的信息,可以有兩種方法:通過選擇 Edit|Add To Interface 菜單或用內(nèi)置的類型庫編輯器都可以,Edit|Add To Interface 菜單只有當(dāng)當(dāng)前文件為實(shí)現(xiàn)單元時(shí)才能使用。如下圖所示:

 

 

上圖顯示了OnColorItem 是如何加入到IListBoxXEvents 接口中的。定義一個(gè)ActiveX接口的新事件同Delphi中有點(diǎn)不同。不象Delphi中那樣給事件聲明一個(gè)屬性類比如TNotifyEvent, 你必須寫一個(gè)將會(huì)傳遞給事件處理函數(shù)的帶參數(shù)的過程。類似于寫一個(gè)控件中的事件分配方法。OnColorItem事件定義如下:

 

procedure OnColorItem(Index: Integer; var Color: Integer );

 

點(diǎn)OK按鈕,Delphi 就把這個(gè)聲明加入了類型庫。這使得我們可以給OnColorItem事件寫處理函數(shù)了。但是在這之前, 我們還必須實(shí)現(xiàn)產(chǎn)生事件的代碼,這有點(diǎn)類似于在Delphi控件中定義新的事件。生成事件屬性和事件分配方法僅僅是一部分工作。我們還必須在合適的時(shí)間調(diào)用事件分配方法來產(chǎn)生事件。最好的產(chǎn)生OnColorItem事件的位置就是在Delphi控件的OnDrawItem事件中,實(shí)現(xiàn)的方法見源碼清單1。

 

TListBoxX 封裝類定義了一個(gè)事件處理函數(shù)DrawItemEvent 來對(duì)嵌入的ListBoxOnDrawIem事件來響應(yīng),DrawItemEvent函數(shù)在InitializeControl方法中進(jìn)行初始化。同時(shí)DrawItemEvent函數(shù)負(fù)責(zé)產(chǎn)生OnColorItem事件。為了產(chǎn)生事件,要使用FEvents接口來激發(fā)OnColorItem事件過程。Index參數(shù)來自于DrawItemEvent參數(shù)列表,Color參數(shù)是在DrawItemEvent里定義的。當(dāng)OnColorItem 事件返回時(shí), ItemColor 變量將包括缺省的顏色或用戶定義的顏色。然后ItemColor變量就被用來畫列表項(xiàng)。如下圖所示:

 

上圖顯示了ListBoxX控件在VB中的運(yùn)行狀況。雖然ActiveX不可能象在Delphi可以隨意引用Canvas來畫圖,但是這個(gè)例子證明了利用ActiveX控件的靈活性,我們還是可以作一些有趣的效果。

 

正如我們?cè)谏厦孢@個(gè)例子中看到的,實(shí)際上把Delphi控件轉(zhuǎn)化為ActiveX控件并不是很容易,這是由于我們轉(zhuǎn)換的是一個(gè)現(xiàn)成的Delphi控件,特別是這個(gè)控件使用了某些VCL的高級(jí)特性。從這個(gè)方面來說,Active控制框架不如VCL靈活,然而ActiveX是一個(gè)公認(rèn)的標(biāo)準(zhǔn),可以在除了Delphi外的其他環(huán)境中使用,犧牲靈活性意味著獲得了廣泛性。

 

結(jié)論

 

如果你想從頭開始創(chuàng)建一個(gè)ActiveX控件,首先你的控件必須從TWincontrol開始繼承,如果想要提供自繪畫的功能,必須從TCustomControl開始。另外,應(yīng)該使用自動(dòng)化兼容的數(shù)據(jù)類型來定義屬性、方法、參數(shù)。如果你想轉(zhuǎn)換一個(gè)已有的VCL控件變成ActiveX,注意一定要改變參數(shù)類型,否則方法,屬性等等是不會(huì)被轉(zhuǎn)換的。

 

源碼清單1 - ListBoxImpl.pas

 

unit ListBoxImpl;

 

interface

 

uses

  Windows, ActiveX, Classes, Controls, Graphics, Menus, Forms,

  StdCtrls, ComServ, StdVCL, AXCtrls, DelphiByDesignXLib_TLB;

 

type

  TListBoxX = class(TActiveXControl, IListBoxX)

  private

    { Private declarations }

    FDelphiControl: TListBox;

    FEvents: IListBoxXEvents;

    procedure ClickEvent(Sender: TObject);

    procedure DblClickEvent(Sender: TObject);

    procedure KeyPressEvent(Sender: TObject; var Key: Char);

 

    // Add a custom event handler for the OnDrawItem event

    procedure DrawItemEvent( Control: TWinControl; Index: Integer;

                             Rect: TRect; State: TOwnerDrawState );

  protected

    { Protected declarations }

    procedure InitializeControl; override;

    procedure EventSinkChanged(const EventSink: IUnknown); override;

    procedure DefinePropertyPages(

      DefinePropertyPage: TDefinePropertyPage); override;

    function Get_BorderStyle: TxBorderStyle; safecall;

    function Get_Color: TColor; safecall;

    function Get_Columns: Integer; safecall;

    function Get_Ctl3D: WordBool; safecall;

    function Get_Cursor: Smallint; safecall;

    function Get_DragCursor: Smallint; safecall;

    function Get_DragMode: TxDragMode; safecall;

    function Get_Enabled: WordBool; safecall;

    function Get_ExtendedSelect: WordBool; safecall;

    function Get_Font: Font; safecall;

    function Get_ImeMode: TxImeMode; safecall;

    function Get_ImeName: WideString; safecall;

    function Get_IntegralHeight: WordBool; safecall;

    function Get_ItemHeight: Integer; safecall;

    function Get_ItemIndex: Integer; safecall;

    function Get_Items: IStrings; safecall;

    function Get_MultiSelect: WordBool; safecall;

    function Get_ParentColor: WordBool; safecall;

    function Get_ParentCtl3D: WordBool; safecall;

    function Get_SelCount: Integer; safecall;

    function Get_Sorted: WordBool; safecall;

    function Get_Style: TxListBoxStyle; safecall;

    function Get_TabWidth: Integer; safecall;

    function Get_TopIndex: Integer; safecall;

    function Get_Visible: WordBool; safecall;

    procedure AboutBox; safecall;

    procedure Clear; safecall;

    procedure Set_BorderStyle(Value: TxBorderStyle); safecall;

    procedure Set_Color(Value: TColor); safecall;

    procedure Set_Columns(Value: Integer); safecall;

    procedure Set_Ctl3D(Value: WordBool); safecall;

    procedure Set_Cursor(Value: Smallint); safecall;

    procedure Set_DragCursor(Value: Smallint); safecall;

    procedure Set_DragMode(Value: TxDragMode); safecall;

    procedure Set_Enabled(Value: WordBool); safecall;

    procedure Set_ExtendedSelect(Value: WordBool); safecall;

    procedure Set_Font(const Value: Font); safecall;

    procedure Set_ImeMode(Value: TxImeMode); safecall;

    procedure Set_ImeName(const Value: WideString); safecall;

    procedure Set_IntegralHeight(Value: WordBool); safecall;

    procedure Set_ItemHeight(Value: Integer); safecall;

    procedure Set_ItemIndex(Value: Integer); safecall;

    procedure Set_Items(const Value: IStrings); safecall;

    procedure Set_MultiSelect(Value: WordBool); safecall;

    procedure Set_ParentColor(Value: WordBool); safecall;

    procedure Set_ParentCtl3D(Value: WordBool); safecall;

    procedure Set_Sorted(Value: WordBool); safecall;

    procedure Set_Style(Value: TxListBoxStyle); safecall;

    procedure Set_TabWidth(Value: Integer); safecall;

    procedure Set_TopIndex(Value: Integer); safecall;

    procedure Set_Visible(Value: WordBool); safecall;

  end;

 

implementation

 

uses AboutListBox;

 

{ TListBoxX }

 

procedure TListBoxX.InitializeControl;

begin

  FDelphiControl := Control as TListBox;

  FDelphiControl.OnClick := ClickEvent;

  FDelphiControl.OnDblClick := DblClickEvent;

  FDelphiControl.OnKeyPress := KeyPressEvent;

 

  //添加一個(gè)定制的事件來處理OnDrawItem事件

  FDelphiControl.OnDrawItem := DrawItemEvent;

end;

 

procedure TListBoxX.EventSinkChanged(const EventSink: IUnknown);

begin

  FEvents := EventSink as IListBoxXEvents;

end;

 

function TListBoxX.Get_Enabled: WordBool;

begin

  Result := FDelphiControl.Enabled;

end;

 

procedure TListBoxX.Set_Enabled(Value: WordBool);

begin

  FDelphiControl.Enabled := Value;

end;

 

procedure TListBoxX.DrawItemEvent( Control: TWinControl;

  Index: Integer; Rect: TRect; State: TOwnerDrawState );

var

  ItemColor: Integer;

begin

  ItemColor := Integer(FDelphiControl.Font.Color);

 

  //產(chǎn)生OnColorItem ActiveX事件

  if FEvents <> nil then

    FEvents.OnColorItem( Index, ItemColor );

 

  //ItemColor畫列表項(xiàng)

  with FDelphiControl do

  begin

    if not ( odSelected in State ) then

      Canvas.Font.Color := ItemColor;

    Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top, Items[Index]);

    Canvas.Font.Color := FDelphiControl.Font.Color;

  end;

end;

 

initialization

  TActiveXControlFactory.Create(

    ComServer,

    TListBoxX,

    TListBox,

    Class_ListBoxX,

    1,

    '{B19A64E4-644D-11D1-AE4B-444553540000}',

    0);

end.

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
奇技淫巧之Delphi和JavaScript互通 | 武稀松(wr960204)的博客
如何在程序中執(zhí)行動(dòng)態(tài)生成的Delphi代碼
Raymond的狗屋
ActiveX控件在Delphi中的使用方法
delphi之如何快速開發(fā)原生ActiveX控件
Delphi WebBrowser始終在當(dāng)前窗口打開新網(wǎng)頁
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服