ActiveX控件的MFC设计之旅

发布时间 : 星期四 文章ActiveX控件的MFC设计之旅更新完毕开始阅读

m_hMyWnd = pwnd->Create();

//建立工作线程 DWORD dwID;

CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MyThread, this, NULL, &dwID); }

6.定义Trigger方法

void CTFireCtrl::Trigger(LPCTSTR strParam) {

// TODO: Add your dispatch handler code here m_strParam = strParam; if(m_hEvent){

SetEvent(m_hEvent); } }

7.定义End方法 void CTFireCtrl::End() {

// TODO: Add your dispatch handler code here m_bEnd = TRUE; Sleep(100);

CloseHandle(m_hEvent); m_hEvent = NULL;

::DestroyWindow(m_hMyWnd); }

8.应该是可以了,编译一下,开始VB工程

在VB的Form1中加一控件TFire1,一按钮Command1 代码如下:

Private Sub Command1_Click() TFire1.Trigger \End Sub

Private Sub Form_Load() TFire1.Start End Sub

Private Sub Form_Unload(Cancel As Integer) TFire1.End End Sub

Private Sub TFire1_ThreadEvent(ByVal strEvent As String) MsgBox strEvent End Sub

调试运行,就可以了

关于属性页,这里先翻译msdn上一段关于属性页的介绍。 用户通过属性页来操作控件的属性,用户可以设置一个或多个属性页,每个属性页上可以显示控件的某些属性。这些属性既可以来自一个控件,也可以来自多个控件,也就是说一个属性页上可以显示多个控件的属性。

每个ActiveX 控件属性页都是一个进程内对象,拥有它自己的CLSID,每个属性页均实现了IPropertyPage接口。 IPropertyPage::SetObjects是用来将控件对象的接口指针(IUnknown)传递给属性页的。

MFC的 COlePropertyPage也实现了IPropertyPage接口,它将控件对象指针的保存在一个IDispatch接口指针的数组中。该数组可以通过COlePropertyPage::GetObjectArray()访问,这样就可以通过IDispatch接口来访问控件的属性了,令人头疼的是通过IDispatch来访问控件属性,实在有够麻烦,MFC提供了COleDispatchDriver来帮助访问,可惜,也仅仅是能稍微简化一些操作而已。其实,MFC为了自己方便,在COlePropertyPage还提供了一组函数来帮助访问控件的属性,只不过这组函数没公布在msdn中罢了,下面是这组函数的声明: // DDP_ property get/set helper routines

BOOL SetPropText(LPCTSTR pszPropName, BYTE &Value); BOOL GetPropText(LPCTSTR pszPropName, BYTE* pValue); BOOL SetPropText(LPCTSTR pszPropName, short &Value); BOOL GetPropText(LPCTSTR pszPropName, short* pValue); BOOL SetPropText(LPCTSTR pszPropName, int &Value); BOOL GetPropText(LPCTSTR pszPropName, int* pValue); BOOL SetPropText(LPCTSTR pszPropName, UINT &Value); BOOL GetPropText(LPCTSTR pszPropName, UINT* pValue); BOOL SetPropText(LPCTSTR pszPropName, long &Value); BOOL GetPropText(LPCTSTR pszPropName, long* pValue); BOOL SetPropText(LPCTSTR pszPropName, DWORD &Value); BOOL GetPropText(LPCTSTR pszPropName, DWORD* pValue); BOOL SetPropText(LPCTSTR pszPropName, CString &Value); BOOL GetPropText(LPCTSTR pszPropName, CString* pValue); BOOL SetPropText(LPCTSTR pszPropName, float &Value); BOOL GetPropText(LPCTSTR pszPropName, float* pValue); BOOL SetPropText(LPCTSTR pszPropName, double &Value); BOOL GetPropText(LPCTSTR pszPropName, double* pValue); BOOL SetPropCheck(LPCTSTR pszPropName, int Value); BOOL GetPropCheck(LPCTSTR pszPropName, int* pValue); BOOL SetPropRadio(LPCTSTR pszPropName, int Value); BOOL GetPropRadio(LPCTSTR pszPropName, int* pValue); BOOL SetPropIndex(LPCTSTR pszPropName, int Value); BOOL GetPropIndex(LPCTSTR pszPropName, int* pValue);

在一般情况下,我们并不用直接访问控件的属性,一切都由框架帮助做了(框架利用了DoDateExchange,DoDataExchange 又用了上面的SetPropText/GetPropText函数组)。

但是,有时候,我们希望能在控件中直接访问控件的属性和方法。对于普通属性,使用上面的GetPropText和SetPropText足以满足需要,但是对于带参数的属性和方法,就只好老老实实的用 COleDispatchDriver来InvokeHelper了。 下面是在属性页中访问控件属性和方法的例子toop.

1.控件中设置了一个字符串数组CStringArray m_saItems,提供了方法long Add(LPCTSTR strItem)和get/set method属性BSTR Item(long lItem)来访问数组中的某项字符串,另外还有一个只读属性long Count(在添加属性的向导中,设置为get/set methods类型的属性,并去掉SetCount即是设置为只读属性了)

2.控件另外设置了一member variable属性OLE_COLOR Color

3.属性和方法的实现如下:

void CToppCtrl::OnColorChanged() {

// TODO: Add notification handler code SetModifiedFlag(); }

long CToppCtrl::Add(LPCTSTR strItem) {

// TODO: Add your dispatch handler code here return m_saItems.Add(strItem); return 0; }

BSTR CToppCtrl::GetItem(long nItem) {

CString strResult;

// TODO: Add your property handler here

if(nItem >= 0 && nItem < m_saItems.GetSize()){ strResult = m_saItems[nItem]; }

return strResult.AllocSysString(); }

void CToppCtrl::SetItem(long nItem, LPCTSTR lpszNewValue) {

// TODO: Add your property handler here

if(nItem >= 0 && nItem < m_saItems.GetSize()){ m_saItems[nItem] = lpszNewValue; }

SetModifiedFlag(); }

long CToppCtrl::GetCount() {

// TODO: Add your property handler here return m_saItems.GetSize(); return 0; }

控件编完后,就是属性页这个重头戏了:

1.界面,对于控件中字符串数组,添加了一编辑框和一按钮(\添加项目\来调用控件的Add方法;添加了一列表框来调用控件的Item属性填充列表框。

2.界面,对于控件的Color属性,添加了一按钮(\设置颜色\和一静态文本框 (Caption为\看看我的颜色吧\,ID为IDC_STATIC_COLOR)来设置颜色和获得颜色属性,文本框的文本背景颜色即为获得的颜色。

3. 添加成员函数BOOL AddItem(LPCTSTR lpszItem)用来调用控件的Add方法添加字符串,添加CString GetItem(long lItem)函数来获得字符串数组中的lItem项对应的字符串,添加long GetCount()来获得数组中字符串的数目;添加COLORREF GetColor()函数来获得控件的Color属性,添加SetColor()函数来设置控件的Color属性,这些函数的实现如下:

BOOL CToppPropPage::AddItem(LPCTSTR lpszItem) {

USES_CONVERSION;

COleDispatchDriver PropDispDriver; BOOL bResult = FALSE; ULONG nObjects = 0;

LPDISPATCH* ppDisp = GetObjectArray(&nObjects); for (ULONG i = 0; i < nObjects; i++) {

DISPID dwDispID;

LPCOLESTR lpOleStr = T2COLE(\

if (SUCCEEDED(ppDisp->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID))) {

PropDispDriver.AttachDispatch(ppDisp, FALSE); BYTE rgbParams[] = VTS_BSTR; long lret = 0;

PropDispDriver.InvokeHelper(dwDispID, DISPATCH_METHOD, VT_I4, &lret, rgbParams, lpszItem);

PropDispDriver.DetachDispatch(); bResult = TRUE; } }

return bResult; }

CString CToppPropPage::GetItem(long lItem) {

CString str = _T(\ USES_CONVERSION;

COleDispatchDriver PropDispDriver; ULONG nObjects = 0;

联系合同范文客服:xxxxx#qq.com(#替换为@)