总爱唠叨几句(只关心技术的人可以跳过,^_^)
来北京前,在武汉做开发,那里全部用VC,并且采用比较传统的方法解决问题。渐渐的,我感觉到自己的知识体系很不完善,做事情总是想采取简洁通用完美的方案,然而认识有限总是无功而返,回到传统解决途径上去。那个地方没有人可以教我,可能由于大家专注不同。一个人苦心钻研技术,显得茕茕孑立,很多时候我都在怀疑为什么别人可以查阅到那么多资料,他们到底有什么秘诀?我看到我的研究生同学,他们都在公司做技术,应该很有朝气活力,敢于研究技术的。可是我为他们担心,他们逐渐沦为代码机器,不敢于改革自己现有的编程模式,把思维禁锢在一个很小的范围。我的一个同学给我发牢骚,说头又给他一个MIS项目维护代码,抱怨里面代码如何乱,风格如何糟糕,动不动就死机。他总问我某个控件实现特定功能怎么做,我很抱歉,因为有的我也不知道。我想起2年前的自己,热衷于驾驭控件的技巧,机器上的各类控件琳琅满目,每发现一个好控件,如获珍宝收藏起来,然而大多都没有派上用场。学习的过程让我明白一个道理:应该形成解决问题的方案,学会解决问题才是王道。
大三开的COM课程,我刚一接触,就深深爱上这个东西,当时几个班就我最用心学,可能大家觉得很难没有认真学。我想说的是要感谢COM,它应该是C++开发从编码到设计的转折点,给我最深的感觉就是它是一种框架行为。
来到北京,我的视野开阔很多,在一个技术远远超过自己的人的指点下,我如沐春风。我从一个不怕coding的人成长成一个不怕设计的人,自然心高气爽许多。
框架技术体系一直喜欢讲体系,学习技术,总是想把握住整个体系,有利有弊。利就是眼界开阔,增加底气;弊就是战线太长,自己很疲惫。非常赞成中国的中庸思想,对于我来说,COM就是中庸,上下开壑,开辟.NET和OLE学习之路。
Automation作为COM之前的一种老技术,翻译过来叫自动化。由于一开始接触的就是COM,习惯COM和MFC分离开发,因此一直没有很好理解Automation技术,只知道它集成在MFC应用中,以类型库方式提供服务。
昨天写完MFC和VBA集成后,突然感觉到MFC应用和VBE集成之间的牵连,能感觉到VBE就像一个提供Automation的Server。于是我花了一些事件研究Automation,不知为何,我总怀恋老技术,喜欢琢磨“过时”的东西。
总感叹Office系列软件,如此无缝集成,毫无疑问,它的模型是非常清晰的,框架架构出来的应该就是模型,这种架构技巧需要技术的积累。我曾经下决心学习设计模式,每每都沉不住气。当我深入学习MFC各种应用开发模型的时候,我明白了高人思维为何深邃,源于他们对MFC的深入探索。MFC在许多人眼里过时了,我谈过的很多技术也有人指出落后了,我喜欢深入研究MFC,因为它里面有许多思想值得学习。
Automation开发这里我以对话框应用程序讨论自动化,当然象office那样的大型软件在app,mainframe,doc层面上都有。
建立一个基于对话框的MFC应用程序,注意选择automation支持。简单来说实现了IDispatch接口的类支持自动化。
生成一个对话框类和一个对话框代理类,VBA里面也存在这种思想。一个C++类对象是死的,接口是活得,所以要是的应用灵活,就必须为对象配备一个组件对象,外界可以通过组件接口操纵C++对象。
Dlg类中有成员
CAutomationServerDlgAutoProxy* m_pAutoProxy; 代理类中有成员
CAutomationServerDlg* m_pDialog; 这个就称为“对偶”设计模式吧!
这个程序可以作为独立程序启动,也可以作为自动化服务启动。
为自动化接口添加属性,为自动化控制(客户程序)提供服务:
自动化属性实现:
BOOL CAutomationServerDlgAutoProxy::GetVisible()
{
// TODO: Add your property handler here
return (m_pDialog!=NULL && (m_pDialog->GetStyle()&WS_VISIBLE)!=0);
}
void CAutomationServerDlgAutoProxy::SetVisible(BOOL bNewValue)
{
// TODO: Add your property handler here
if(bNewValue = GetVisible())
{
return;
}
// visiable
if(bNewValue)
{
// embed start
if(m_pDialog == NULL)
{
if(AfxGetThread()->m_pMainWnd == NULL)
{
m_pDialog = new CAutomationServerDlg();
AfxGetThread()->m_pMainWnd = m_pDialog;
}
// show it
m_pDialog->ShowWindow(SW_SHOWNORMAL);
}
}
else
{
m_pDialog->ShowWindow(SW_HIDE);
}
}
BSTR CAutomationServerDlgAutoProxy::GetWindowText()
{
CString strResult;
// TODO: Add your property handler here
m_pDialog->GetWindowText(strResult);
return strResult.AllocSysString();
}
void CAutomationServerDlgAutoProxy::SetWindowText(LPCTSTR lpszNewValue)
{
// TODO: Add your property handler here
m_pDialog->SetWindowText(lpszNewValue);
} 自动化注册机制
在自动化代理类里面有这样一个宏声明:
IMPLEMENT_OLECREATE2(CAutomationServer2DlgAutoProxy, "AutomationServer2.Application", 0xaa98c00e, 0xd46f, 0x4e9e, 0xaf, 0x97, 0xc8, 0x24, 0xa0, 0x29, 0xe4, 0xa4)
看看
IMPLEMENT_OLECREATE2的定义:
#ifndef IMPLEMENT_OLECREATE2
#define IMPLEMENT_OLECREATE2(class_name, external_name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
AFX_DATADEF COleObjectFactory class_name::factory(class_name::guid, \
RUNTIME_CLASS(class_name), FALSE, _T(external_name)); \
const AFX_DATADEF GUID class_name::guid = \
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } };
#endif // IMPLEMENT_OLECREATE2
具体注册代码是:
COleObjectFactory::UpdateRegistryAll(); 但是这个函数似乎与上面的宏定义没有关系,为了找到关系我进入UpdateRegistryAll函数内部,发现:
for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
pFactory != NULL; pFactory = pFactory->m_pNextFactory)
{
if (!pFactory->UpdateRegistry(bRegister))
{
AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
return FALSE;
}
} 原来模块状态记录了所有类厂列表,为了找到类厂列表加入类厂位置,我搜索了mfc源码,发现OLEFACT.cpp里面有这样的代码:
COleObjectFactory::COleObjectFactory(REFCLSID clsid,
CRuntimeClass* pRuntimeClass, BOOL bMultiInstance, LPCTSTR lpszProgID)
{
ASSERT(pRuntimeClass == NULL ||
pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CCmdTarget)));
ASSERT(AfxIsValidAddress(&clsid, sizeof(CLSID), FALSE));
ASSERT(lpszProgID == NULL || AfxIsValidString(lpszProgID));
// initialize to unregistered state
m_dwRegister = 0; // not registered yet
m_bRegistered = FALSE;
m_clsid = clsid;
m_pRuntimeClass = pRuntimeClass;
m_bMultiInstance = bMultiInstance;
m_lpszProgID = lpszProgID;
m_bOAT = (BYTE) OAT_UNKNOWN;
// licensing information
m_bLicenseChecked = FALSE;
m_bLicenseValid = FALSE;
// add this factory to the list of factories
m_pNextFactory = NULL;
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
pModuleState->m_factoryList.AddHead(this);
AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
ASSERT_VALID(this);
} 原来类厂构造函数里面把自己加入到模块状态的列表里面。
现在总结一下:IMPLEMENT_OLECREATE2宏定义了一个类厂实例,在构造的时候加入模块状态的类厂列表,然后在模块初始化的时候,调用类厂的UpdateRegistry函数更新注册表,实现注册。
Automation调用下面生成一个客户程序控制AutomationServer,基于MFC对话框应用程序。
添加自动化程序产生的类型库:添加类->从类型库导入刚生成的tlb文件,向导会生成调用类。
创建自动化组件,显示自动化服务程序:
if(m_ias.CreateDispatch("AutomationServer.Application"))
{
m_ias.SetVisible(TRUE);
} 通过按钮事件设置服务器窗口标题,演示调用服务:
void CAutomationControlDlg::OnButtonSettext()
{
// TODO: Add your control notification handler code here
UpdateData();
if(m_ias.m_lpDispatch)
{
m_ias.SetWindowText(m_strText);
}
}
void CAutomationControlDlg::OnButtonGettext()
{
// TODO: Add your control notification handler code here
if(m_ias.m_lpDispatch)
{
m_strText = m_ias.GetWindowText();
UpdateData(FALSE);
}
} 下面是截图控制启动激活自动化服务程序:
调用自动化服务功能
代码下载
posted on 2006-08-31 20:33
万连文 阅读(4332)
评论(7) 编辑 收藏 引用 所属分类:
MFC