vc6開發activex併發布全攻略(三)

原文:http://flashaway.blog.163.com/blog/static/95624576200942211853685/

小南瓜餅(^^):http://blog.csdn.net/Ibznphone

前面兩片文章我們製作了個一簡單的 ActiveX,而這個ActiveX只實現了一個簡單的計算功能。其實ActiveX控件的功能很好很強大,只要你能想到的,它基本都能夠實現。可我現在的水平那也只能想到而做不到 >_< 。所以,還是在網上多找些例子,邊做邊學。

下面是我轉載的一個例子,實現的功能是將網頁保存到本地。照舊,我會在後面列出我製作時出現的問題及解決方案。

原文地址:http://www.7880.com/info/2005/06/08/article-14697.html

ActiveX控件的開發

    這段時間因爲工作的需要,開發了一個ActiveX控件,採用的開發工具是VC,希望可以給大家做類似的開發時提供參考。

 

一,ActiveX控件的功能:

1,主要是用來下載和保存指定的網頁。

2,要能夠嵌在網頁中,供服務器頁面的腳本調用。

3,提供下載保存到哪個文件夾的窗口,給用戶自己選擇保存位置的機會。

4,提供程序接口,使得用戶可以保存單個文件。

5,提供程序接口,使得用戶可以保存多個文件,文件名以數組的方式傳遞過來。

 

二,ActiveX控件的開發過程:

1,通過VC的MFC ActiveX  ControlWizard 嚮導開發這個控件,將項目命名爲ActiveX3

2,在嚮導的Step2 of 2中爲Invisible at runtime打鉤,並去掉Has an “About” Box前面的鉤,該控件在調用時則不顯示。

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

3,打開ClassWizard,在Automation下添加方法:

(1) External Name: DownloadSingle

 Internal Name: DownloadSingle

 Return Type: BOOL

 Parameter List: strDownload  LPCTSTR

         

         該方法的作用:接受並處理參數爲字符串類型的下載請求,同時爲操作員提供指定下載目錄的機會並接受其指定。  

 

(2)    External  Name: DownloadArray

Internal Name: DownloadArray

Return Type: BOOL

Parameter List: arrDownload  Variant

 

         該方法的作用:接受並處理參數字符串數組類型的下載請求,同時爲操作員提供指定下載目錄的機會並接受其指定。

 

4,通過手工添加方法:  

   void TryUrl(CString strAddress)

   被DownloadArray和DownloadSingle調用,用來實現具體下載功能。

 

三,關鍵代碼

 1,   BOOL CActiveX3Ctrl::DownloadSingle(LPCTSTR strDownload)

{

       // TODO: Add your dispatch handler code here

      char buf[MAX_PATH];

       _getcwd(buf,MAX_PATH);

   location=”d:\\”;

   TryUrl(strDownload);

       MessageBox("下載完成!");

       return TRUE;

}

 

2, BOOL CActiveX3Ctrl::DownloadArray(const VARIANT FAR& arrDownload)

{

       // TODO: Add your dispatch handler code here

       char buf[MAX_PATH];

       _getcwd(buf,MAX_PATH);

       location=”d:\\”;

       const VARIANT *varArray;

       if(arrDownload.vt==(VT_VARIANT|VT_BYREF))

       {

          varArray=arrDownload.pvarVal;

       }

       else

       {

          varArray=&arrDownload;

    }

   if((varArray->vt)==(VT_ARRAY | VT_BYREF | VT_VARIANT))

        {

              VARIANT* strarray;

              SAFEARRAY* psa = *(varArray->pparray);

              SafeArrayAccessData(psa,(void**)&strarray);

              UINT uDim = SafeArrayGetDim(psa);

              if(uDim==1)

              {

                     long lLbound,lRbound;

                     SafeArrayGetLBound(psa,1,&lLbound);

                     SafeArrayGetUBound(psa,1,&lRbound);

                     for(long i=lLbound;i<=lRbound;i++)

                     {

                            if(strarray[i].vt==VT_BSTR)

                            {    

                                 TryUrl(strarray[i].bstrVal);

                            }

                     }

              }

              SafeArrayUnaccessData(psa);

       }

    MessageBox("下載完成!");

       return TRUE;

}

3,void CActiveX3Ctrl::TryUrl(CString strAddress)

{

       CFile newFile;

              Cstring fileName=strAddress.Mid(strAddress.ReverseFind('/')+1); 

              newFile.Open(location+"\\"+fileName,CFile::modeCreate | CFile::modeWrite); 

              CInternetSession session;

       CInternetFile* file=NULL;

       try

         {

              file=(CInternetFile*)session.OpenURL(strAddress);      }

          catch(CInternetException* pEx)

         {

              file=NULL;

              pEx->Delete();

         }

         if(file)

         { 

              int number=0;

              BYTE *buf;

              buf=new BYTE[1024];

              do

              {

              number=file->Read(buf,1024);

           newFile.Write(buf,number);

              }

              while(number>0);

        delete []buf;

         }

         file->Close();

      newFile.Close();

       return;

}

四,測試頁面

<html>

<head>

<title>Download three files from the web.</title>

<script language="javascript">

function download1()

{

var file;

file=document.form1.text1.value;

FavouriteDown.downloadSingle(file);

return;

}

</script>

<script language="VBScript">

<!--

Sub downN_OnClick

Dim s(2)

s(0)=document.form1.text1.value

s(1)=document.form1.text2.value

s(2)=document.form1.text3.value

ActiveXDown.DownloadArray(s)

End Sub

-->

</script>

</head>

<body>

<OBJECT ID="ActiveXDown"

CLASSID="CLSID:ADD73828-78F4-4EF1-8734-61590B044F87"

CODEBASE="ActiveX3.ocx#version=1,0,0,0">

</OBJECT>

<center>

<form name="form1">

<input type="text" name="text1" size="50"><p>

下載一個文件:<input type="button" name="down1" value="down1" οnclick="javascript:download1();"><p>

<input type="text" name="text2" size="50"><p>

<input type="text" name="text3" size="50"><p>

下載三個文件:<input type="button" name="downN" value="downN"><p>

</form>

</body>

</html>

 

 

 

 

 #######################以下是在開發ActiveX時出現的問題補充########################

 

按照上面博文的方法,我們要添加三個方法,添加方法我就不具體講了,前面一篇已經抓過圖。需要注意的是博文中第四步說要手動添加void TryUrl(CString strAddress)方法,我到現在也還沒理解,只有通過Automation添加了。在添加過程中,參數無法選擇Cstring類型,如圖:

 vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

如有高手路過,請指點一二。

那我們只能先選擇LPCTSTR代替。那我們就必須在程序裏該下,將LPCTSTR轉換爲CString類型。

//下載網頁

void CMyActiveXCtrl::TryUrl(LPCTSTR str)

{

       // TODO: Add your dispatch handler code here

      CString   strAddress(str);//在這裏轉換成CString類型 

         CFile newFile;

      CString fileName=strAddress.Mid(strAddress.ReverseFind('/')+1);

      newFile.Open(location+"\\"+fileName,CFile::modeCreate | CFile::modeWrite);

      CInternetSession session;

      CInternetFile* file=NULL;

      try

      {

            file=(CInternetFile*)session.OpenURL(strAddress);     

         }

       catch(CInternetException* pEx)

       {

            file=NULL;

            pEx->Delete();

          }

       if(file)

          { 

              int number=0;

              BYTE *buf;

              buf=new BYTE[1024];

              do

              {

                  number=file->Read(buf,1024);

                  newFile.Write(buf,number);

              }

              while(number>0);

              delete []buf;

       }

       file->Close();

       newFile.Close();

       return;

}

 

而且程序中的location也得通過Automation選項卡添加成全局變量(添加變量請參見前面的一篇文章),並且賦初值,如下圖:

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

還有BOOL CActiveX3Ctrl::DownloadArray(const VARIANT FAR& arrDownload)編譯時也出錯,說是字符分割時出現錯誤:修改後的代碼如下:

//同時保存多個網頁

BOOL CMyActiveXCtrl::DownloadArray(const VARIANT FAR& arrDownload)

{

       // TODO: Add your dispatch handler code here

 

      char buf[MAX_PATH];

 

       _getcwd(buf,MAX_PATH);

 

       const VARIANT *varArray;

 

       if(arrDownload.vt==(VT_VARIANT|VT_BYREF))

       {

          varArray=arrDownload.pvarVal;

       }

 

       else

 

       {

 

          varArray=&arrDownload;

 

    }

 

   if((varArray->vt)==(VT_ARRAY | VT_BYREF | VT_VARIANT))

   {

         VARIANT* strarray;

         SAFEARRAY* psa = *(varArray->pparray);

         SafeArrayAccessData(psa,(void**)&strarray);

         UINT uDim = SafeArrayGetDim(psa);

         if(uDim==1)

               {

              long lLbound,lRbound;

              SafeArrayGetLBound(psa,1,&lLbound);

              SafeArrayGetUBound(psa,1,&lRbound);

              for(long i=lLbound;i<=lRbound;i++)

                       {

                   if(strarray[i].vt==VT_BSTR)

                               {    

                                     //這裏編譯時出錯,下面是改動後的代碼

                                          int size= WideCharToMultiByte(CP_ACP,0,strarray[i].bstrVal,-1, NULL, 0, NULL,0);

                                          char * AsciiBuff =new char[size];

                                          WideCharToMultiByte(CP_ACP,0,strarray[i].bstrVal,-1,AsciiBuff,size, NULL, 0);

                        TryUrl(AsciiBuff);

 

                   }

                       }

               }

         SafeArrayUnaccessData(psa);

     }

 

       MessageBox("下載完成!");

       return TRUE;

}

 

哦,還要注意添加一個頭文件引用:

#include <afxinet.h>

如下圖:

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

現在編譯下,直接通過,呵呵。

 

編譯通過後,你可以通過ActiveXControlTestContainer對控件進行調試。調試前先設置下:打開

工程->設置,彈出對話框設置調試,選擇可執行調試設置爲ActiveXControlTestContainer,如下圖:

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

然後在程序裏打上斷點。按F5啓動調試,在方法中選擇DownloadSingle方法,設置參數,我這裏輸入http://localhost/test.html,點擊invoke按鈕,程序就會走到你設置的斷點處:

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

那我們點擊invoke按鈕,如果沒有斷點,程序直接執行,彈出下載完成對話框。因爲程序中我設置的路徑是D:\,所以應該在我的D盤下可以找到一個名爲test.html的文件。如果你也找到了,說明你的控件也可以正常運行了。

 

下面就該發佈這個ActiveX了。如果你是第一次讓用戶安裝此控件,那你可以參照我的上一篇文章進行發佈。如果前面用戶已經安裝了上一個版本,那我們這次就是讓用戶升級ActiveX了。

升級ActiveX,我們需要修改三個地方。

一, 我們首先要修改程序中的版本。打開工程的ResourceView資源瀏覽菜單,選擇VS_VERSION_INFO節點,我們可以看到原來的FILEVERSION中的版本號是1.0.0.1, 我們把它改成1,0,0,2。如下圖(NND,圖怎麼倒了,湊活着看吧,呵呵):

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

F7直接編譯完成。

二,修改發佈文件信息

MyActiveX.inf,將FileVersion該爲1,0,0,2

 vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

重新生成cab文件並簽名。將生成的MyActiveX.cab拷貝到服務器IIS發佈目錄。

三, 修改test.html頁面cab的版本信息,將version改爲1,0,0,2 

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

 

注意:文中的版本信息1,0,0,2中間一定是逗號。

 

那現在我們就可以讓用戶打開這個包含控件的頁面,IE會提示用戶重新安裝ActiveX控件。

如果用戶安裝成功,我們可以在C:\WINDOWS\Downloaded Program Files目錄下看到這個Activex控件信息:

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

還可以打開IE中的Internet選項,程序->管理加載項目中查看

vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

也可以點擊刪除按鈕對我們的ActiveX進行刪除。

 

下面我們開始對ActiveX進行測試:

Test.html頁面我做了下改動,代碼如下:

<html>

<head>

<title>Download three files from the web.</title>

</head>

<body>

<object id='test1' codeBase='http://10.79.108.75/MyActiveX.cab#version=1,0,0,2' classid='clsid:743F39F2-E3A5-4550-A203-4A1CFAE9ABCF' height=0 width=0 ></object>

<center>

<form name="form1">

<input type="text" name="text1" size="50"><p>

下載一個文件:<input type="button" name="down1" value="down1" οnclick="javascript:download1();"><p>

<input type="text" name="text2" size="50"><p>

<input type="text" name="text3" size="50"><p>

下載三個文件:<input type="button" name="downN" value="downN"><p>

</form>

</body>

</html>

<script language="javascript">

       a=test1.test(2,1);

       alert(a);

function download1()

{

       var file;

       file=document.form1.text1.value;

       test1.downloadSingle(file);

       return;

}

 

</script>

<script language="VBScript">

<!--

 

Sub downN_OnClick

 

Dim s(2)

 

s(0)=document.form1.text1.value

 

s(1)=document.form1.text2.value

 

s(2)=document.form1.text3.value

 

test1.DownloadArray(s)

 

End Sub

 

-->

 

</script>

如圖:

 vc6開發activex併發布全攻略(三)(進階篇) - 一閃而過 - 一閃而過的博客

 

輸入網址進行測試,下載成功。

如果你輸入爲空,或者網頁打不開,IE就會崩潰而退出,這是因爲我們在程序中都沒有做驗證。反正大概功能已經實現,驗證你可以自己修改正下。

還有就是我把test.html中的的vbscript該爲javascript後,點多個下載後程序執行失敗,很是鬱悶,javascript代碼如下:

function download2()

{

       alert(1);

       var a1=new Array(3);

       a1[0]=document.form1.text1.value;

       a1[1]=document.form1.text2.value;

       a1[2]=document.form1.text3.value;

       test1.DownloadArray(a1);

}

後來找了一篇博文《把javascript,vbscript中得數組傳遞給COM組件(or Activex)》,原文網址是:

http://blog.csdn.net/wzsy/archive/2008/03/18/2193551.aspx

有興趣你可以研究下,我就不研究了,呵呵。

到此我們的ActiveX又新增了些功能。後面還會增加些簡單的功能,敬請關注。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章