ActiveX控件的使用和創(chuàng)建課件_第1頁
ActiveX控件的使用和創(chuàng)建課件_第2頁
ActiveX控件的使用和創(chuàng)建課件_第3頁
ActiveX控件的使用和創(chuàng)建課件_第4頁
ActiveX控件的使用和創(chuàng)建課件_第5頁
已閱讀5頁,還剩283頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第十二章ActiveX控件的使用和創(chuàng)建

1a第十二章ActiveX控件的使用和創(chuàng)建1a近年來,軟件產(chǎn)業(yè)已經(jīng)發(fā)生了一場革命性的變化。軟件的制作和打包方式已經(jīng)不再是所有的應(yīng)用程序都必須從源代碼編譯鏈接成一個完整的、很大的可執(zhí)行代碼文件,而是大多數(shù)應(yīng)用程序都可以由一些較小的構(gòu)件組成。這些小的構(gòu)件,通常稱為組件。這些組件可以用多種不同的程序語言創(chuàng)建,且可以具有多種不同的的形式。最為流行的組件之一便是ActiveX控件。組件不但可以作為最終軟件產(chǎn)品提供給其他程序設(shè)計人員,而且在大型軟件開發(fā)中,使用組件也是組織不同分工的程序設(shè)計人員共同完成整個軟件設(shè)計開發(fā)的重要策略和方法。本章的學(xué)習(xí)目的是:2a近年來,軟件產(chǎn)業(yè)已經(jīng)發(fā)生了一場革命性的變化。軟件的制掌握如何使用ActiveX控件,以便在軟件開發(fā)中使用第三方提供的產(chǎn)品化組件和如何創(chuàng)建自己的ActiveX控件,以便開發(fā)產(chǎn)品化組件,提供給其他程序設(shè)計者。本章的主要內(nèi)容包括:·什么是ActiveX控件以及它們是如何工作的。·如何在項(xiàng)目工作區(qū)中添加ActiveX控件?!と绾卧赩isualC++應(yīng)用程序中使用ActiveX控件。·如何調(diào)用與ActiveX控件相關(guān)聯(lián)的各種方法?!と绾翁幚碛葾ctiveX控件激活的事件?!と绾斡肰isualC++AppWizard

建立ActiveX控件項(xiàng)目。·如何用ClassWizard向ActiveX控件添加屬性和方法。·如何用VisualC++提供的工具測試自己的ActiveX

控件。3a掌握如何使用ActiveX控件,以便在軟件開發(fā)中使用第三12.1什么是ActiveX控件在介紹ActiveX控件之前有必要了解另外兩個編程技術(shù)概念:·OLE(ObjectLinkedandEmbeded)對象連接嵌入是Microsoft基于對象的技術(shù)。該技術(shù)用于跨越進(jìn)程和機(jī)器邊界的數(shù)據(jù)信息和操作方法的共享。不過最初的OLE僅僅允許把不同的應(yīng)用程序創(chuàng)建的文檔組合成一個單一文檔?!OM(ComponentObjectModel)組件對象模型是遵循OLE基本技術(shù)的對象模型。一個COM對象是一個對象定義的實(shí)例,該對象定義指定了該對象的數(shù)據(jù)和一個或多個作用于該對象的接口執(zhí)行方法。客戶程序與COM對象之間的相互作用只能通過COM對象的接口實(shí)現(xiàn)。4a12.1什么是ActiveX控件4aActiveX控件就是一組封裝在COM對象中的功能模塊。這個COM對象是獨(dú)立的,但并不能單獨(dú)運(yùn)行,而只能在ActiveX容器中運(yùn)行,如VisualC++或VisualBasic應(yīng)用程序,這一點(diǎn)很像在組合設(shè)備中插入具有特定功能的組件,例如在組合式音響中,插入一個DVD播放組件。5aActiveX控件就是一組封裝在COM對象中的12.1.1ActiveX和IDispatch接口每個COM對象都有一些標(biāo)準(zhǔn)接口,例如,IUnknown

接口,該接口用來詢問是否找到了該組件所支持的其他接口。每個接口支持一組特定的功能,例如,可以用一個接口來處理控件的可視外觀,一個接口來控制控件外觀如何與插入該控件的應(yīng)用程序進(jìn)行交互,一個接口來觸發(fā)插入該控件應(yīng)用程序中的事件,等等。

ActiveX技術(shù)是建立在微軟的COM技術(shù)之上,并使用COM的接口和交互模型使ActiveX控件與插入控件的應(yīng)用程序進(jìn)行完全無縫的集成。COM技術(shù)奠定了構(gòu)建ActiveX

對象的方式及設(shè)計ActiveX接口的方法。ActiveX

技術(shù)定義了建立于COM

之上的層面、各種對象應(yīng)該支持什么樣的接口以及如何與不同類型的對象交互。6a12.1.1ActiveX和IDispatch接口6

ActiveX控件的關(guān)鍵技術(shù)之一是自動。所謂“自動”可描述為:·將一個應(yīng)用程序中嵌入另一個應(yīng)用程序?!ぎ?dāng)用戶的操作涉及到被嵌入者的功能時,激活被嵌入者,并控制被嵌入者的用戶接口或文檔部分,同時進(jìn)行被嵌入者自身的更改?!ぎ?dāng)用戶將操作轉(zhuǎn)移到應(yīng)用程序中非嵌入程序的控制部分時,被嵌入者自行關(guān)閉(例如在word應(yīng)用程序中自動嵌入Excel電子表格應(yīng)用程序)。實(shí)現(xiàn)自動工作的關(guān)鍵之一是特殊(調(diào)度)接口

IDispatch。7aActiveX控件的關(guān)鍵技術(shù)之一是自動。所謂“自

ActiveX控件可以提供的所有方法有各自的唯一標(biāo)識值DISPID。這些標(biāo)識值被存放在用來查找特定方法的標(biāo)識列表中。IDispatch接口由一個指示方法的標(biāo)識列表和IDispatch接口提供的方法組成。當(dāng)獲取一個特定方法的DISPID之后,就可以將該方法的DISPID作為參數(shù),通過調(diào)用IDispatch接口的方法Invoke

來實(shí)現(xiàn)調(diào)用DISPID所標(biāo)識的指定方法。下圖示意性描述了IDispatch接口如何使用Invoke方法來運(yùn)行ActiveX

控件提供的方法,實(shí)現(xiàn)的ActiveX

控件的自動化。8aActiveX控件可以提供的所有方法有各自的唯一DISPID1DISPID2DISPID3DISPID4DISPIDnActiveX對象IDispatchvtable客戶程序IDispatch::Invoke(DISPID)Invoke(){switch(DISPID3){case1:MethodX();case2:MethodY();case3:MethodZ();…}調(diào)度接口9aDISPID1ActiveX對象IDispatch客戶程序12.1.2ActiveX容器和服務(wù)器任何可以嵌入另一對象的ActiveX對象都是ActiveX

服務(wù)器,而無論它是一個完整的應(yīng)用程序或僅僅是一個ActiveX控件。任何可以包含其他被嵌入ActiveX服務(wù)器的ActiveX對象都是ActiveX容器。注意,不要把術(shù)語容器和服務(wù)器與上圖中的客戶程序混淆。客戶程序是指調(diào)用其嵌入對象的IDispatch接口的對象。容器和服務(wù)器都相互調(diào)用對方的IDispatch接口,因此它們相互成為對方的客戶程序。10a12.1.2ActiveX容器和服務(wù)器10a這兩種類型的ActiveX對象并不互相排斥。ActiveX服務(wù)器同時也可以是ActiveX容器,例如,微軟的InternetExplorer

Web

瀏覽器中InternetExplorer是一個可以在ActiveX容器外殼中運(yùn)行的ActiveX服務(wù)器。可以運(yùn)行該服務(wù)器的ActiveX容器外殼還可以包含Word、Excel、Powerpoint

等其他應(yīng)用程序,同時這些應(yīng)用程序還可以作為其他應(yīng)用程序的ActiveX

服務(wù)器。

ActiveX控件是ActiveX

服務(wù)器的一個特例,即該

服務(wù)器不能自身運(yùn)行,必須被嵌入到ActiveX容器中。如果在AppWizard所創(chuàng)建的MFC應(yīng)用程序項(xiàng)目中,設(shè)置了使用ActiveX組件選項(xiàng),則該項(xiàng)目所創(chuàng)建的應(yīng)用程序就自動成為一個ActiveX容器。11a這兩種類型的ActiveX對象并不互相排斥。Ac

ActiveX容器和ActiveX控件之間的大多數(shù)交互操作是通過三個IDispatch接口完成(如下圖所示)。這些IDispatch接口中的一個位于控件中,通過該接口,容器可以調(diào)用控件的各種方法,為容器的功能提供服務(wù)。

容器也為控件提供兩個IDispatch接口。其中一個接口用于控件在容器中觸發(fā)事件。另一個接口用于容器為控件設(shè)置屬性,也就是說ActiveX控件的大部分屬性實(shí)際上由是容器提供,而由控件實(shí)現(xiàn)的。當(dāng)設(shè)置屬性時,容器調(diào)用控件中一個方法,以便通知控件從容器中讀取所提供的屬性。VisualC++創(chuàng)建了一系列關(guān)于ActiveX控件接口的C++類,用戶只與這些C++類“暴露”給用戶的方法交互,而不需要直接調(diào)用控件的IDispatch接口,所以上述活動中的大部分對用戶來說是“透明”的。12aActiveX容器和ActiveX控件之間的大ActiveX容器ActiveX控件IDispatch(事件)IDispatch(屬性)IDispatch13aActiveX容器ActiveX控件IDispatch(事件12.2在應(yīng)用程序項(xiàng)目中添加和使用ActiveX控件使用VisualC++使得在應(yīng)用程序項(xiàng)目添加和使用ActiveX控件變得十分方便。下面通過實(shí)例詳細(xì)講述如何創(chuàng)建一個可以包含ActiveX控件的應(yīng)用程序項(xiàng)目;如何為這個項(xiàng)目添加ActiveX控件和如何在應(yīng)用程序中使用所添加的ActiveX控件。14a12.2在應(yīng)用程序項(xiàng)目中添加和使用ActiveX控件112.2.1創(chuàng)建一個可以包含ActiveX控件的應(yīng)用程序1創(chuàng)建一個MFC應(yīng)用程序

項(xiàng)目,命名為“ActiveX”。2選擇項(xiàng)目類型為DialogBased,并在創(chuàng)建過程中注意選擇項(xiàng)目具有ActiveXControls支持狀態(tài),其他均可取默認(rèn)選擇。3刪除缺省對話框模板IDD_ACTIVEX_DIALOG中的所有缺省控件,添加一個命令按鈕:標(biāo)識為IDC_EXIT,標(biāo)題為E&XIT。4在缺省創(chuàng)建的CActiveXDlg類中,為新添加命令按鈕IDC_EXIT

的BN_CLICKED通知消息建立消息映射

ON_BN_CLICKED(IDC_EXIT,OnExit)和定義消息處理函數(shù)OnExit的原型和定義

afx_msgvoidOnExit();

voidCActiveXDlg::OnExit(){OnOK();}15a12.2.1創(chuàng)建一個可以包含ActiveX控件的應(yīng)用程12.2.2注冊ActiveX控件在給應(yīng)用程序項(xiàng)目添加ActiveX控件之前,必須在系統(tǒng)中注冊控件。在系統(tǒng)中注冊ActiveX控件的方法有兩種。一種方法是運(yùn)行ActiveX控件的安裝程序,進(jìn)行自動注冊。另一種方法是手工注冊ActiveX控件。手工注冊的步驟如下:1進(jìn)入DOS控制臺界面。2將當(dāng)前目錄改變到ActiveX控件文件所在的目錄中,例如:

Windows\system。16a12.2.2注冊ActiveX控件16a3執(zhí)行系統(tǒng)命令regsvr32,并指定ActiveX控件名為該命令的參數(shù)。例如要注冊一個文件名為MYCTL.OCX的ActiveX控件,假如該控件文件MYCTL.OCX在Windows\system目錄中,則可執(zhí)行如下命令:

C:\WINDOWS>cdsystem

C:\WINDOWS\SYSTEM>regsvr32myctl.ocx17a3執(zhí)行系統(tǒng)命令regsvr32,并指定ActiveX注意:·手工注冊可能會導(dǎo)致所注冊的控件缺少某些信息,從而在開發(fā)中無法使用,所以建議使用控件所帶的安裝程序?!と绻褂玫腁ctiveX控件在系統(tǒng)安裝時已經(jīng)被缺省注冊了,則不需要使用上述方法進(jìn)行控件的注冊。本例中要添加的控件就是這類ActiveX控件。

ActiveX控件一旦在系統(tǒng)中注冊成功,就可以將它添加到應(yīng)用程序項(xiàng)目中。在VisualC++6.0中注冊和添加ActiveX控件的步驟如下:18a注意:18a1選擇Project->AddTo

Project->ComponentsandControls。2在彈出的“ComponentsandControlsGallery”對話框中,選擇“RegistedActiveXControls”文件夾:19a1選擇Project->AddToProject->C3在該文件夾中,查找并選中要添加的已注冊ActiveX控件,本例中選擇MicrosoftFlexGridControlversion6.0控件,雙擊被選中控件選項(xiàng),或按《Insert》按鈕。20a3在該文件夾中,查找并選中要添加的已注冊ActiveX控4在提示是否確實(shí)要添加該控件的對話框中,按《OK》按鈕。5在“ConfirmClasses”對話框中,單擊《OK》按鈕添加控件所包含的全部或部分C++類:21a4在提示是否確實(shí)要添加該控件的對話框中,按《OK》按鈕。26在“ComponentsandControlGallery”對話框中單擊《Close》按鈕完成為項(xiàng)目添加控件的工作。7控件FlexGird已經(jīng)被添加到資源編輯器的“ControlPalette”上:22a6在“ComponentsandControlGa8查看工作區(qū)的ClassView,發(fā)現(xiàn)項(xiàng)目中已自動增加了與FlexGird控件相關(guān)的類:

CMSFlexGrid、COleFont、CRowCursor和CPicture,每個類中都提供了相應(yīng)的方法。23a8查看工作區(qū)的ClassView,發(fā)現(xiàn)項(xiàng)目中已自動增加在VisualC++.NET中注冊和添加ActiveX控件的步驟如下:1在Toolbox中,單擊鼠標(biāo)右鍵彈出的環(huán)境菜單中選擇菜單項(xiàng)“ChooseItems…”:24a在VisualC++.NET中注冊和添加Activ2在彈出的屬性表《ChooseToolboxItems》中,選擇屬性頁“COM

Components”,在該屬性頁中選擇所需的ActiveX控件“FlexGird” 后,按OK

按鈕。25a2在彈出的屬性表《ChooseToolboxItems3添加了ActiveX控件“FlexGird”后的Toolbox如下:注意,經(jīng)過上述操作后,并不會在項(xiàng)目中增加封裝“FlexGird”控件的類CMsfgrid(相應(yīng)的定義文件和實(shí)現(xiàn)文件)。只有將控件從ToolBox中添加到對話框模板中,控件的類CMsfgrid(相應(yīng)的定義文件和實(shí)現(xiàn)文件)才會被自動添加到項(xiàng)目中。26a3添加了ActiveX控件“FlexGird”后的12.2.3在對話框模板中添加ActiveX控件

ActiveX控件添加到項(xiàng)目中之后,便可以像使用其他標(biāo)準(zhǔn)控件一樣,把它添加對話框模板中。本例中所添加的ActiveX控件FlexGird的主要屬性設(shè)置如下:控件名屬性設(shè)置值FlexGirdIDIDC_MSFGRIDRows20Cols4MergeCellsRestrictAllFormatString<Region|<Product|<Employee|<Sales27a12.2.3在對話框模板中添加ActiveX控件控件名在完成對控件所有屬性的設(shè)置之后,需要為該控件添加一個數(shù)值類對象m_ctrlFGrid,以便能和代碼中的控件進(jìn)行交互。所添加的代碼如下:classCActiveXDlg:publicCDialog{ …public:

CActiveXDlg(CWnd*pParent=NULL); //standardconstructor … enum{IDD=IDD_ACTIVEX_DIALOG};

CMSFlexGrid m_ctrlFGrid; …};28a在完成對控件所有屬性的設(shè)置之后,需要為該控件添加一個數(shù)28a12.2.4在應(yīng)用程序中使用ActiveX控件與ActiveX控件進(jìn)行交互本例中將使用添加的FlexGrid控件生成一個產(chǎn)品銷售數(shù)字統(tǒng)計表,其中包括4個銷售人員在5個銷售區(qū)的銷售情況。要求能夠在屏幕上滾動顯示數(shù)據(jù),這些數(shù)據(jù)應(yīng)按能區(qū)域或產(chǎn)品種類分類,以比較各個銷售人員在每種產(chǎn)品上的銷售業(yè)績。為此,首先調(diào)用FlexGrid控件的方法SetTextArray將要處理、顯示的數(shù)據(jù)存入到控件的數(shù)組中,并將數(shù)組中數(shù)據(jù)將被載入表格的相應(yīng)單元格中。調(diào)用FlexGrid控件的內(nèi)置排序方法SetSort,使表格按升序排列。為了實(shí)現(xiàn)這些操作需要為CActiveXDlg類添加如下成員函數(shù)定義:29a12.2.4在應(yīng)用程序中使用ActiveX控件29a1把數(shù)據(jù)載入控件添加一個私有成員函數(shù)將數(shù)據(jù)裝載到FlexGrid控件中,該函數(shù)命名為LoadData,函數(shù)類型為void,其定義代碼如下:voidCActiveXDlg::LoadData(){intliCount; //Thegridrowcount

CStringlsAmount; //Thesalesamount

//Initializetherandomnumbergenerator

srand((unsigned)time(NULL));

//CreateArrayinthecontrolfor(liCount=m_ctrlFGrid.GetFixedRows(); liCount<m_ctrlFGrid.GetRows();liCount++)30a1把數(shù)據(jù)載入控件30a{

//Generatethefirstcolumn(region)valuesm_ctrlFGrid.SetTextArray(GenID(liCount,0),RandomStringValue(0));

//Generatathesecondcolumn(product)valuesm_ctrlFGrid.SetTextArray(GenID(liCount,1),RandomStringValue(1));//Generatethethirdcolumn(employee)valuesm_ctrlFGrid.SetTextArray(GenID(liCount,2),RandomStringValue(2));

//GeneratathesalesamountvalueslsAmount.Format("%5d.00",rand());

//Populatethefourthcolumnm_ctrlFGrid.SetTextArray(GenID(liCount,3),lsAmount);}31a{31a//MergetheCommonsubsequentrowsinthesecolumns

m_ctrlFGrid.SetMergeCol(0,TRUE);m_ctrlFGrid.SetMergeCol(1,TRUE);m_ctrlFGrid.SetMergeCol(2,TRUE);

DoSort(); //Sortthegrid}32a//MergetheCommonsubseq代碼分析:·函數(shù)循環(huán)處理控件中所有行,給每個單元格中放入數(shù)據(jù)。通過調(diào)用控件的GetRows方法可獲得控件中總行數(shù),而調(diào)用控件的GetFixedRows方法可獲得有標(biāo)題行的編號。通過調(diào)用控件的SetTextArray方法可把數(shù)據(jù)添加到控件單元格中,調(diào)用該方法的兩個參數(shù)是由函數(shù)GetID獲取單元格的ID和使用函數(shù)RandomStringValue產(chǎn)生要放入控件單元格的數(shù)據(jù)。這兩個函數(shù)都是CActiveXDlg類的新增成員函數(shù)。·把數(shù)據(jù)放入表格單元格后,調(diào)用控件的方法SetMergeCol,用于通知控件,如果相鄰行有著同樣的值,可以把前三列的單元格合并?!ぷ詈?,使用另一個CActiveXDlg類的新增函數(shù)來完成單元格數(shù)據(jù)的排序。33a代碼分析:33a2計算單元格ID控件FlexGrid

的單元格按從左至右、從上至下編號。計算單元格ID的函數(shù)GetID

的訪問權(quán)限為private,其定義代碼如下:intCActiveXDlg::GenID(intm_iRow,intm_iCol){intliCols=m_ctrlFGrid.GetCols(); //Getthenumberofcolumnreturn(m_iCol+liCols*m_iRow); //GenerateanID}3生成隨機(jī)數(shù)據(jù)實(shí)現(xiàn)這一功能的函數(shù)RandomStringValue將根據(jù)參數(shù)——單元格的當(dāng)前列號分別為第一列產(chǎn)生隨機(jī)的銷售區(qū)域名,為第二列產(chǎn)生隨機(jī)的銷售產(chǎn)品名,為第三列產(chǎn)生隨機(jī)的銷售人員名。該函數(shù)的訪問權(quán)限也為private,其定義代碼如下:34a2計算單元格ID34aCStringCActiveXDlg::RandomStringValue(intm_iColumn){

CStringlsStr; //ThereturnstringintliCase; //ArandomvalueID//Whichcolumnarewegeneratingforswitch(m_iColumn){case0: //Thefirstcolumn(region)liCase=(rand()%5);//Generatearandomvaluebetween0and4

//Whatvaluewasgenerated?switch(liCase){case0: //0-Northwestregion lsStr="Northwest"; break;35aCStringCActiveXDlg::RandomStrcase1: //1-Southwestregion lsStr="Southwest"; break;case2: //2-Midwestregion lsStr="Midwest"; break;case3: //3-Northeastregion lsStr="Northeast"; break;case4: //4-Southeastregion lsStr="Southeast"; break;}break;case1: //Thesecondcolumn(product)liCase=(rand()%5);//Generatearandomvaluebetween0and4//Whatvaluewasgenerated?36acase1: //1-Southweswitch(liCase){ case0: //0-Dodads lsStr="Dodads"; break;case1: //1-Thingamajigs lsStr="Thingamajigs"; break;case2: //2-Whatchamacallits lsStr="Whatchamacallits"; break;case3: //3-RoundTuits lsStr="RoundTuits"; break;default: //4-Widgets lsStr="Widgets";}break;37aswitch(liCase)37acase2: //Thethirdcolumn(employee)liCase=(rand()%4);//generatearandomvaluebetween0and3//Whatvaluewasgenerated?switch(liCase){case0: //0-Dore lsStr="Dore"; break;case1: //1-Harvey lsStr="Harvey"; break;case2: //2-Pogo lsStr="Pogo"; break;default: //3-Nyra lsStr="Nyra"; }38acase2: //Thethirdcolumbreak;}

//ReturnthegeneratedstringreturnlsStr;}39abreak;39a4為控件中顯示數(shù)據(jù)排序?yàn)镃ActivexDlg類定義私有成員函數(shù)DoSort用以調(diào)用FlexGrid控件的排序函數(shù)SetSort實(shí)現(xiàn)對控件的排序。排序的方式是升序還是降序取決于調(diào)用SetSort的參數(shù)。其定義代碼如下:voidCActiveXDlg::DoSort(){//Setthecurrentcolumntocolumn0m_ctrlFGrid.SetCol(0);

//Setthecolumnselectiontoallcolumnsm_ctrlFGrid.SetColSel((m_ctrlFGrid.GetCols()-1));

//GenericAscendingsort

m_ctrlFGrid.SetSort(1);}40a4為控件中顯示數(shù)據(jù)排序40a5修改CActiveXDlg::OnInitDialog在此函數(shù)中加入對函數(shù)LoadData的調(diào)用,實(shí)現(xiàn)對FlexGrid控件的初始化。BOOLCActiveXDlg::OnInitDialog(){

CDialog::OnInitDialog();…

LoadData(); //LoaddataintotheGridcontrol…returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}6編譯運(yùn)行“ActiveX”41a5修改CActiveXDlg::OnInitDialog響應(yīng)控件事件運(yùn)行上面的程序,你會發(fā)現(xiàn)FlexGrid控件對任何輸入事件都沒有響應(yīng)。這是因?yàn)殡m然ActiveX控件為VisualC++應(yīng)用程序提供了多種事件,但大多數(shù)ActiveX

控件并沒有與可用事件相關(guān)聯(lián)的缺省功能,而必須告訴控件在每個事件發(fā)生時做些什么。在本例中,我們將添加兩個控件事件的響應(yīng),使用戶可以按住鼠標(biāo)左或右鍵選中列標(biāo)題并將它拖動到另一個位置,從而重新安排列的順序。實(shí)現(xiàn)此功能,必須捕獲兩個控件事件:鼠標(biāo)左或右鍵被按下和被釋放?!ぴ谑髽?biāo)按鈕按下事件中:需要檢查用戶單擊了列標(biāo)題,如果是,應(yīng)捕獲所選中的列。42a響應(yīng)控件事件42a·在鼠標(biāo)按鈕釋放事件中:需要將所捕獲的列移動到鼠標(biāo)被釋放時所處的列位置。要完成這項(xiàng)功能,還需要在CActiveXDlg

類中增加一個私有數(shù)據(jù)成員,用于保存所捕獲列的列號,所添加的代碼如下:…

private:

intm_iMouseCol;1捕獲所選列·使用ClassWizard為IDC_MSFGRID控件對象的MouseDown事件消息添加響應(yīng)函數(shù);·編寫函數(shù)代碼如下:43a·在鼠標(biāo)按鈕釋放事件中:需要將所捕獲的列移動到鼠標(biāo)被釋43avoidCActiveXDlg::OnMouseDownMsfgrid(shortButton,shortShift, longx,longy){//TODO:Addyourcontrolnotificationhandlercodehere//Didtheuserclickonadatarowandnottheheaderrow?if(m_ctrlFGrid.GetMouseRow()!=0){

//Ifso,thenzerooutthecolumnvariableandexitm_iMouseCol=0;return;}

//SavethecolumnClickedonm_iMouseCol=

m_ctrlFGrid.GetMouseCol();}44avoidCActiveXDlg::OnMouseDownM2把列移動到鼠標(biāo)被釋放處·使用ClassWizard為IDC_MSFGRID

控件對象的MouseUp事件消息添加響應(yīng)函數(shù);·編寫函數(shù)代碼如下:voidCActiveXDlg::OnMouseUpMsfgrid(shortButton,shortShift, longx,longy){//TODO:Addyourcontrolnotificationhandlercodehere//Iftheselectedcolumnwasthefirstcolumn,there'snothingtodoif(m_iMouseCol==0)return;m_ctrlFGrid.SetRedraw(FALSE); //Turnthecontrolredrawoffm_ctrlFGrid.SetColPosition(m_iMouseCol, m_ctrlFGrid.GetMouseCol());

//Changetheselectedcolumnposition45a2把列移動到鼠標(biāo)被釋放處45aDoSort(); //Resortthegridm_ctrlFGrid.SetRedraw(TRUE); //Trunredrawbackon}這兩個事件消息的映射如下:BEGIN_EVENTSINK_MAP(CActiveXDlg,CDialog)

//{{AFX_EVENTSINK_MAP(CActiveXDlg)

ON_EVENT(CActiveXDlg,IDC_MSFGRID,-605/*MouseDown*/,

OnMouseDownMsfgrid,VTS_I2VTS_I2VTS_I4VTS_I4)

ON_EVENT(CActiveXDlg,IDC_MSFGRID,-607/*MouseUp*/,

OnMouseUpMsfgrid,VTS_I2VTS_I2VTS_I4VTS_I4)

//}}AFX_EVENTSINK_MAPEND_EVENTSINK_MAP()3編譯運(yùn)行“ActiveX”46aDoSort(); //Resorttheg12.3創(chuàng)建ActiveX控件本例通過制作一個能繪制涂鴉的控件實(shí)例,描述一個ActiveX控件的一般創(chuàng)建方法,并通過測試工具和一個應(yīng)用實(shí)例來驗(yàn)證該控件的設(shè)計功能。·控件功能:能在一個可確定的矩形區(qū)域中通過點(diǎn)擊鼠標(biāo)或通過其他方法獲得模擬的鼠標(biāo)點(diǎn)擊事件,以便隨機(jī)繪制涂鴉,并且能將所繪制的涂鴉保存到一個磁盤文件中和能使用該磁盤文件所保存的數(shù)據(jù)恢復(fù)涂鴉。為實(shí)現(xiàn)這些功能,所設(shè)計的控件應(yīng)具有以下屬性、方法和事件:47a12.3創(chuàng)建ActiveX控件47a·控件屬性:屬性是指控件中可見的、容器應(yīng)用程序可修改的屬性數(shù)據(jù)。四種基本的屬性類型是:

環(huán)境(ambient) 由容器應(yīng)用程序提供給控件,例如,背景 顏色或缺省字體,使控件看上去就像是容器應(yīng)用程序的

一部分;擴(kuò)展(extended) 由容器應(yīng)用程序提供并實(shí)現(xiàn)的屬性,控件 可以對這些屬性做一定擴(kuò)展;

庫存(stock) 由ActiveX控件開發(fā)工具實(shí)現(xiàn),例如控件的 字體或控件的背景顏色;

定制(custom) 是最需要關(guān)注的屬性,因?yàn)檫@些屬性是所 設(shè)計的控件專有的,并且直接與控件的功能有關(guān)。 本例需要三個custom屬性:48a·控件屬性:屬性是指控件中可見的、容器應(yīng)用程序可修改的48a

NumberSquiggles 繪制涂鴉的最多段數(shù);

SquiggleLength 一段涂鴉的最大長度;

KeepCurrentDrawing 是否保持當(dāng)前所繪制的涂鴉。為了能在容器應(yīng)用程序中訪問和修改這些屬性還需要為每個屬性提供相應(yīng)的Get和Set

方法,即把這些屬性“暴露”給容器

應(yīng)用程序?!た丶椒ǎ菏强丶械哪鼙蝗萜鲬?yīng)用程序調(diào)用的函數(shù)。在本控件中除了要提供三個屬性的訪問和設(shè)置方法,以及顯示控件版本信息的方法外,還需要提供下列三個與控件功能密切相關(guān)的方法:

DoClick 用于模擬在控件區(qū)域內(nèi)鼠標(biāo)點(diǎn)擊操作;

SaveDrawing 用于保存當(dāng)前的涂鴉為一個磁盤文件;

LoadDrawing 使用磁盤文件中保存的數(shù)據(jù)恢復(fù)涂鴉。49a NumberSquiggles 繪制涂鴉的最多段數(shù);49a·控件事件:事件是控件發(fā)給容器應(yīng)用程序的通知消息。它們用于通知容器應(yīng)用程序某種事件已經(jīng)發(fā)生,以便容器應(yīng)用程序在需要時采取相應(yīng)的措施。從控件中可以觸發(fā)兩類事件:

庫存事件 通過ActiveX控件開發(fā)工具實(shí)現(xiàn),可以在控件內(nèi)以 函數(shù)調(diào)用的方式使用,也可以使你觸發(fā)容器應(yīng)用程序中 的鼠標(biāo)或鍵盤事件、錯誤或狀態(tài)的變化。定制事件 這些事件與控件的特定功能相關(guān)聯(lián)。這類事件可 以指定與事件一起傳遞給容器的參數(shù),使容器能得到所 需要的數(shù)據(jù),以便對事件消息作出反應(yīng)。本控件中定義了三個事件:

click

庫存事件,通知在控件區(qū)域中發(fā)生了鼠標(biāo)點(diǎn)擊;

FileStored

定制事件,通知當(dāng)前保存涂鴉已經(jīng)成功或失??;

FileLoaded

定制事件,通知當(dāng)前恢復(fù)涂鴉已經(jīng)成功或失敗。50a·控件事件:事件是控件發(fā)給容器應(yīng)用程序的通知消息。它們50a12.3.1創(chuàng)建控件外殼使用MFCActiveXControlWizard(控件創(chuàng)建向?qū)В橐獎?chuàng)建的任何ActiveX控件建立一個“外殼”(“Squiggle”ActiveX控件項(xiàng)目)。它將生成所有必要的文件,并配置項(xiàng)目,這樣在編譯項(xiàng)目時,編譯器就會建立一個ActiveX控件。在VisualC++6.0中,該項(xiàng)目創(chuàng)建的方法和操作步驟如下:51a12.3.1創(chuàng)建控件外殼51a52a52a創(chuàng)建此項(xiàng)目需要經(jīng)過下列兩步:1在“Step1of2”對話框中進(jìn)行如下操作:

53a創(chuàng)建此項(xiàng)目需要經(jīng)過下列兩步:53a·確定項(xiàng)目中包含幾個ActiveX控件,默認(rèn)的控件數(shù)為1?!ご_定所創(chuàng)建的控件是否需要運(yùn)行時許可證,這是一種防止控件的使用者在沒有購買運(yùn)行時許可證的情況下使用控件進(jìn)行開發(fā)的措施。默認(rèn)選擇為不需要運(yùn)行時許可證。·確定是否為程序源代碼生成注釋,默認(rèn)選擇為生成注解。·確定是否為控件生成幫助文件,默認(rèn)選擇為沒有幫助文件。本例中均使用默認(rèn)選擇。54a·確定項(xiàng)目中包含幾個ActiveX控件,默認(rèn)的控件數(shù)為12在“Step2of2”對話框中繼續(xù)進(jìn)行下列操作:·如果需要,可以選擇瀏覽或修改控件的類名和文件名。組合列表框中包含了項(xiàng)目中所有要創(chuàng)建的ActiveX控件類名。55a2在“Step2of2”對話框中繼續(xù)進(jìn)行下列操作·選擇所創(chuàng)建的控件具有的特性:①控件在可見時被激活(默認(rèn)特性);②運(yùn)行時不可見;③在“InsertObject”對話框中可使用;④具有版本對話框“About”(默認(rèn)特性);⑤作用為一個簡單的框架控件?!みx擇一種窗口類(在組合列表框中列出的)作為所創(chuàng)建控件

的子類,例如,欲創(chuàng)建一個特殊的編輯框,以便對用戶輸入該編輯框的任何內(nèi)容進(jìn)行一些編輯,就可以選擇EDIT類作為

控件的子類。默認(rèn)選擇為不選擇任何窗口類,即none。56a·選擇所創(chuàng)建的控件具有的特性:56a·按Advanced按鈕可以進(jìn)行高級設(shè)置,但要求對ActiveX控件有相當(dāng)深入的了解,所以一般可以不做此項(xiàng)選擇。本例中均使用默認(rèn)選擇。3按《Finish》按鈕完成ActiveX控件外殼的創(chuàng)建。57a·按Advanced按鈕可以進(jìn)行高級設(shè)置,但要求對Ac在VisualC++.NET中,該項(xiàng)目創(chuàng)建的方法和操作步驟如下:1創(chuàng)建一個名為“Squiggle”ActiveX控件項(xiàng)目:58a在VisualC++.NET中,該項(xiàng)目創(chuàng)建的方法和操2保持該ActiveX控件項(xiàng)目不具有運(yùn)行許可證的缺省設(shè)置:59a2保持該ActiveX控件項(xiàng)目不具有運(yùn)行許可證的缺省設(shè)3保持該ActiveX控件項(xiàng)目的所有命名缺省設(shè)置:60a3保持該ActiveX控件項(xiàng)目的所有命名缺省設(shè)置:604保持該ActiveX控件項(xiàng)目的所有控件屬性缺省設(shè)置:5按《Finish》按鈕完成ActiveX控件外殼的創(chuàng)建。61a4保持該ActiveX控件項(xiàng)目的所有控件屬性缺省設(shè)置:12.3.2增加進(jìn)行繪制涂鴉的類CLine和CModArt1CLine類分解涂鴉的繪制操作是由一系列的隨機(jī)線段(線段的位置、長度、顏色和線寬均隨機(jī)發(fā)生)組成的。因此,創(chuàng)建一個類CLine,將描述這些線段的屬性和操作封裝在其中,并在整個涂鴉的繪制過程中,逐個隨機(jī)創(chuàng)建CLine類對象。⑴定義CLine類使用ClassWizard定義一個GenericClass類CLine,并在Base

Class列表框的第一行輸入CObject作為基類,保留其public屬性。62a12.3.2增加進(jìn)行繪制涂鴉的類CLine和CMod注意:①由于編譯器找不到CObject類的定義,因此,會在確認(rèn)定義CLine類時,顯示如下信息框:63a63a你可以不必理會它,而按“確認(rèn)”按鈕完成CLine的創(chuàng)建。但如果你使用的基類是比MFC類層次更低的自定義類,則需要留意此信息,并將必須的頭文件包含(#include)到源代碼文件中。②在VisualC++.NET中,定義CLine時不會發(fā)生上述問題。64a64a②為了使CLine類具有持續(xù)性,需要在CLine類的定義文件中加入宏: classCLine:publicCObject {

DECLARE_SERIAL(CLine) … };在實(shí)現(xiàn)文件中加入如下宏: …

IMPLEMENT_SERIAL(CLine,CObject,1) …65a②為了使CLine類具有持續(xù)性,需要在CLi⑵為CLine類增加描述線段的屬性classCLine:publicCObject{…private:

COLORREFm_crColor; //線段顏色

CPointm_ptFrom; //線段起點(diǎn)

CPointm_ptTo; //線段終點(diǎn)

UINTm_pnWidth; //畫筆寬度};66a⑵為CLine類增加描述線段的屬性66a⑶增加一個能為線段屬性賦值的構(gòu)造函數(shù)CLine::CLine(CPointptFrom,CPointptTo, UINTpnWidth,COLORREFcrColor){

//Initializethefromandtopointsm_ptFrom=ptFrom;m_ptTo=ptTo;m_pnWidth=pnWidth;m_crColor=crColor;}67a⑶增加一個能為線段屬性賦值的構(gòu)造函數(shù)67a⑷定義繪制線段的成員函數(shù)Draw并為其編碼voidCLine::Draw(CDC*pDC){ //Createapen

CPenlpen(PS_SOLID,m_pnWidth,m_crColor); //Setthenewpenasthedrawingobject

CPen*pOldPen=pDC->SelectObject(&lpen); //Drawtheline pDC->MoveTo(m_ptFrom); pDC->LineTo(m_ptTo); //Resetthepreviouspen pDC->SelectObject(pOldPen);}68a⑷定義繪制線段的成員函數(shù)Draw并為其編碼68a⑸手工重載CObject的持續(xù)化虛成員函數(shù)Serialize并為其編碼voidCLine::Serialize(CArchive&ar){

CObject::Serialize(ar);if(ar.IsStoring())ar<<m_ptFrom<<m_ptTo<<(DWORD)m_crColor<<m_pnWidth;elsear>>m_ptFrom>>m_ptTo>>(DWORD)m_crColor>>m_pnWidth;}69a⑸手工重載CObject的持續(xù)化虛成員函數(shù)Seriali2CModArt類創(chuàng)建此類的目的就是要實(shí)現(xiàn)對一個完整涂鴉畫面的描述和圍繞繪制涂鴉所需要的所有操作。⑴定義CModArt

類與定義CLine類相似,使用ClassWizard創(chuàng)建一個GenericClass類CModArt,并在BaseClass列表框的第一行輸入CObject作為基類,保留其public屬性。雖然CModArt類也需要實(shí)現(xiàn)持續(xù)性,但不需要在類定義文件和實(shí)現(xiàn)文件中加入實(shí)現(xiàn)持續(xù)性的宏,原因是CModArt的持續(xù)性可以通過CLine的持續(xù)性實(shí)現(xiàn)。70a2CModArt類70a⑵為CModArt類增加描述整幅涂鴉的屬性classCModArt:publicCObject{public:…CRectm_rDrawArea; //繪制涂鴉的區(qū)域

CObArraym_oaLines; //用于存放組成涂鴉的所有線段的數(shù)組…private:

intm_iLength; //組成一條涂鴉線的最多線段數(shù)

intm_iSegments; //組成整幅涂鴉畫面的最多涂鴉線數(shù)…};71a⑵為CModArt類增加描述整幅涂鴉的屬性71a⑶為CModArt添加一些訪問和修改屬性的公有成員函數(shù)intCModArt::GetLength(){

//Returnthecurrentvalueforthem_iLengthvariablereturnm_iLength;}voidCModArt::SetLength(intiLength){

//Setthecurrentvalueforthem_iLengthvariablem_iLength=iLength;}72a⑶為CModArt添加一些訪問和修改屬性的公有成員函數(shù)intCModArt::GetSegments(){

//Returnthecurrentvalueforthem_iSegmentsvariablereturnm_iSegments;}voidCModArt::SetSegments(intiSegments){

//Setthecurrentvalueforthem_iSegmentsvariablem_iSegments=iSegments;}voidCModArt::SetRect(CRectrDrawArea){

//Setthedrawingarearectanglem_rDrawArea=rDrawArea;}73aintCModArt::GetSegments()73a⑷為CModArt添加生成一條涂鴉線的私有成員函數(shù)voidCModArt::NewLine(){intlNumLines,lCurLine;UINTnCurWidth;CPointpTo,pFrom;intcRed,cBlue,cGreen;

//Normalizetherectanglebeforedeterminingthewidthandheightm_rDrawArea.NormalizeRect();

//GettheareawidthandheightintlWidth=m_rDrawArea.Width();intlHeight=m_rDrawArea.Height();

//DeterminethenumberofpartstothissquigglelNumLines=rand()%m_iLength;

//Arethereanypartstothissquiggle?74a⑷為CModArt添加生成一條涂鴉線的私有成員函數(shù)74if(lNumLines>0){//DeterminethecolorcRed=rand()%256;cBlue=rand()%256;cGreen=rand()%256;

//DeterminethepenwidthnCurWidth=(rand()%8)+1;

//DeterminethestratpointforthesquigglepFrom.x=(rand()%lWidth)+m_rDrawArea.left;pFrom.y=(rand()%lHeight)+m_rDrawArea.top;

//Loopthroughthenumberofsegmentsfor(lCurLine=0;lCurLine<lNumLines;lCurLine++){ //Determinetheendpointofthesegment pTo.x=((rand()%23)-10)+pFrom.x; pTo.y=((rand()%23)-10)+pFrom.y;

//CreateanewClineobject

CLine*pLine=newCLine(pFrom,pTo,nCurWidth,

RGB(cRed,cBlue,cGreen));75aif(lNumLines>0)75a

try

//Addthenewlinetotheobjectarray m_oaLines.Add(pLine);

//Didwerunintoamemoryexception

catch(CMemoryException*perr) {//Displayamessgefortheuser,givinghimthebadnews

AfxMessageBox("Outofmemory",MB_ICONSTOP|MB_OK);

//Didwecreatealineobject? if(pLine)

deletepLine;pLine=NULL; //Deleteit perr->Delete(); //Deletetheexceptionobject } pFrom=pTo; //Setthestartingpointtotheendpoint}}}76a try//Addthenewlineto⑸為CModArt添加生成整幅涂鴉的公有成員函數(shù)voidCModArt::NewDrawing(){intlNumLines,lCurLine;

//DeterminehowmanylinestocreatelNumLines=rand()%m_iSegments;

//Arethereanylinestocreate?if(lNumLines>0){//Loopthroughthenumberoflinesfor(lCurLine=0;lCurLine<lNumLines;lCurLine++)

NewLine(); //Createthenewline}}77a⑸為CModArt添加生成整幅涂鴉的公有成員函數(shù)77a⑹修改CModArt的構(gòu)造函數(shù)CModArt::CModArt(){

//Initializetherandomnumbergenerator

srand((unsigned)time(NULL));

//Initializetheproptyvariablesm_iLength=200;m_iSegments=50;}78a⑹修改CModArt的構(gòu)造函數(shù)78a⑺為CModArt添加繪制整幅涂鴉的公有成員函數(shù)DrawvoidCModArt::Draw(CDC*pDC){//GetthenumberoflinesintheobjectarrayintliCount=m_oaLines.GetSize();intliPos;

//Aretheranyobjectsinthearray?if(liCount){//Loopthroughthearray,drawingeachobjectfor(liPos=0;liPos<liCount;liPos++) ((CLine*)m_oaLines[liPos])->Draw(pDC);}}79a⑺為CModArt添加繪制整幅涂鴉的公有成員函數(shù)Dr⑻為CModArt添加清除整幅涂鴉的公有成員函數(shù)ClearDrawingvoidCModArt::ClearDrawing(){//GetthenumberoflinesintheobjectarrayintliCount=m_oaLines.GetSize();intliPos;if(liCount) //Arethereanyobjectsinthearray{//Loopthroughthearray,deletingeachobjectfor(liPos=0;liPos<liCount;liPos++)

deletem_oaLines[liPos];m_oaLines.RemoveAll();//Resetthearray}}80a⑻為CModArt添加清除整幅涂鴉的公有成員函數(shù)Cl⑼為CModArt重載持續(xù)化函數(shù)SerializevoidCModArt::Serialize(CArchive&ar){//Passthearchiveobjectontothearraym_oaLines.Serialize(ar);}顯然,CModArt類的持續(xù)化操作是通過數(shù)組中保存的CLine類對象的持續(xù)化函數(shù)實(shí)現(xiàn)的。在控件類CSquiggleCtrl中添加CModArt類對象m_maDrawing,訪問權(quán)限為私有。該對象成員用于在控件中調(diào)用CModArt的方法實(shí)現(xiàn)繪制涂鴉。注意在CSquiggleCtrl類的定義文件中包含CModArt類的頭文件。81a⑼為CModArt重載持續(xù)化函數(shù)Serialize812.3.3為控件添加屬性為了在使用控件時能訪問和修改CModArt的屬性m_iLength

和m_iSegments,需要為CSquiggleCtrl添加相應(yīng)的屬性。1添加屬性SquiggleLength⑴在DSquiggle處,單擊鼠標(biāo)右鍵,彈出環(huán)境菜單,并選擇菜單項(xiàng)“AddProperty…”:82a12.3.3為控件添加屬性82a在VisualC++6.0中: 在VisualC++>NET中:83a在VisualC++6.0中: ⑵在“AddProperty”對話框中,將該屬性命名為

SquiggleLength, 并指定其類型為short

或SHORT類型。接受系統(tǒng)自動為該屬 性命名的內(nèi)部變量名m_squiggleLength或m_SquiggleLength,以 及為該屬性自動增加的通知函數(shù)OnSquiggleLengthChanged。保 持缺省的屬性實(shí)現(xiàn)類型(Membervariable)。單擊《OK》或 《Finish》按鈕,完成該屬性的添加操作。 上述操作如下圖所示:84a⑵在“AddProperty”對話框中,將該屬性命名在VisualC++6.0中:85a在VisualC++6.0中:85a在VisualC++.NET中:86a在VisualC++.NET中:86a⑶為OnSquiggleLengthChanged添加執(zhí)行代碼:在VisualC++6.0中的代碼如下:shortCSquiggleCtrl::OnSquiggleLengthChanged(){m_maDrawing.SetLength(m_squiggleLength); //添加的代碼

SetModifiedFlag(); //缺省代碼}在VisualC++.NET中的代碼如下:voidCSquiggleCtrl::OnSquiggleLengthChanged(){

AFX_MANAGE_STATE(AfxGetStaticModuleState()); //缺省代碼m_maDrawing.SetLength(m_squiggleLength); //添加的代碼

SetModifiedFlag(); //

缺省代

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論