• vc6开发activex并发布全攻略(三)(进阶篇)(转载)


    vc6开发activex并发布全攻略(三)(进阶篇)  

    http://flashaway.blog.163.com/blog/static/95624576200942411404477/

     

     

    前 面两片文章我们制作了个一简单的 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" onclick="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" onclick="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又新增了些功能。后面还会增加些简单的功能,敬请关注。

     

  • 相关阅读:
    redis配置引发的问题
    String类的split()方法
    修改mysql编码配置文件不生效
    mysql性能优化小知识点
    limit使用
    mysql执行顺序
    记录一个不知名的错误
    子数组最大和及下标
    maven项目中不能加载java目录下的配置文件
    判断树是否为搜索树
  • 原文地址:https://www.cnblogs.com/vc60er/p/2849013.html
Copyright © 2020-2023  润新知