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_I4;
PropDispDriver.InvokeHelper(dwDispID, DISPATCH_PROPERTYGET, VT_BSTR, &str, rgbParams, lItem);
PropDispDriver.DetachDispatch(); } }
return str; }
COLORREF CToppPropPage::GetColor() {
long l = 0;
GetPropText(\ COLORREF cr = RGB(0, 0, 0);
::OleTranslateColor((OLE_COLOR)l, NULL, &cr); return cr; }
void CToppPropPage::SetColor(COLORREF cr) {
SetPropText(\}
long CToppPropPage::GetCount() {
long lcount = 0;
GetPropText(\ return lcount; }
4.添加按钮(\添加项目\响应函数
void CToppPropPage::OnButtonAdditem() {
// TODO: Add your control notification handler code here UpdateData();
AddItem(m_strItem); //m_strItem为编辑框关联的CString对象 //填充列表框 long lcount = 0;
GetPropText(\
m_list.ResetContent(); //m_list为列表框关联的CListBox对象 for(int i=0; i m_list.AddString(GetItem(i)); } } 5.添加按钮(\设置颜色\响应函数来设置控件的Color属性 void CToppPropPage::OnButtonSetcolor() { // TODO: Add your control notification handler code here CColorDialog dlg; if(dlg.DoModal() == IDOK){ long lcolor = dlg.GetColor(); SetPropText(\ GetDlgItem(IDC_STATIC_COLOR)->Invalidate(); } } 6.添加WM_CTLCOLOR消息响应函数,在函数里获得控件的Color属性,并用该Color设置静态文本框的文本背景颜色 HBRUSH CToppPropPage::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = COlePropertyPage::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: Change any attributes of the DC here if(nCtlColor == CTLCOLOR_STATIC){ COLORREF cr = GetColor(); pDC->SetBkColor(cr); } // TODO: Return a different brush if the default is not desired return hbr; } 7.OK了,编译,可以在ActiveX Control Container中测试了 在上一步中我们实际是通过IDispatch接口的Invoke方法来访问控件的属性和方法的,虽然有COleDispatchDriver和其它一些辅助函数,但还是有些繁杂,能不能直接得到控件对象的指针,这样就可以直接访问控件了,甚至于控件的内部变量了?答案是肯定了。 我们的控件派生自COleControl,COleControl派生自CWnd,CWnd又派生自CCmdTarget,我们的 IDispatch接口就是在CCmdTarget中实现的(其实应该是实现在COleDispatchImpl类中),实现的方法比较特殊,这里不细细分析了,有兴趣的朋友可以自己看看MFC源码或者网上搜搜资料,应该能知道的。 我们能从CCmdTarget中获得IDispatch接口指针 (GetIDispatch函数),同样的,我们也能从IDispatch接口指针中反向导出CCmdTarget对象指针,用到的是 CCmdTarget的静态成员函数 static CCmdTarget* FromIDispatch( LPDISPATCH lpDispatch ); 前面我们已经知道可以通过属性页的GetObjectArray来获得控件的IDispatch接口指针,而有了上面的FromIDispatch这个函数,我们又可以从IDispatch接口指针中来获得控件的指针了,那么问题就解决了。 另外,这里我们还用到COlePropertyPage的一个虚拟函数OnObjectsChanged,在控件变化(包括控件加载上和卸载掉时)时,都会调用到这个函数。(其实,并不是一定要用这个函数的,只是想介绍一下,就用上了) 还是用上一步中的例子topp 1.添加控件类指针为属性页类的成员变量(#include \,应该不用说的吧) CToppCtrl* m_pctrl; 2.添加获得控件类指针的函数CToppCtrl* GetCtrlPtr(); CToppCtrl* CToppPropPage::GetCtrlPtr() { ULONG ulObjects; LPDISPATCH* lpObjectArray = GetObjectArray( &ulObjects ); ASSERT( lpObjectArray != NULL ); LPDISPATCH lpdisp = NULL; if(ulObjects > 0){//在这个函数中,并不一定能保证就有控件. lpdisp = lpObjectArray[0];//这里省事了,就假设只有一个控件了 } CToppCtrl* pctrl = NULL; if(lpdisp){ pctrl = (CToppCtrl*)CCmdTarget::FromIDispatch(lpdisp); } return pctrl; } 3.重载OnObjectsChanged,设置m_pctrl(在其它地方,如OnInitDialog中设置也无所谓,甚至即用即获得也无所谓) void CToppPropPage::OnObjectsChanged() { ULONG ulObjects; LPDISPATCH* lpObjectArray = GetObjectArray( &ulObjects ); ASSERT( lpObjectArray != NULL ); LPDISPATCH lpctl = NULL; if(ulObjects > 0){//在这个函数中,并不一定能保证就有控件. lpctl = lpObjectArray[0];//这里省事了,就假设只有一个控件了 } if(lpctl){ m_pctrl = (CToppCtrl*)CCmdTarget::FromIDispatch(lpctl); } else{ m_pctrl = NULL; } } 3.修改上一步中的几个成员函数 BOOL CToppPropPage::AddItem(LPCTSTR lpszItem) { if(m_pctrl) m_pctrl->m_saItems.Add(lpszItem); return m_pctrl != NULL; } CString CToppPropPage::GetItem(long lItem) { if(m_pctrl) { if(lItem >= 0 && lItem < m_pctrl->m_saItems.GetSize()){ return m_pctrl->m_saItems[lItem]; } else{ return _T(\ } } else{ return _T(\ } } //在获得m_color时,是直接将m_color从protected拉到了public下的,可恶的MFC,再添加新的属性或方法时可能会重新再添加一个,会给你带来一个小小的麻烦。 COLORREF CToppPropPage::GetColor() { if(m_pctrl) return m_pctrl->TranslateColor(m_pctrl->m_color); return RGB(0, 0, 0); } void CToppPropPage::SetColor(COLORREF cr) { if(m_pctrl) m_pctrl->m_color = cr; } long CToppPropPage::GetCount() {
相关推荐: