在Visual Basic 中使用C++ 類 (轉)

gugu99發表於2008-03-04
在Visual Basic 中使用C++ 類 (轉)[@more@]在 中使用C++ 類

 用C++ Builder 建立可重用的OLE Automation

 李國興

我在Borland C++ For 環境下編制工程輔肋設計時定義了一個生成AutoCAD DXF 圖形的類,在後來用Visual Basic 編寫另一輔肋設計程式時又需要生成DXF圖形檔案,為了利用已有的程式碼,我在Borland C++ Builder 3.0 中將普通的C++類轉換成Automation 程式內,供Visual basic 使用,成功地實現了不同語言源程式級的重用。現將轉換方法簡單地介紹給大家。供大家參考。

 原C++ 類宣告如下: (為節約篇幅,進行了大量簡化只實現基本功能)

class Dxf{

 private:

 HFILE handle; //DXF 檔案頭

 String SecStart; //節頭

 String SecEnd; //節尾

 String Tables; //表節串

 String Blocks; //塊節串

 String Entities; //實體節串

 protected:

 bool WriteTitleSec(); //寫標題節

 bool WriteBlockSec(); //寫塊節

 bool WriteEntitiesSec(); //寫實體節

 public:

 Dxf();

 bool SaveToFile(char *filename); // 儲存資料到檔案

 void Dxf_Line(float x1,float y1,float x2,float y2,int Layer=0); // 畫直線

};

將C++類轉換成程式內伺服器的過程如下:

1. 開啟BorLand C++ Builder 3.0 的整合開發環境,選擇File選單下的new 子選單,C++ Builder 將開啟專案選擇視窗,選擇 頁面,在Active 頁面中選擇Active Library。然後再選擇File選單下的new 子選單,選擇ActiveX 頁面,在Active 頁面中選擇Automation object 開啟Automation Object Wizard 對話方塊,在Class name 框中填入DxfCls 作為在VB中引用Dxf 類的類名,單點Ok 完成。C++ Builder 3.0 將建立型別庫,完成工程的建立。並開啟型別庫編輯視窗。(一點說明,由於BorLand C++ Builder在建立Automation Object 時,預設是建立程式外的自動化伺服器,在此我僅需的是作為DLL的程式內的自動化伺服器,因此要首先創造一外型別庫,再把自動化伺服器加到型別庫中去。

2. 選擇將工程以DxfCls 名存檔,並將unit1以Dxf存檔。

3. 在型別庫編輯窗中的Attributes頁中將Name 中的project1 改為Dxf,將Help組框中的Help string 改為dxf Library,此字串將在的引用選擇窗中顯示。其它不用修改。

4. 將原Dxf 類中的除構造和析構以外的暴露給VB,其方法是選擇Idxfcls節點,單擊工具欄上的Method,然後在Attributes 頁上將name對話方塊中Method1修改為您所需要的函式名,再選擇Parameters 頁設定函式的返回資料型別和型參。在選擇返回資料時,注意下拉選單框中不直接支援bool 作為返回型別,您可以選擇short或者選擇Varian_bool 作為返回型別,在這裡我選擇short來替代bool 作為返回型別。此外型參表中的前兩項對應通常C函式中的資料名和資料型別,資料型別以下拉選單的型式選擇。如果要設定函式的預設形參可雙擊第三個引數,此時將彈出parameters Flags 編輯窗,在編輯窗中選中has default value ,在下面的編輯框中填入預設資料。

5. 單擊工具欄上的Refresh, 編輯器自動在您的Dxf.cpp和dxf.h中新增上您在型別庫中設定的函式宣告。

6. 開啟dxf.cpp檔案,您可在找到SaveToFile等函式的宣告如下:

short STDMETHODCALLTYPE TDxfClsImpl::SaveToFile(LPSTR filename)

{

 try

 {

 }

 catch(Exception &e)

 {

 return Error(e.Message.c_str(), IID_IDxfCls);

 }

 return S_OK;

};

將原dxf.cpp中的已暴露的函式的實現部分貼上到新的dxf.cpp 中的各函式的try 部分,並修改錯誤處理程式碼和返回資料。其它私有函式直接貼上到新的檔案中,僅修改函式名前的類名。

7. 開啟原dxf.h檔案,將類的宣告部分中除已暴露的函式以外的其它部分貼上到剪粘板,然後再開啟當前工程的dxf.h視窗,將剪貼簿的內容複製到TdxfClsImpl類中間。

8. 選擇project選單中的make dxfcls 將工程編譯成DLL檔案。至此完成了C++中的普通類到自動化伺服器的遷移。

9. 選擇Run 選單下的Register ActiveX server, 對dxf 進行註冊。以後就可以在VB中使用dxf 類了。

10. 在VB5.0中使用,在Visual Basic 專案中,選擇工程|引用,開啟引用視窗,選中dxf library 庫,按確認後返回,然後開啟檢視|物件遊覽器,開啟所有庫下拉選單後選擇dxf,再選擇dxfcls就可以見到以上所暴露的SaveToFile和Dxf_line 函式。VB 工程中可以用Dim dxf as new dxfcls 建立引用了。新的dxf 實現類的宣告和實現如下,標頭檔案中的細體字是C++ Bulr 3.0 自動生成,粗體字是新增的。讀者可與C++ Bulider 3.0 自動生成檔案對照。 為了節約篇幅,自動生成的註釋已去掉。

附一. Dxf.h 標頭檔案

#ifndef dxfH

#define dxfH

 #include

#include

//---------------------------------------------------------------------------

#include "Dxf_TLB.h"

#define LIBID_DxfCls LIBID_Dxf

class ATL_NO_VTABLE TDxfClsImpl:

 AUTOOBJECT_IMPL(TDxfClsImpl, DxfCls, IDxfCls)

{

public:

 TDxfClsImpl();

 

BEGIN_COM_MAP(TDxfClsImpl)

 AUTOOBJECT_COM_INTERFACE_ENTRIES(IDxfCls)

END_COM_MAP()

 DECLARE_TYPED_COMSERVER_REGISTRY("Dxf.DxfCls")

 private:

 HFILE handle; 

 int Vports; 

 int LayerNum; 

 String SecStart; 

 String SecEnd;

 String Tables;

 String Blocks;

 String Entities;

 void WriteTitleSec();

 void WriteBlockSec();

 void WriteEntitiesSec();

protected:

 short STDMETHODCALLTYPE SaveToFile(LPSTR filename);

 STDMETHOD(Dxf_Line(float x1, float y1, float x2, float y2, short Layer));

};

#endif

 附二. dxf.cpp檔案

#include

#pragma hdrstop

#include

#include

#include "dxf.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

 

TDxfClsImpl::TDxfClsImpl()

{

 SecStart=" 0nSECTIONn";

 SecEnd=" 0nENDSECn";

 Vports=2;

 LayerNum=1;

 Tables=" 2nTABLESn 0nTABLEn 2nVPORTn 70n";

 Blocks=" 2nBLOCKSn";

 Entities=" 2nENTITIESn";

}

void TDxfClsImpl::WriteTitleSec()

{

write(handle, SecStart.c_str(), SecStart.Length()); // 寫節頭

write(handle," 2nHEADERn",strlen(" 2nHEADERn"));

write(handle, SecEnd.c_str(),SecEnd.Length()); // 寫節尾

}

void TDxfClsImpl::WriteBlockSec()

{

write(handle,SecStart.c_str(), SecStart.Length()); // 寫節頭

write(handle,Blocks.c_str(),Blocks.Length());

write(handle,SecEnd.c_str(),SecEnd.Length()); // 寫節尾

}

void TDxfClsImpl::WriteEntitiesSec() // 寫實體節

{

write(handle, SecStart.c_str(), SecStart.Length());

write(handle,Entities.c_str(),Entities.Length());

write(handle, SecEnd.c_str(),SecEnd.Length());

}

short STDMETHODCALLTYPE TDxfClsImpl::SaveToFile(LPSTR filename)

{

 int i;

 try {

 if (FileExists(filename)){

 i=FileGetAttr(filename);

 if (i& faReadOnly)

 FileSetAttr(filename,i&0xFE);

 DeleteFile(filename); }

 handle=open(filename,O_CREAT|O_TEXT|O_RDWR);

 if (handle==-1) return false;

 WriteTitleSec(); //寫標題節

 WriteBlockSec();

 WriteEntitiesSec();

 write(handle," 0nEOFn",strlen(" 0nEOFn"));

 close(handle);

 }

 catch(Exception &e)

 {

 return false;

}

 return true;

};

//---------------------------------------------------------------------------

STDMETHODIMP TDxfClsImpl::Dxf_Line(float x1, float y1, float x2, float y2,

 short Layer)

{

 char buffer[16];

 try {

 Entities+=" 0nLINEn 8n";

 Entities+=IntToStr(Layer);

 Entities+="n 10n";

 sprintf(buffer,"%6.1f",x1);

 Entities+=buffer;

 Entities+="n 20n";

 sprintf(buffer,"%6.1f",y1);

 Entities+=buffer;

 Entities+="n 30n 0.0n 11n";

 sprintf(buffer,"%6.1f",x2);

 Entities+=buffer;

 Entities+="n 21n";

 sprintf(buffer,"%6.1f",y2);

 Entities+=buffer;

 Entities+="n 31n 0.0n"; }

 catch(Exception &e) {

 return Error(e.Message.c_str(), IID_IDxfCls);

 }

 return S_OK;

};

附三 示例:

在VB 5 中建一新視窗,在視窗上放一Commanutton,命名為cmdCreate,然後輸入以下程式碼,執行後,單擊cmdCreate,就可生成基本的AutoCAD下使用的.DXF檔案。

Private Sub cmdCreate_Click()

 Dim Dxf As New DxfCls

 Dxf.Dxf_Line 100, 100, 500, 100

 Dxf.SaveToFile App.Path & "dxftest.dxf"

End Sub

以上程式分別在Borland C++ Builder 3 Server/Client suit 和VB 5.0 專業版下執行透過。生成的dxftest.dxf在AutoCAD for windows 12 下顯示圖形正常。

一點體會:現在各種語言都提供了建立OLE Automation 伺服器的功能,為我們重用以前的程式碼和利用各種語言進行混合提供了方便。我們可利用各種語言的特點,地開發出高效的應用。 

參考:Borland C++ Builder 3 Server/Client suit 聯機幫助檔案。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1000361/,如需轉載,請註明出處,否則將追究法律責任。

相關文章