ActiveX是微软九十年代中期开发的一种技术,它允许你创建一个类似applet的应用程序,并允许你在微软的浏览器中下载和运行。这篇教程的阅读对象是那些希望使用Visuall C++开发第一个ActiveX程序但却不知道如何下手的人。当我自己尝试学习这种技术的时候,我发现关于ActiveX技术使用的信息大部分都没什么用处,是太老了或者缺失一些关键的信息。这让我建立一个可用ActiveX控件工程的过程困难重重。我写这篇文章的用意就是帮助你快速的建立一个ActiveX控件。其中将要讲解关于ActiveX开发的一些基础概念,诸如方法(method)、属性(propertiy)和事件(event),以及ActiveX控件和网页之间的通讯方法。并将要学习如何再Windows XP系统中的IE浏览器默认的安全设置中无警告的执行这个控件。

在这个指南中,我们将要创建一个ActiveX控件用来显示一个GIF动画表现的进度条,用来表示这个控件的载入和执行信息。这个控件的功能将会展示如何在网页和控件之间的信息。我们将会指导你如何使用微软Visual Studio 2005中一步一步的创建这个控件。

创建一个ActiveX控件

为了创建一个ActiveX控件,需要对微软Visual Studio 2005执行以下步骤:

http://www.codeproject.com/com/CompleteActiveX/image002.jpg

图1.新建项目对话框

http://www.codeproject.com/com/CompleteActiveX/image004.jpg

图2.MFC ActiveX控件向导

·        CMyActiveXApp – 这个是ActiveX应用程序类,继承于COleControlModule。后者是驱动一个OLE控件的基础。控件模块对象包含了初始化(InitInstance)和清理(ExitInstance)的成员函数。

·        CMyActiveXCtrl – 由基类COleControl驱动。它提供了我们的控件的大部分功能。

·        CMyActiveXPropPage – 由基类COlePropertyPage驱动。它被用来管理控件的属性页对话框。ActiveX Control控件向导会建立一个默认的对话框为这个控件提供属性页。

加入对GIF动画的支持

为了让这个ActiveX控件支持显示一个GIF动画表现的进度条功能,我们将要使用CPictureEx类型,它是Oleg Bykov在CodeProject Article提供的。这里提供一些相关的细节。首先,把源码文件pictureex.cpp和pictureex.h加入到你的工程,在解决方案资源管理其中右键单机工程,选择添加现有项目,然后选择同文件和源文件,填交到代码树中。

为了添加一个GIF资源到项目中,我们必须面对Visual Studio 2005(以及vs2003)的一个问题,它不允许导入GIF图像各式的文件到资源中。如果你这么做了,你对得到一个错误警告,你需要通过下面的途径来绕过这个问题:

增加图形进程条对话框

现在,我们将要增加一个图形进程条对话框。

·        1.在资源视图中,右键单击对话框文件夹,选择插入dialog创建一个默认的对话框。

·        2.删除“确定”和“取消”两个不需要的按键,并且调整对话框尺寸到230 x 40。

·        3.改变对话框的其中一些属性:Border – None,Style – Child, System Menu – False, Visible –True.

·        4.改变控件ID到IDD_MAINDIALOG

·        5.插入一个图片控件(picture control)到对话框中来,选择Visual Studio最右边的工具箱,选择picture control,然后点击对话框。调整这个控件的尺寸到200 x 20。改变控件的ID到IDC_PROGRESSBAR,把Color属性设置为White。

·        6.为对话框创建一个类,右键单击对话框选择添加类。结果打开了MFC类向导如图3所示。把类名定义为CMainDialog,继承于CDialog。单击完成让想逃来创建这个类的默认源代码。

http://www.codeproject.com/com/CompleteActiveX/image006.jpg

图3.MFC类向导如图 – CMainDialog

现在我们可以向类中增加成员变量了。成员变量m_MainDialog是一个CMainDialog类型,m_ProgressBar是我们将要加入主对话框的进度条控件。

·        1.把变量m_MainDialog加入到类CMyActiveXCtrl中。选择类视图,右键单击CMyActiveXCtrl,选择添加,添加变量。输入变量类型CMainDialog以及变量名m_MainDialog,然后单击完成按键。

·        2.类似的,增加成员变量m_ProgressBar到类CMainDialog中。输入变量类型CPictureEx,变量名m_ProgressBar,并打开控件变量选项,然后确认控件ID为IDC_PROGRESSBAR,在单击完成按键之前,确认一下变量CPictureEx而不是被改成的CStatic。

http://www.codeproject.com/com/CompleteActiveX/image008.jpg

Figure 4. 添加成员变量向导– m_ProgressBar

增加支持代码

好了,现在我们需要卷起袖子写入一些代码了,用来绘制主对话框和进度条控件。

·        1.选择类CMyActiveXCtrl。在属性页中,选择消息图标,在WM_CREATE条目下选择<添加> OnCreate来添加处理WM_CREATE消息。向导将会帮助我们在类CMyActiveXCtrl中添加OnCreate方法来处理理WM_CREATE消息。

·        2.对MyActiveXCtrl.cpp文件进行编辑,并添加下面代码在OnCreate方法中用来创建除对话框:

m_MainDialog.Create(IDD_MAINDIALOG,this);

在OnDraw方法中增加下列代码来对主对话框窗口填入背景色:

m_MainDialog.MoveWindow(rcBounds,TRUE);

CBrushbrBackGnd(TranslateColor(AmbientBackColor()));

pdc->FillRect(rcBounds,&brBackGnd);

·        3.选择类型CMainDialog。在属性页中,选择消息图标,在WM_CREATE条目下选择<添加> OnCreate来添加处理WM_CREATE消息。向导将会帮助我们在类CMainDialog 中添加OnCreate方法来处理理WM_CREATE消息。

·        4.编辑MainDialog.cpp,并在OnCreate方法中增加下面代码用来创建进度条GIF动画:

if(m_ProgressBar.Load(MAKEINTRESOURCE(IDR_PROGRESSBAR),_T("GIF")))

m_ProgressBar.Draw();

确定当前编译模式为Release,并编译MyActiveX ActiveX应用程序。

为ActiveX控件创建网页

我们选择的用来快速创建测试网页的工具是微软的ActiveX ControlPad。你可以到微软去下载。

你也可以在其它的网站上面找到可用的下载链接,在你使用Visual Studio的系统上安装并运行这个工具。为了便于测试程序的效果,你还需要装上微软的IIS web服务器。

当你第一次运行ActiveX ControlPad,它会为你创建一个默认的HTML网页。为了插入ActiveX控件,右键单击HTML代码中<BODY>标签,然后选择ActiveX Control。在Insert ActiveXControl窗口中,选择在刚才用Visual Studio创建的MyActiveX Control,然后选择OK。

http://www.codeproject.com/com/CompleteActiveX/image010.jpg

图5. ActiveX ControlPad – Insert ActiveX Control

之后在ActiveX ControlPad中会显示两个矩形对话框,让你有机会修改你所选定的控件。属性对话框提供给你更改控件属性的方法,Edit ActiveXControl 对话框和意让你手工编辑这个控件。你可以关闭这两个窗口,我们之后会在HTML代码中更加细致的对其进行手动配置。你现在需要找到HTML代码中的OBJECT ID 标签,类似图6所示。把OBJECT ID标签里面的size参数改变到“WIDTH=350”和“HEIGHT=50”。然后储存HTML文件为myactivex.htm,并放置到IIS Web服务器的根文件夹中。

http://www.codeproject.com/com/CompleteActiveX/image012.jpg

图6. ActiveX ControlPad – MyActiveX ActiveX Control

开始测试ActiveX控件,在IE中载入网页http://localhost/myactivex.htm 。如果你得到了一些警告信息,只需要选择确定忽略它们。正确的结果是会在网页中显示一个GIF动画的进度条。如果没有,或者你在控件中得到了一个红色的X,那很可能是你对浏览器的安全设置把ActiveX下载或者运行给关闭了,这时候你应该打开IE的安全设置,把所有关于ActiveX的选项启用。

http://www.codeproject.com/com/CompleteActiveX/image014.jpg

图7. MyActiveX控件在IE中显示

接下来,我们需要构建ActiveX控件让其可以直接在IE浏览器中载入,而没有让然讨厌的错误信息。

构建一个已签名的ActiveX控件

为了构建一个已签名的ActiveX控件,你需要从某个机构购买一个签名代码证书,这些可以欠发证书的机构包括Thawte,Verisign,以及GeoTrust等。当你接受了这项服务的话,它们会帮助你验证程序不被篡改,并向你发放一个证书给你用来对你的ActiveX应用程序签名。我选择了Thawte提供的签名证书,它提供给你两个千名文件mycert.spc与mykey.pvk。

对ActiveX程序进行签名,我们需要把程序打包成CAB文件。让其可以从网页下载这个ActiveX控件并进行安装。在安装过程中包括了注册ActiveX组件的过程。为了实现这个功能,我们需要为ActiveX控件设置一个VERSIONINFO结构的OLESelfRegister值,在Visual Studio 2003中会帮助我们完成,而在VS2005中需要我们进行处理。我们需要编辑资源文件myactivex.rc加入下面OLESelfRegister值,如下:

VS_VERSION_INFOVERSIONINFO

FILEVERSION 1,0,0,1

PRODUCTVERSION 1,0,0,1

FILEFLAGSMASK 0x3fL

#ifdef _DEBUG

FILEFLAGS 0x1L

#else

FILEFLAGS 0x0L

#endif

FILEOS 0x4L

FILETYPE 0x2L

FILESUBTYPE 0x0L

BEGIN

BLOCK "StringFileInfo"

BEGIN

BLOCK "040904e4"

BEGIN

VALUE "CompanyName","TODO: <Company name>"

VALUE "FileDescription","TODO: <File description>"

VALUE "FileVersion","1.0.0.1"

VALUE "InternalName","MyActiveX.ocx"

VALUE "LegalCopyright",

"TODO: (c) <Companyname>. All rights reserved."

VALUE "OLESelfRegister","\0"

VALUE "OriginalFilename","MyActiveX.ocx"

VALUE "ProductName","TODO: <Product name>"

VALUE "ProductVersion","1.0.0.1"

END

END

BLOCK "VarFileInfo"

BEGIN

VALUE "Translation", 0x409,1252

END

END

在我们签名应用程序之前,ActiveX控件需要被打包成CAB文件。CAB文件中同时包含了一个INF文件被用来安装ActiveX 控件。为了构件CAB文件,你需要运行Cabinet SoftwareDevelopment Kit的cabarc.exe工具。下面提供了一个简单的INF文件例子,用来包装MyActiveX控件到CAB文件。你需要把CLSID行的值改成HTML文件中OBJECT ID标签所使用的值(之前用ActiveX Control Pad生成)。

[Add.Code]

myactivex.ocx=myactivex.ocx

myactivex.inf=myactivex.inf

[myactivex.ocx]

file=thiscab

clsid={36299202-09EF-4ABF-ADB9-47C599DBE778}

RegisterServer=yes

FileVersion=1,0,0,0

[myactivex.inf]

file=thiscab

建立CAB文件,向下面一样运行cabarc工具。 重要:确认在运行cabarc.exe时OCX和INF文件在相同的文件夹中,否则的话CAB文件从网页中下载之后会产生错误。这是一个导致警告的问题。

cabarc -s 6144 Nmyactivex.cab myactivex.ocx myactivex.inf

当对一个CAB文件进行签名的时候,你需要得到Microsoft MSDN上的signcode.exe工具。这里关系到“可信的签名和检查”将会在这个文章的后面提到。你使用signcode工具把从外面卖到的代码证书绑定到CAB文件中。下面是一个使用签名代码签名myactivex.cab文件的例子:

signcode -n"myactivex" -i

http://www.myactivex.com -spc mycert.spc -v mykey.pvk -t

http://timestamp.verisign.com/scripts/timstamp.dll myactivex.cab

在上面的例子中,http://www.myactivex.com 提供了这个给签名ActiveX控件提供更多用户信息的网页。

把这个CAB文件应用到网页中,首先拷贝myactivex.cab到你网页所在的文件夹,然后你必须修改网页中OBJECT ID标记中CODEBASE参数索引到你的CAB文件上来。参照图8的例子。如果你在IE中载入这个网页,它将会下载CAB文件并安装你的ActiveX控件,过程中并不会出现一个没有签名的警告。

http://www.codeproject.com/com/CompleteActiveX/image016.jpg

图8. ActiveX ControlPad – MyActiveX with CODEBASE

构建一个安全的ActiveX控件

如果希望再IE载入控件的时候不对控件不安全作出警告的信息的话,你必须保证执行代码使用安全的初始化和脚本的Active控件。相关的细节可以参照微软MSDN上的文章“Safe Initialization and Scripting for ActiveX Controls”。本文的后面会给出链接地址。不过我在这篇文章里面看到了大量的错误和冗长的文章。其实只需要在代码中加入DllRegisterServer和DllUnregisterServer这两个方法。下面我们就一步步指导你把ActiveX控件改成安全的:

编辑MyActiveX.cpp文件加入下面代码。在你的ActiveX控件中CLSID_SafeItem的值需要等于你在MyActiveXCtrl.cpp文件中的IMPLEMENT_OLECREATE_EX,同时,这个值也要和你在网页中的OBJECT ID标记CLSID值相同。

#include "comcat.h"

#include "strsafe.h"

#include "objsafe.h"

// CLSID_SafeItem - Necessary for safe ActiveXcontrol

// Id taken from IMPLEMENT_OLECREATE_EXfunction in xxxCtrl.cpp

const CATID CLSID_SafeItem =

{ 0x36299202, 0x9ef, 0x4abf,{ 0xad, 0xb9,0x47, 0xc5, 0x99, 0xdb, 0xe7, 0x78}};

// HRESULT CreateComponentCategory - Used toregister ActiveX control as safe

HRESULT CreateComponentCategory(CATID catid,WCHAR *catDescription)

{

ICatRegister *pcr = NULL ;

HRESULT hr = S_OK ;

hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,

NULL, CLSCTX_INPROC_SERVER,IID_ICatRegister, (void**)&pcr);

if (FAILED(hr))

return hr;

// Make sure the HKCR\ComponentCategories\{..catid...}

// key is registered.

CATEGORYINFO catinfo;

catinfo.catid = catid;

catinfo.lcid = 0x0409 ; // english

size_t len;

// Make sure the provided description isnot too long.

// Only copy the first 127 characters if itis.

// The second parameter of StringCchLengthis the maximum

// number of characters that may be readinto catDescription.

// There must be room for aNULL-terminator. The third parameter

// contains the number of charactersexcluding the NULL-terminator.

hr = StringCchLength(catDescription,STRSAFE_MAX_CCH, &len);

if (SUCCEEDED(hr))

{

if (len>127)

{

len = 127;

}

}

else

{

// TODO: Write an error handler;

}

// The second parameter of StringCchCopy is128 because you need

// room for a NULL-terminator.

hr = StringCchCopy(catinfo.szDescription,len + 1, catDescription);

// Make sure the description is nullterminated.

catinfo.szDescription[len + 1] = '\0';

hr = pcr->RegisterCategories(1,&catinfo);

pcr->Release();

return hr;

}

// HRESULTRegisterCLSIDInCategory -

//      Register your component categoriesinformation

HRESULTRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)

{

// Register yourcomponent categories information.

ICatRegister *pcr = NULL ;

HRESULT hr = S_OK ;

hr =CoCreateInstance(CLSID_StdComponentCategoriesMgr,

NULL, CLSCTX_INPROC_SERVER,IID_ICatRegister, (void**)&pcr);

if (SUCCEEDED(hr))

{

// Register this category as being"implemented" by the class.

CATID rgcatid[1] ;

rgcatid[0] = catid;

hr =pcr->RegisterClassImplCategories(clsid, 1, rgcatid);

}

if (pcr != NULL)

pcr->Release();

return hr;

}

// HRESULTUnRegisterCLSIDInCategory - Remove entries from the registry

HRESULTUnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)

{

ICatRegister *pcr = NULL ;

HRESULT hr = S_OK ;

hr =CoCreateInstance(CLSID_StdComponentCategoriesMgr,

NULL, CLSCTX_INPROC_SERVER,IID_ICatRegister, (void**)&pcr);

if (SUCCEEDED(hr))

{

// Unregister this category as being"implemented" by the class.

CATID rgcatid[1] ;

rgcatid[0] = catid;

hr = pcr->UnRegisterClassImplCategories(clsid,1, rgcatid);

}

if (pcr != NULL)

pcr->Release();

return hr;

}

改变DllRegisterServer方法:

STDAPIDllRegisterServer(void) {

HRESULT hr;    // HResult used by Safety Functions

AFX_MANAGE_STATE(_afxModuleAddrThis);

if(!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))

returnResultFromScode(SELFREG_E_TYPELIB);

if(!COleObjectFactoryEx::UpdateRegistryAll(TRUE))

return ResultFromScode(SELFREG_E_CLASS);

// Mark the control as safe forinitializing.

hr =CreateComponentCategory(CATID_SafeForInitializing,

L"Controls safely initializablefrom persistent data!");

if (FAILED(hr))

return hr;

hr =RegisterCLSIDInCategory(CLSID_SafeItem,

CATID_SafeForInitializing);

if (FAILED(hr))

return hr;

// Mark the control as safe for scripting.

hr =CreateComponentCategory(CATID_SafeForScripting,

L"Controls safely scriptable!");

if (FAILED(hr))

return hr;

hr =RegisterCLSIDInCategory(CLSID_SafeItem,

CATID_SafeForScripting);

if (FAILED(hr))

return hr;

return NOERROR;

}

修改DllUnregisterServer方法:

STDAPIDllUnregisterServer(void)

{

HRESULT hr;    // HResult used by Safety Functions

AFX_MANAGE_STATE(_afxModuleAddrThis);

if (!AfxOleUnregisterTypeLib(_tlid,_wVerMajor, _wVerMinor))

returnResultFromScode(SELFREG_E_TYPELIB);

if(!COleObjectFactoryEx::UpdateRegistryAll(FALSE))

return ResultFromScode(SELFREG_E_CLASS);

// Remove entries from the registry.

hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,

CATID_SafeForInitializing);

if (FAILED(hr))

return hr;

hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,

CATID_SafeForScripting);

if (FAILED(hr))

return hr;

return NOERROR;

}

ActiveX控件属性、方法以及事件

在ActiveX控件和网页之间传递消息需要通过属性、方法以及事件。为了便于展示这方面的技术,我们将要创建一个简单的网页,其中包含了简单的form元素,包括一个文本框与一个提交按键,文本通过一个输入参数属性被输入到ActiveX控件中。有一个控件方法把文本拷贝到输出参数属性上,然后激发一个事件把文本显示到网页中。我们需要做下列步骤:

http://www.codeproject.com/com/CompleteActiveX/image018.gif

图9. 添加属性向导

http://www.codeproject.com/com/CompleteActiveX/image020.jpg

Figure 10. 添加方法向导

http://www.codeproject.com/com/CompleteActiveX/image022.jpg

图11.添加事件向导

在上面的过程中,向导帮助我们创建了大多数的工作。我们只需要简单的添加几行代码来添加ActiveX控件拷贝文本和通知网页的事件。编辑文件MyActiveXCtrl.cpp,并且增加下面的代码来读入参数。

// Copy text fromthe input parameter to the output parameter

m_OutputParameter= m_InputParameter;

// Fire an eventto notify web page

FireParameterLoaded();

为了测试,下面使用ActiveX ControlPad工具来创建HTML代码:

<HTML>

<HEAD>

<TITLE>MyActiveX- Methods, Properties, and Events</TITLE>

<SCRIPTLANGUAGE="JavaScript">

functionPassParameter()

{

if (StringInput.value != "")

{

MyActiveX1.InputParameter =StringInput.value;

MyActiveX1.LoadParameter();

}

}

</SCRIPT>

</HEAD>

<BODY>

< CENTER>

MyActiveX -Methods, Properties, and Events Example

< P></P>

<OBJECTID="MyActiveX1" WIDTH=350 HEIGHT=50

CLASSID="CLSID:36299202-09EF-4ABF-ADB9-47C599DBE778">

<PARAM NAME="_Version"VALUE="65536">

<PARAM NAME="_ExtentX"VALUE="2646">

<PARAM NAME="_ExtentY"VALUE="1323">

<PARAM NAME="_StockProps"VALUE="0">

</OBJECT>

< p></p>

Input Parameter:<INPUT TYPE ="text" NAME="StringInput" VALUE="">

< p></p>

<INPUTTYPE="button" NAME="Submit"

VALUE="Submit"ONCLICK=PassParameter()>

<SCRIPTFOR=MyActiveX1 EVENT=ParameterLoaded()>

</SCRIPT>

< /center>

</BODY>

储存这些HTML代码到你的服务器上,并运行它。你将会看到一个网页显示一个进度条,并且拥有一个提交文本的form元素,其中包含一个文本输入框和一个提交按键。党提交后会显示一个新的页面,在其中显示“The parameter you entered is: ”,和你输入的文本。下面我们将会对网页HTML代码介绍一下概况。

当你按下提交,JavaScript脚本函数PassParameter将会被调用。在这个函数中在StringInput中的文本将会被拷贝到ActiveX控件的InputParameter属性中。接下来方法LoadParameter被调用,把InputParameter属性的值拷贝到OutputParameter中,最后调用FireParameterLoaded()来触发一个ActiveX事件。下面的HTML代码被用来处理这个事件。

<SCRIPTFOR=MyActiveX1 EVENT=ParameterLoaded()>

</SCRIPT>

ActiveX开发流程相关推荐

  1. 基于vlc的ActiveX流媒体播放器的二次开发流程

    在ActiveX中使用Dialog开发基于libvlc的流媒体播放器 一.  首先创建一个ActiveX工程,工程名假设为:MyActiveX   next,next,然后到下面界面,完成. 二. 创 ...

  2. 简述Web程序开发流程

    总体开发流程 分析需求, 列出功能清单或写需求说明书. 设计程序功能, 写功能规格书和技术规格书. 进入开发与测试的迭代. 调试和性能等专项测试. 部署上线 运维 前端开发流程 根据功能规格绘制页面草 ...

  3. 移动端开发者眼中的前端开发流程变迁与前后端分离

    写在最开始 这是一篇面向移动端开发者的科普性文章,从前端开发的最初流程开始,结合示范代码,讨论开发流程的演变过程,希望能覆盖一部分前端开发技术栈,从而对前端开发的相关概念形成初步的认识. 本文会提供一 ...

  4. node.js的开发流程_Node.js子流程:您需要了解的一切

    node.js的开发流程 by Samer Buna 通过Samer Buna Node.js子流程:您需要了解的一切 (Node.js Child Processes: Everything you ...

  5. 软件开发流程包含哪些内容

    2019独角兽企业重金招聘Python工程师标准>>> 能否开发出一个好的软件,关键是看软件开发前期所做的工作,重点是这个软件有没有一个好的 软件开发流程,因为一个好的软件开发流程关 ...

  6. TCP 网络应用程序开发流程

    TCP 网络应用程序开发流程 1. TCP 网络应用程序开发流程的介绍 TCP 网络应用程序开发分为: TCP 客户端程序开发 TCP 服务端程序开发 说明: 客户端程序是指运行在用户设备上的程序 , ...

  7. web开发流程 - 网上商城示例

    一.需求确定 1:通过各种手段确定系统的功能与性能    1)功能:注册.浏览.搜索...    2)性能:可同时支持n个并发访问,并且响应时间不低于m毫秒...    3)手段:头脑风暴(brain ...

  8. Leangoo阶段式硬件产品开发流程

    一.概述 本场景描述的是基于阶段式硬件研发流程以及在Leangoo中如何实现. 二.硬件产品开发流程 下图所示的是一个硬件产品开发大体上所需要经历的全部流程: 1)立项 在立项之前首先需要确定产品定位 ...

  9. 究竟什么样的开发流程是规范的?

    概述 有读者反馈,读了文章 一线技术管理者究竟在管什么事?收获满满,但还有点不过瘾,还想了解更细的东西... 这篇文章分享开发流程规范,目的是提高产品质量,优化开发流程,供大家参考. 规范是死的,人是 ...

  10. 敏捷开发流程的8个步骤

    一.敏捷开发流程的8个步骤包括: 1.目标制定,目标对齐:通过市场调研.业务思路.风险评估制定公司规划和目标,根据这一目标产生所有部门的目标并实现对齐: 2.产品规划:产品研发部门根据目标制定产品关键 ...

最新文章

  1. IJ-java-com-util-common:
  2. php 后退按钮事件,php – 后退按钮的会话问题
  3. Taro+react开发(90):列表渲染key值
  4. topcoder srm 699 div1 -3
  5. 中国科学院图书馆分类法
  6. DOS bat 的注释方法
  7. Print2Flash 3汉化破解版下载
  8. c++ socket下ipv4到ipv6的移植
  9. android webview下载附件几种方法
  10. Java程序员职业发展规划和方向有哪些?
  11. 智能人物画像综合分析系统——Day1
  12. 数学建模常用数据汇总!!!
  13. 新手建网站怎样在运营方面渐入佳境
  14. MAC下网易MuMu模拟器调试ReactNative
  15. CSS图片底部留白的解决办法
  16. spring cloud 快速上手系列 -> 02-配置中心 Config -> 022-Config客户端
  17. SVN Commit的时候提示Unexpected HTTP status 413 'Request Entity Too Large' on xxxx
  18. 更换网站字体详细教程附字体包
  19. 【MySQL】设置MySQL字符集
  20. activeMQ的原理及使用

热门文章

  1. iconfont 图标不显示
  2. uniapp 蓝牙连接条码枪/扫描枪 HID模式
  3. 【电场】基于模拟电荷法计算输电线路铁塔周围电场分布附matlab代码
  4. 机器学习笔记 - 什么是支持向量回归(SVR)?
  5. 矩阵求导法则与性质,机器学习必备~
  6. 移动开发用户行为分析神器之--AppSee!
  7. 第九届蓝桥杯快速排序java
  8. 一键解决Win10 LTSC 2021官方镜像存在的问题
  9. 90%人不知道的大厂面试流程和技巧
  10. android反编译apk命令,APK反编译关键命令及步骤