VC ActiveX 控件 开发总结
生活随笔
收集整理的這篇文章主要介紹了
VC ActiveX 控件 开发总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
VC 制作ActiveX 控件(OCX)
http://ileson.iteye.com/blog/10029101、vc6下建立一下activeX工程?
? ?詳見http://hi.baidu.com/mailrabbit/blog/item/0624a608bde798346b60fbb6.html
2、在頁面中調用?
? ?2.1:注冊ocx到系統(也可以這樣)?
Cmd代碼 ?收藏代碼
regsvr32 E:\ocx\test.ocx ?
? ?2.2找到classid?
? ? ? 有幾種方法:?
? ? ? ?①、VC--》菜單欄中的“工具”--》OEL/COM Object viewer--》Object Classes--》All Objects --》找到對應的OCX名稱,找到例如 如下值:clsid={96E5CC6E-18BD-43DA-B564-2EAB9F282C76}=XNPOS Control?
? ? ? ②、在注冊表里找,其實上面的工具,也是從注冊表里提取的。。。?
? cmd->regedit-> ?ctrl+f ?輸入你的ocx名稱?
? ? ? ?③、其實在工程文件里,有個odl文件。。最后一行的clsid 就是。。。?
? ?2.3頁面?
Html代碼 ?收藏代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ?
<html xmlns="http://www.w3.org/1999/xhtml"> ?
<head> ?
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> ?
<title>無標題文檔</title> ?
<script type="text/javascript" language="javascript"> ?
/** ?
?*測試OCX ?
?*/ ?
function testOCX(){ ?
? ? alert("進入"); ?
? ? var ocx=document.getElementById("pos"); ?
? ? alert(ocx); ?
? ? var t=ocx.test(1,2); ?
? ? alert(t); ?
} ?
</script> ?
</head> ?
??
<body> ?
<!--clsid : 如果控件成功注冊到本機后,這個值在本機注冊表中可以找到,js獲取控件對象就是通過這個來找的。--> ?
<OBJECT name="xn_pos" ID="pos" WIDTH="0" HEIGHT="0" CLASSID="CLSID:96E5CC6E-18BD-43DA-B564-2EAB9F282C76" codebase="xnpos.ocx"></OBJECT> ?
??
<input type="button" value="測試OCX" οnclick="testOCX();" /> ?
</body> ?
</html> ?
3、過程中遇到的一些問題 ??
? ?3.1、xxx.odl 中支持boolean; ?.cpp和.h中不支持boolean只能用BOOL;?
? ? ? ? xxx.odl 中不支持int 支持long .參數寫成int時 ctrl+w就不管用了,報?
? ? ? ? ? ?“Parsing ? error: ? "int" ? is ? not ? a ? valid ? OLE ? parameter ? type。”?
? ?3.2、接口函數都寫在 xxxCtl.cpp中?
? ? 3.3、VC設置編譯時活動的工程?
? ? ? ? ? 3.3.1>menu---Project---Settings(具體的項目,無參考價值,請讀者忽略!)?
?
? ? ? ? ? 3.3.2>menu---Build---Set Active Configuration?
?
? ?3.4、用regsvr32 注冊不到系統里報“找不到指定模塊”錯誤。?
分析:有可能控件有依賴的其它DLL文件沒有在系統System32下。?
解決辦法:用工具depends查看一下ocx 控件的依賴關系,其中有黃色標記的dll 就是該控件所需要的。將其放到system32下就可以了。(這個方法百試不爽,同樣可以解決瀏覽器有些可以加載有些加載不上去的問題)?
? ?今天發現:LoadLibrary("xxx.dll"); 返回NULL 也是這個問題。。。?
? ?3.5、解決ActiveX 工程無法用vc 調試的問題(更正:是有辦法的;各種調試)?
? ? ? ? 方法一:笨辦法 AfxMessageBox();(在適當的時候用,這個太費勁了,特別是大項目時)?
? ? ? ? 方法二:曲線救國 ;?
? ? ? ? ? ? ? ? ? ? ? ?·在一個工作空間中分別建ActiveX工程 和Dialog工程,用dialog ? ? ?工程來管理ActiveX工程。具體辦法 就是用dialog 工程來加載ActiveX工程下你自己寫的程序文件,然后編譯調試就OK?
? ? ? ? ? ? ? ? ? ? ? ?·在這期間遇到dialog中無法編譯源程序,提示找不到頭文件。解決方法如下: 1、Project -->Settings-->如下圖:?
點擊查看原始大小圖片
3.6、很多時候,在本機編寫ocx時,本機上的瀏覽器加載不到這個控件,今天終于發現如何解決了。?
其實不是找不到,是因為瀏覽器通過clsid 已經找到本機有自己制作的控件了,所以它就默認不再加載控件到瀏覽器控件的目錄了。如果這時候,你把vc工程清理一下,再通過瀏覽器訪問你的頁面時,就會加載你的控件。害我迷糊了好長時間,甚至要測試我還要換一臺機器。希望新手可以解惑!!!!?
3.7、頁面刷新,重復加載ocx對象幾次后,會將瀏覽器卡死。。。(還未找到解決辦法,哪位有解決思路,QQ:278952725)?
? ?經過大量的實驗,發現比較接近的可能是:?
3.7.1、資源占用未及時釋放。(如調用了第三方的dll,這個dll用調用了i/o 操作,何時釋放不受控制,so 出現崩潰)如操作外設,i/o資源沒有及時釋放(我遇到的一個例子是:我寫了兩個控件(功能是一樣的,調用同樣的硬件資源)分別加載到兩個頁面中,當點A頁面后,再點B頁面就會造成瀏覽器崩潰,甚至關閉!)。程序中一定要注意釋放i/o資源,及其它耗時的操作!?
3.7.2、程序問題。多線程造成的死鎖。?
3.8、因為現在有好多機器裝的是64位的操作系統(win7,win8),這時候老的32位動態庫,放到system32 下就不能被調用了。。?
? ? ?解決辦法:windows下有個 sysWOW ?目錄。。。把32位的dll 放到這里在。。。{我發現打成cab壓縮包后,在瀏覽器端 自動解壓時,也會自動解壓到 sysWOW64中!所以還是打包方便}?
DEPENDS.rar (134 KB)
========
VC++開發Activex控件以及簽名發布
http://arlon.iteye.com/blog/845775?
前言?
? ? ? 本人不懂C++,當前由于要做一個打印控件,使用Activex插件技術,所以在網絡上搜索了相關技術文檔,今天有空,遂將自己的當前學到的一些關于Activex技術整理之,進而和朋友們分享之。?
一、 開發環境?
開發工具:Visual Studio 2008?
開發語言:Visual C++
測試工具:IE 7+
二、 創建MFC ActiveX項目?
1、 打開VS2008新建MFC項目。這里我們取名為“PrintUtil”。
?
2、 輸入項目名稱為“PrintUtil”和項目位置。點擊“確定”按鈕,打開向導對話框。?
3、 選擇“控件設置”選項卡,具體設置可參考上圖。其它選項卡為默認設置。最后點擊“完成”按鈕保存設置。
?
三、 添加控件方法?
VC2005會為我們自動創建好MFC ActiveX程序框架,我們只要給該ActiveX控件添加方法即可。現在我們給控件添加一個“AddFun”方法,這個方法是將兩個數相加并返回結果。?
1、 點擊“視圖”,打開“類視圖”窗口。?
?
2、 展開“PrintUtilLib”項,選中“_DPrintUtil”項。點擊鼠標右鍵,選擇“添加”下的“添加方法”。?
3、 打開添加方法向導窗口。因為我們是添加一個加法方法,所以我們設置的返回類型為LONG型,方法名設為AddFun,添加兩個LONG類型參數Add1,Add2。?
4、 ? 其它為默認設置,點擊“完成”按鈕完成添加方法。接下來我們打開“解決方案資源管理器”打開“PrintUtilCtrl.cpp”文件。
5、 打開代碼視圖,我們會發現VC2005已經為我們添加了一個“AddFun”方法,我們在方法內添加“return Add1 + Add2;”語句。
四、 MFC Activex 安全問題?
1、在默認環境下,編譯的MFC Activex控件,只能在本地代碼中運行,即在http://localhost/xxx/xxx.htm中執行,而在http://127.0.0.1/xxx/xxx.htm中提示無相關屬性,需要設置其初始化和腳本運行的安全性?
ActiveX在遠程IE頁面上執行,需要實現安全接口。?
在ATL寫的ActiveX中,用IObjectSafety。?
http://support.microsoft.com/kb/168371/en-us?
在MFC寫的ActiveX中,直接修改注冊表。?
http://support.microsoft.com/kb/161873/en-us?
mfc實現的ocx,要在app實現文件中包括兩個文件:?
在PrintUtil.h文件中實現以下方法:
// PrintUtil.cpp : CPrintUtilApp 和DLL 注冊的實現。 ??
#include "stdafx.h" ??
#include "PrintUtil.h" ??
#include <objsafe.h> ??
??
#ifdef _DEBUG ??
#define new DEBUG_NEW ??
#endif ??
CPrintUtilApp theApp; ??
??
const GUID CDECL BASED_CODE _tlid = ??
{ 0x3C8F86CA, 0x6470, 0x4B7C, { 0xB2, 0x76, 0x3B, 0xEB, 0xF, 0xB0, 0x1B, 0x4E } }; ??
const WORD _wVerMajor = 1; ??
const WORD _wVerMinor = 0; ??
// CPrintUtilApp::InitInstance - DLL 初始化 ??
??
BOOL CPrintUtilApp::InitInstance() ??
{ ??
BOOL bInit = COleControlModule::InitInstance(); ??
??
if (bInit) ??
{ ??
// TODO: 在此添加您自己的模塊初始化代碼。 ??
} ??
??
return bInit; ??
} ??
// CPrintUtilApp::ExitInstance - DLL 終止 ??
??
int CPrintUtilApp::ExitInstance() ??
{ ??
// TODO: 在此添加您自己的模塊終止代碼。 ??
??
return COleControlModule::ExitInstance(); ??
} ??
??
// 創建組件種類 ? ??
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\Component Categories\{..catid...} ? ? ?
? ? // key is registered. ? ? ?
? ? CATEGORYINFO catinfo; ? ? ?
? ? catinfo.catid = catid; ? ? ?
? ? catinfo.lcid = 0x0409 ; // english ? ? ?
? ? // Make sure the provided description is not too long. ? ? ?
? ? // Only copy the first 127 characters if it is. ? ? ?
? ? int len = wcslen(catDescription); ? ? ?
? ? if (len>127) len = 127; ? ? ?
? ? wcsncpy(catinfo.szDescription, catDescription, len); ? ? ?
? ? // Make sure the description is null terminated. ? ? ?
? ? catinfo.szDescription[len] = '\0'; ? ? ?
? ? hr = pcr->RegisterCategories(1, &catinfo); ? ? ?
? ? pcr->Release(); ? ? ?
? ? return hr; ? ? ?
} ? ?
??
// 注冊組件種類 ? ??
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid) ??
{ ? ? ?
? ? // Register your component 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; ? ? ?
} ? ??
??
// 卸載組件種類 ? ??
HRESULT UnRegisterCLSIDInCategory(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 - 將項添加到系統注冊表 ??
STDAPI DllRegisterServer(void) ??
{ ? ? ?
? ? HRESULT hr; ? ? ?
? ? AFX_MANAGE_STATE(_afxModuleAddrThis); ? ? ?
? ? if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid)) ? ? ?
? ? ? ? return ResultFromScode(SELFREG_E_TYPELIB); ? ? ?
? ? if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE)) ? ? ?
? ? ? ? return ResultFromScode(SELFREG_E_CLASS); ? ? ?
? ? // 標記控件初始化安全. ? ? ?
? ? // 創建初始化安全組件種類 ? ??
? ? hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!"); ? ? ?
? ? if (FAILED(hr)) return hr; ? ? ?
? ? // 注冊初始化安全 ? ??
? ? hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing); ? ? ?
? ? if (FAILED(hr)) return hr; ? ? ?
? ? // 標記控件腳本安全 ? ??
? ? // 創建腳本安全組件種類 ? ??
? ? hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!"); ? ? ?
? ? if (FAILED(hr)) return hr; ? ? ?
? ? // 注冊腳本安全組件種類 ? ??
? ? hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting); ? ? ?
? ? if (FAILED(hr)) return hr; ? ? ?
? ? return NOERROR; ? ? ?
} ? ? ?
??
// DllUnregisterServer - Removes entries from the system registry ? ? ?
STDAPI DllUnregisterServer(void) ??
{ ? ? ?
? ? HRESULT hr; ? ? ?
? ? AFX_MANAGE_STATE(_afxModuleAddrThis); ? ? ?
? ? if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor)) ? ? ?
? ? ? ? return ResultFromScode(SELFREG_E_TYPELIB); ? ? ?
? ? if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE)) ? ? ?
? ? ? ? return ResultFromScode(SELFREG_E_CLASS); ? ? ?
? ? // 刪除控件初始化安全入口. ? ? ?
? ? hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing); ? ? ?
? ? if (FAILED(hr)) return hr; ? ? ?
? ? // 刪除控件腳本安全入口 ? ??
? ? hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting); ? ? ?
? ? if (FAILED(hr)) return hr; ? ? ?
? ? return NOERROR; ? ? ?
} ? ?
??
現在控件就可以在自注冊時就注冊為安全控件了。?
2、設置項目屬性 將配置類型設置成靜態庫(.lib)?
3、最后生成項目,ocx控件就產生了。?
五、 ActiveX發布步驟?
在這里簡單說明下,打包activeX需要制作證書,具體用到makecert 、cert2spc 、signtool 這三個VS提供的工具,工具在VS文件夾里面,以下制作過程需要在工具所在的文件夾下完成!?
1、單擊"開始"-->"運行(R)"-->輸入"cmd"-->回車-->進入到操作的控件所在的目錄(需要將上面所說的工具,和ocx控件放到一個文件夾下);
2、創建PVK文件(私人密匙文件),在命令行中輸入" makecert -sk PrintUtil PrintUtil.pvk -n CN=XXXXXXX公司",然后回車;?
sk-表示主題的密鑰容器位置,ss-主題的證書存儲名稱, n-證書頒發對象,r-證書存儲位置;?
3、創建CER文件(公司證書),在命令行中輸入" makecert -sk PrintUtil.pvk PrintUtil.cer ",然后回車,如圖所示,若出現"Successed"提示,則會在C:\ PrintUtil目錄下生成PrintUtil.cer文件;?
sk-表示主題的密鑰容器位置,is-頒發者的證書存儲名稱, n-證書頒發對象,ic-頒發者的證書存儲位置,-$-授權范圍(用于代碼簽名);
?
4、創建SPC測試軟件出版商證明書,在命令行中輸入" cert2spc PrintUtil.cer PrintUtil.spc ",然后回車;?
5、創建INF文件,用記錄本編輯以下信息:
Inf代碼 ?收藏代碼
[version] ??
signature="$CHINA$" ??
AdvancedINF=1.0 ??
??
[Add.Code] ??
PrintUtil.ocx=PrintUtil.ocx ??
??
[PrintUtil.ocx] ??
file=thiscab ??
clsid={ 1BABEDC3-3936-4850-B79B-2417E28A5655 } ??
FileVersion=1,0,0,0 ??
RegisterServer=yes ??
DestDir=11 ??
?
6、創建CAB文件,在命令行中輸入" cabarc -s 6144 n PrintUtil.cab PrintUtil.ocx PrintUtil.inf ",-s 選項表示在壓縮文件中保留用于代碼簽名的空間,n命令指定希望創建 CAB 文件,然后回車;?
7、使用Code Signing Wizard簽署一個CAB文件,首先雙擊運行工具集里面的signcode.exe(或在命令行里直接輸入“signcode”后回車),系統會彈出如圖所示的數字簽名向導;?
8、單擊"下一步(N)"按鈕,選擇要進行數字簽名的且已做成CAB包的文件PrintUtil.cab文件;?
9、選擇好CAB包后單擊"下一步(N)"按鈕,在選擇想要的簽名類型里選擇"自定義(C)"并單擊"下一步(N)"按鈕;?
10、點擊“從文件選擇”簽名證書 ( 公鑰文件 ),如: PrintUtil.cer :?
11、在圖20中單擊“下一步(N)”按鈕來到下圖,然后在圖里選擇“CSP中的私鑰(K)”。?
12、在上圖中單擊“下一步(N)”按鈕,然后在下圖中的散列算法中選擇“shal”,并單擊“下一步(N)”按鈕。?
13、在“證書路徑中的證書”中選擇“證書路徑中的所有證書,包括根證書(C)”,在“其它證書(可選)”中選擇“包括在以下PKCS #7 證書(.p7b)文件中的證書(P):”,并單擊“瀏覽(R)…”按鈕選擇PrintUtil.spc文件,選擇完后單擊“下一步(N)”按鈕:?
14、接下來在彈出的“數據描述”窗口中輸入公司的名稱和網址并單擊“下一步(N)”按:?
15、現大部份工作都已完成,在接下來的一步當中是可選的操作,其作用只是為CAB加入時間戳,此步驟完全可以不做。?
VeriSign: ?http://timestamp.verisign.com/scripts/timstamp.dll?
Comodo: ?http://timestamp.comodoca.com/authenticode?
GeoTrust/TrustCenter: http://www.trustcenter.de/codesigning/timestamp?
16、完成?
六、 運行?
編寫jsp頁面,test.jsp?
Html代碼 ?收藏代碼
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> ??
<% ??
String path = request.getContextPath(); ??
String basePath = request.getScheme() + "://" ??
+ request.getServerName() + ":" + request.getServerPort() ??
+ path + "/"; ??
%> ??
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> ??
<html> ??
<head> ??
<base href="<%=basePath%>"> ??
??
<title>My JSP 'index.jsp' starting page</title> ??
<meta http-equiv="pragma" content="no-cache"> ??
<meta http-equiv="cache-control" content="no-cache"> ??
<meta http-equiv="expires" content="0"> ??
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> ??
<meta http-equiv="description" content="This is my page"> ??
<object id="printUtil" ??
classid="clsid:1BABEDC3-3936-4850-B79B-2417E28A5655" ??
codebase="<%=basePath%>/PrintUtil.cab#version=1,0,0,0"></object> ??
<script type="text/javascript"> ??
? ? function add(arg1,args) { ??
? ? ? ? try { ??
? ? ? ? ? ? var v = printUtil.AddFun(arg1,args); ??
? ? ? ? ? ? alert(v); ??
? ? ? ? } catch (e) { ??
? ? ? ? ? ? alert(e.message) ??
? ? ? ? } ??
? ? } ??
? ? add(1,2); ??
</script> ??
</head> ??
<body> ??
</body> ??
</html> ?
??
運行結果:
本文所用到的工具見附件:
?
makeCAB.rar (188.6 KB)
========
VC6編寫ActiveX控件全過程
http://www.cnblogs.com/rushoooooo/archive/2011/06/22/2087547.html/*vc編寫Activex控件全過程*/
最近在自己的項目中使用了ActiveX控件。在這里就不介紹ActiveX控件的相關知識給大家掃盲了,我們直接進入編程。
1、新建控件工程
在新建項目時,選擇新建ActiveX控件,如下圖所示:
VC++下的ActiveX控件編程相關
其他的基本可以選擇默認屬性,然后我們就可以進入自己新建的工程了,如右下圖所示。方框中標出的是新建控件之后自帶的三個類。我做的控件只是使用了C***Ctrl這個類,主要是設置一些與外界進行數據通信的接口的屬性的,我自定義的幾個屬性都是在這里完成編程的。
2、為控件添加對話框
VC++下的ActiveX控件編程相關
這個控件的思想其實不是我的原創,只是項目的變化而產生的,而之前我是基于傳統的上位機軟件來編寫這個程序的,所以就選擇了向控件中加載對話框的方法。首先是設置對話框的ID,這里假設對話框的ID為IDD_XY_DLG,然后我們可以在C***Ctrl中的OnCreate() 函數中添加對話框的加載程序,具體的程序如下:
? ? int C***Ctrl::OnCreate(LPCREATESTRUCT lpCreateStruct)?
? ? {
? ? ?if (COleControl::OnCreate(lpCreateStruct) == -1)
? ? ?return -1;
? ? ?dlg.Create(IDD_XY_DLG,this);
? ? ?dlg.ShowWindow(SW_SHOW);
? ? ?return 0;
? ? }
對話框添加完之后,對對話框的操作與基于對話框的操作時完全一致的。所以這里沒有什么好講的。我自己的對話框的編寫也基本移植的之前自己編寫的上位機的程序。
3、為控件添加屬性
制作控件的一個重要原因就是要提高程序的通用性,而通用性的提高必須是控件能夠與第三方程序進行數據交換,這里的數據交換就是通過控件的屬性來完成的。現在我們來講一下添加屬性的步驟。View->ClassWizard->Automation后進入添加界面,如下圖所示:
VC++下的ActiveX控件編程相關
注意上圖中紅色直線標注的部分,我們是在C***Ctrl類下來進行屬性的添加,做為示范,我們用兩種方法分別添加兩個屬性。
(1)在上圖中點擊Add Property按鈕添加新的屬性名稱,如下圖所示。
VC++下的ActiveX控件編程相關
我們添加一個名字為xy0的float型屬性,這里需要注意的是最上面的External name上填寫的是控件屬性的外部名稱,就是第三方用戶在使用你的控件時看到的屬性名稱,而系統會自動為你生成一個Variable name名稱來關聯你添加的屬性的外部名稱。我們在控件內部編程時只需要調用內部變量就可以了。現在我們來使用Member variable屬性創建屬性,這種方式不需要自己編寫關聯,而是系統自己為你添加。一路點擊OK就可以完成屬性的添加,我們可以看到在C***Ctrl類上新增了與新添加的屬性相對應的程序,這個程序相當于屬性值發生改變的回調函數,具體的程序如下:
? ? void C***Ctrl::OnXy0Changed()
? ? {
? ? ?// 添加屬性值發生改變后需要控件進行的相應的操作
? ? ?SetModifiedFlag();
? ? ?}
(2)使用Get/Set methods屬性創建屬性。
使用這種方法添加的屬性,我們需要自己編寫獲取控件屬性函數和改變控件屬性程序。在我做的項目中,使用這種方法比較的多,我們以新建一個float型的C5屬性做為例子,添加屬性后,我們可以看到系統新增了兩個函數——GetSC5() 和SetC5() ,對應著獲取屬性的值和設置屬性的值,具體的程序如下:
? ? float C***Ctrl::GetSC5()?
? ?{
? ? // 獲取C5屬性相應的操作
? ? ? return f0.0; //返回屬性值
? ? }
? ? void C***Ctrl::SetC5(float newValue)
? ?{
? ? // 設置C5屬性相應的操作
? ? SetModifiedFlag();
? ? }
??
========
VC++編寫ActiveX控件
http://blog.csdn.net/waxgourd0/article/details/6637017前言:ocx是ocx控件的擴展名,OCX 是對象類別擴充組件。如果你用過Visual Basic或者Delphi一類的可視化編程工具,那么對控件這個概念一定不會陌生,就是那些工具條上的小按鈕,如EditBox,Grid,ImageBox,Timer等等。每個控件都有自己的事件、方法和屬性。使用了控件的編程非常容易。首先,在程序的設計階段可以設置一些屬性,如大小,位置,標題(caption)等等;在程序運行階段,可以更改這些屬性,還可以針對不同的事件,調用不同的方法來實現對該控件的控制。控件就好像一塊塊的積木,程序要做的事只是將這些積木搭起來。控件的最大好處是可以重復使用,甚至可以在不同的編程語言之間使用,例如你可以在VB中嵌入用VC開發的控件。
? ? ? ?那么下面開始詳細介紹如何生成你想要的“*.ocx”文件:
1、從最簡單的開始入手
? ? ? ?1.1 ?如何建立Ocx工程
? ? ? ?新建項目->MFC ActiveX WinZard
? ? ? ?在這里解決方案的名字我取名為SIP_OCX_DEMO,點擊“確定”,在出現的窗口中直接點擊“完成”。VC++會自動生成一些文件,這些文件就構成了ActiveX的基本模板,文件的主要結構如下:
? ? ? ?注意上面紅框標注的文件是非常重要的部分,直接編譯會在Debug目錄下生成一個名為“SIP_OCX_DEMO.ocx”的控件注冊文件,然后利用“regsvr32”命令就可以實現本機對此控件的注冊,就可以使用本語言或者跨語言編寫程序時引用此控件來實現相應的功能(當然現在沒有任何功能)。
? ? ? ?1.2 ?如何調試
? ? ? ?VC++6.0自帶有一個調試控件的工具“ActiveX控件測試容器”,通過三種方式可以打開:
1.點擊“調試”按鈕,然后瀏覽"C:\Program Files\Microsoft Visual Studio\Common\Tools\TSTCON32.EXE“;
2. 系統的“開始“-》“程序”-》“Microsoft Visual C++ 6.0”-》“Microsoft Visual C++ 6.0 Tools”-》“Active Control Test Container”;
3. VC++開發環境中的“工具”-》“ActiveX Control Test Container”。
? ? ? ?但是如果編譯環境是VS2005呢?VC6.0時代的第一種調試方法還是可行的,點擊調試按鈕,如下所示:
? ? ? ?在上面的可執行文件名稱的下拉框中有ActiveX Control Test Container的選項,選擇點確定即可。當然還有別的手段,后面會提到。用上面的方法調試出下面窗口:
? ? ? ?右擊空白區域,插入控件,然后會彈出下面的對話框:
? ? ? 選中指定控件,點擊確定,控件就被加載到此工具中,然后可以通過這個工具來看此控件的相關事件響應等等。
2、自定義方法和事件
1.點擊“視圖”,打開“類視圖”窗口;其中App類負責啟動初始化與結束時清理工作;Ctrl類是我們主要使用的;PropPage是屬性類。
注意紅框所示內容(以-lib結尾的文件)即為供第三方使用的借口和事件通知的接口的所在位置。
2.展開“ActiveXDemoLib”項,選中“_DActiveXDemo”項。點擊鼠標右鍵,選擇“添加”下的“添加方法”。
3.打開添加方法向導窗口。因為是添加一個無形參無返回值的測試方法,所以設置的返回類型為void,方法名設為test。
4.其它為默認設置,點擊“完成”按鈕完成添加方法。接下來我們打開“解決方案資源管理器”打開“SIP_OCX_DEMOCtrl.cpp”文件。
5. 打開代碼視圖,我們會發現VC2005已經為我們添加了一個“test”方法;
同時在.idl文件中會發現:
這里就是供第三方集成的接口列表。
3、自定義功能實現
? ? ? ?首先為了實現這個功能,我需要一個主對話框,當IE加載這個ActiveX時會把這個對話框圖顯示出來。在資源視圖中選擇Dialog右鍵點擊添加資源:
? ? ? ?然后會出現如下窗口:
? ? ? ?
? ? ? ?選擇新建,在生成的屬性窗口中將ID改為IDD_MAINDIALOG,同時把下面的幾種屬性設置一下:
Border :None
Style :Child
Visible :True
為了以后擴展的要求,加入了一個新的類“CMainDialog”類。操作:右鍵點一個這個對話框,然后選擇“添加類“:
? ? ? ?為了能夠在Ctrl類中使用這個對話框,在SIP_OCX_DEMOCtrl.h增加一個成員變量“m_MainDialog”。
? ? ? ?由于這個變量和對話框資源與關聯,在創建控件時需要把這個對話框也創建出來。這個操作要用消息來驅動。單擊SIP_OCX_DEMOCtrl,在其屬性窗口中的消息窗口中有一個消息叫WM_CREATE,可以讓VS2005創建一個函數OnCreate()。
? ? ? ?在這個函數體中,添加如下代碼,來創建這個對話框。
m_MainDialog.Create(IDD_MAINDIALOG, this); ?
? ? ? ?這里自定義的功能是SIP的一個簡單呼叫,這里不作詳細說明。
?4.控件的使用方法
? ? ? ?ocx控件的安裝方式有很多種,這里介紹最簡單的一種。
1、進入命令行;
2、進入Ocx生成目錄;
3、regsvr32.exe .ocx文件;
4、創建html文件調用本地Ocx;
由于是本地注冊,打開注冊表,開始 菜單 -》 運行 -》regedit -》用控件的名稱SIP_OCX_DEMO查找,可以找到
可以發現其classid 的值為BFE10FBC-C682-4423-8C6E-7A38219FA064,和SIP_OCX_DEMO.ocx 文件同一路徑下編輯一個 test.html文件,內容如下:
[html] view plain copy print?
<OBJECT id="SIP_OCX_DEMO" name="SIP_OCX_DEMO.ocx" ?
? ? ? classid="clsid:BFE10FBC-C682-4423-8C6E-7A38219FA064" ?
? ? ? width="100%" height="250"> ?
?
5、保存后用IE 瀏覽器打開選擇允許使用ActiveX 控件即可看到控件的面板;
在這里本文告一段落,關于更深入的事件和屬性,以及ocx控件的安全發布的內容會另起兩個章節詳細說明。
以下是關于ocx安全發布的博文,歡迎指正:
ocx控件MSI打包升級方案
OCX控件CAB打包手冊及升級方法
ActiveX控件實現安全的初始化和腳本
ActiveX控件屬性:自定義屬性的使用
========
VC++編寫ActiveX控件
http://www.cnblogs.com/beer/archive/2010/08/21/1805462.html前言:
? ? ?暑假在做一個項目的時候,本來是用C#.NET來寫的一個港口進出閘的流程控制程序,里面涉及一個響應用PLC的采集信息的問題(PLC用串口和工控機相連接),然后思考如何用C#寫串口通訊程序,結果師兄在一旁直接用VC++寫了一個“*.ocx控件”,并在自己的電腦上進行了測試,完工后就把生成的“*.ocx”控件注冊文件復制到了我們的電腦上。我們就在C#.NET程序里面將此控件拖入到主窗口中,然后就能直接利用此控件的事件來捕捉PLC的命令了,感覺好神奇。然后,我對C++的態度有了極大的轉變,以前只知道C++寫窗口程序是多么麻煩啊(遠不如C#.NET來得快和直接),而它的所謂“比較底層,和底層操作系統的關系比C#這些高級語言要密切很多”的好處一直都沒有體會到,現在才知道,正是因為C++比較底層,比較基礎,所以它可以開發出很多和語言無關的公用程序塊,如dll動態鏈接庫和COM組件,原則上,只要你的Windows的系統,用VC++開發出來的這些公用程序塊就能被任何語言調用(如果不用MFC框架,而用ATL框架來編寫,甚至還可以脫離Windwos系統,不僅僅實現跨語言,甚至跨平臺調用,這個筆者就沒有仔細研究了)。
? ? ?本人大學本科所學本來是電子技術的工業自動化,結果中途做的幾次項目都是“純軟件”,這次暑假的經歷,終于讓我在“硬件”和“軟件”之前找到一個連接交匯點了。
image
? ? ?以前做電子產品只是為了實現功能,現在發現這遠遠不夠,按照目前的時代潮流,一個系統除了要功能完備化,還要信息化 ,信息化就涉及到數據采集、存儲、分析和顯示。當然如果你不是做系統的,那么你也不必去用全局的眼光去看待這個問題,但你做了電子產品后,卻不能讓它的功能僅僅局限于在現場完成一些自動控制,而應該開發出和設備相關的上層API,供廣大的非電子專業的上層程序員進行二次開發,在PC上層平臺上對數據信息進行更好的組織和處理。而提供的API最好是具有較好的移植性,以適應不同企業的不同語言的程序員。而COM組件技術很好地解決了這個問題。
? ? 說到跨語言的模塊化程序設計,在本文之前發表的一篇《VC++的DLL應用(含Demo演示)》中講了dll的創建方法,用戶可以將一些公用函數放在dll源文件中,然后編譯生成一個dll文件,供程序動態加載連接并調用里面的函數,這個也可以跨語言地進行調用。但dll有自己的局限性,就是沒有事件,而這個時候ActiveX控件就隆重登場了,同樣能夠跨語言使用,ActiveX可以提供方法,屬性甚至是事件(當然對比dll也有缺點,它不是單獨的文件,無法動態加載和卸載)。
? ? ?因為筆者現在只是學習這個技術并作為一個技術積累,而沒有對這個技術進行原理上的深入研究,所以很多術語可能完全是錯誤的,希望高手看到后,不吝踢教和指正,也能防止本文誤認“子弟”了。本文中,作者是把ActiveX,COM,OCX當作相同的概念來對待的,可能不妥,請見識,如果想細究其具體的區別,請參考文章:
《Activex、OLE、COM、OCX、DLL之間有什么區別?》
http://fykyx521.javaeye.com/blog/446275
? ? 其實不管你是否了解它們之前的區別,都無所謂,因為本文只是講解如何從零開始學習并應用這門技術來解決實際問題,大家只需要知道實現步驟就OK了。
好,多的話不說了,下面開始介紹ActiveX這門技術的實現方式。
正文:
? ? ?ActiveX這門技術是通過生成“*.ocx”文件來實現的。先來了解下OCX文件,在百度百科上面對OCX是這樣解釋的:
? ? ?“.ocx是ocx控件的擴展名,OCX 是對象類別擴充組件。如果你用過Visual Basic或者Delphi一類的可視化編程工具,那么對控件這個概念一定不會陌生,就是那些工具條上的小按鈕,如EditBox,Grid,ImageBox,Timer等等。每個控件都有自己的事件、方法和屬性。使用了控件的編程非常容易。首先,在程序的設計階段可以設置一些屬性,如大小,位置,標題(caption)等等;在程序運行階段,可以更改這些屬性,還可以針對不同的事件,調用不同的方法來實現對該控件的控制。控件就好像一塊塊的積木,程序要做的事只是將這些積木搭起來。控件的最大好處是可以重復使用,甚至可以在不同的編程語言之間使用,例如你可以在VB中嵌入用VC開發的控件。”
? ? ?里面最后一句話比較重要,就是用VC開發的OCX控件,你可以在其它語言里面都能調用,這樣很好的實現了功能化組件的良好循環使用,而且還可以實現跨語言地調用(例如,你完全可以用C#調用C++開發的OCX控件)。
? ? ?下面開始介紹,如何用VC++一步步生成你想要的“*.ocx”文件。
1. 建立最簡單的ocx文件并進行調試
1.1 建立最簡單的ocx文件
? ? VC->新建項目->MFC ActiveX WinZard
clip_image004
? ? ?一路點擊“確定”,直到點擊“完成”。最后VC++會自動生成一些文件,這些文件就構成了ActiveX的基本模板,文件的主要結構如下:
clip_image006
? ? 直接編譯一下,然后在Debug目錄下面就會生成一個名為“ocxDemo.ocx”的控件注冊文件,然后利用“regsvr32”命令就可以實現本機對此控件的注冊,然后就可以使用本語言或者跨語言編寫程序時引用此控件來實現相應的功能(后面將會講到)。
1.2 ocx調試方法:
? ? VC++自帶有一個調試控件的工具“ActiveX控件測試容器”,通過三種方式可以打開:
1.點擊“調試”按鈕,會出現如下對話框:
clip_image008
? ? ?然后瀏覽"C:\Program Files\Microsoft Visual Studio\Common\Tools\TSTCON32.EXE“
2. 系統的“開始“-》“程序”-》“Microsoft Visual C++ 6.0”-》“Microsoft Visual C++ 6.0 Tools”-》“Active Control Test Container”
3. VC++開發環境中的“工具”-》“ActiveX Control Test Container”
? ? ?通過上面的任意一種方法,都可以調出下面的程序:
clip_image010
? ? ?右擊空白區域,插入控件,然后會彈出下面的對話框:
clip_image012
? ? ?選中指定控件,然后點擊確定,控件就被加載到此工具中了,然后可以通過這個工具來看此控件的相關事件響應等等。
clip_image014
2.自VC++生成的模板基礎上自定義功能
? ? ?所有的自定義功能基本上都來自于“MFC ClassWizard”類向導對話框。
? ? (“快捷鍵Ctrl+W”或者“查看”->“建立類向導…”)
clip_image016
? ? ?在“Automation”選項卡中為控件添加方法和屬性。
? ? ?在“ActiveX Events”選項卡中為控件添加事件。
2.1 添加控件屬性
? ? ?切換到“Automation”選項卡中,點擊右邊的“Add Property…”會彈出對話框:
clip_image018
External name:外部名稱。指此控件被使用時,外部程序看到的屬性名稱,僅在外部引用時被使用。
Type:屬性類型。除了基本的整形等數據類型外,還有很多復雜的高級數據類型。
Variable name:變量名稱。此屬性在控件源文件中的變量名稱,在編寫控件源碼時使用。
Notification function:提醒函數。當此屬性被改變時,會觸發此提醒函數。
Implementation:實現方式。指屬性的三種類型:固有型,成員變量型,Get/Set方法型。固有型是指系統賦予的固有屬性,如背景色,標題;成員變量型是用戶自定義的屬性;Get/Set方法型,可能是指只能通過Get/Set方法才能獲取和改變的變量吧(這個沒研究)。
2.2 添加控件方法
? ? ?在“Automation”選項卡中,點擊右邊的“Add Method…”會彈出對話框:
clip_image020
External name:方法外部名稱。
Internal name:方法內部名稱。
Return type:返回值類型。除了基本的整形等數據類型外,還有很多復雜的高級數據類型。
Implementation:實現方式。兩種:固有方法,自定義方法。
Parameter list:參數列表。參數名稱和參數類型:參數類型包含很多高級數據類型。
2.3 添加控件事件
? ? ?切換到“ActiveX Events”選項卡中,點擊右邊的“Add Event…”會彈出對話框:
clip_image022
External name:事件外部名稱。
Internal name:事件內部名稱。比外部名稱多了個前綴“Fire”。
Implementation:實現方式。兩種:固有事件,自定義事件。固有事件一般是鼠標移動,雙擊等等事件,這些事件都由系統消息觸發;自定義事件則是完全由用戶定義的一個函數,但這個函數需要用戶在源文件中調用(在內部調用,對于控件的使用方來說,就相當于在調用的地方此事件被觸發,而內部傳入的參數,則是此事件產生的消息附帶信息)。
Parameter list:參數列表。參數名稱和參數類型:參數類型包含很多高級數據類型。
? ? ?總述:通過“類向導”工具,為控件添加屬性、方法和事件后,VC++會自動在相應的文件里面生成代碼,比如內部方法屬性和外部方法屬性之間的映射,消息的建立,消息的聲明,等等。如果用戶要對引進行深入研究,還需要對程序的結構比較熟悉,知道各部分代碼的作用,知道哪些地方的代碼是系統自動生成的,哪些代碼需要用戶手動加入的。Visual C++開發環境雖然有很多優點,但有個缺點也很明顯,就是代碼結構比較亂,感覺沒有VS2005和后面的Visual Studio系列要好。但是由于VC6.0作為一個比較經典的開發環境,而且網上的有關C++的程序設計基本上都是基于VC6.0的,所以,有必要對其進行學習,便于自己讀懂網上的代碼并進行消化吸收。
?
2.4 生成ocx文件并調試
? ? ?直接編譯用戶加入了自定義代碼的項目,然后在項目的Debug目錄下面會生成一個ocx文件,這個就是此控件的注冊文件了。
? ? ?控件的調試工具仍然是“ActiveX Control Test Container”。
? ? ?假設我們在控件中加入了一個事件:固有事件——“MouseMove”鼠標移動事件;用戶自定義事件——ocxClick事件(此事件是通過“WM_MOUSEMOVE”消息來觸發的,返回的是鼠標當前位置的x坐標)。
? ? ?運行“ActiveX Control Test Container”并插入當前控件,當鼠標在上面移動的時候,可以看到MouseMove產生了事件了。
clip_image024
? ? ?同時可以通過“Control”-》“Invoke Method”來對控件的方法進行測試,測試的方法就是你輸入參數,它返回計算結果(下面以自定義的方法funHello為例)。
clip_image026
3.控件的使用方法
3.1 注冊控件
? ? ?ocx控件的安裝方式有很多種,這里介紹最簡單的一種。
步驟:
1.將需要安裝的OCX控件文件復制到某個目錄,例如C盤根目錄下。
2.進入開始,點擊運行。
3.在出現的框中鍵入regsvr32 C:/xxxx.ocx 。(XXXX為控件名, C:/為目錄)
4.點擊確認后等待出現提醒注冊成功即可。
3.2 ActiveX控件的調用
? ? ?ActiveX作為一種通用的COM組件,可以被不同語言調用的。
3.2.1 通過VC++調用
? ? ?利用VC6.0建立一個MFC的基本對話框應用程序
clip_image028
? ? ?在完成程序向導后。執行下面的步驟:
1. 執行“工程”-》“添加到工程”--》“Components and Controls…”。
2. 在彈出的文件瀏覽對話框中,找到Registered ActiveX Controls文件目錄下的你剛才注冊的控件,比如“OcxDemo Control”,然后點擊“Insert”按鈕即可將此控件添加到控件工具條集合中。
3. 將控件工具條上新增加的OCX控件拖入到應用程序主窗口中。
完成上面的步驟后,就可以像使用普通控件一樣在VC中使用此控件了(右擊此控件,可以查看此控件的“事件”和“屬性”,就是你在編寫控件源碼時的那些“外部名稱External name”)。
3.2.2 通過C#調用
? ? ?其實這個才是重點,因為跨語言調用ActiveX技術最被筆者看好的地方。
? ? ?用Visual Studio 2005新建一個C#.NET的Windows窗口程序,然后在工具箱面板上,右擊“選擇項”,選擇COM組件,找到你注冊的ActiveX控件:
clip_image030
? ? ?確定后,那個OcxDemo Control控件就加載到工具箱里面了。可以直接拖動這個控件到C#.NET應用程序的主窗口上去了,然后就像使用普通控件那樣使用此控件了。
? ? ?比如,本文中的ActiveX控件的自定義事件中,是通過鼠標移動來觸發,那么在應用程序中,只要鼠標移動到控件上,那么就會觸發此自定義事件,并獲取當前鼠標位置的橫坐標。
4. 最后一些Tip
1) 在自定義控件時,可在控件源碼的OnDraw()函數中設置控件的外觀(也就是控件被拖入到應用程序中時呈現的樣子,一般默認是一個白色的方框內切橢圓的樣式)。
2) 用C#來使用ActiveX的事件時,事件所產生的數據都包含在Event變量中,只需要用個點運算符就可以取出來了。
5.展望
控件函數的返回值類型那么多,那么復雜,如果要用得好,還需要對那些OLE數據類型進行好好學習。
======== 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的VC ActiveX 控件 开发总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图解VC++6.0和ACE 5.4 开发
- 下一篇: opencv图像处理常用完整示例代码总结