万星星@豌豆荚 欢迎加入我们
一个吃软饭的男人!!!!!我只想写程序####
微博:http://weibo.com/wanlianwen
posts - 172,  comments - 1253,  trackbacks - 0
总爱唠叨几句(只关心技术的人可以跳过,^_^)
来北京前,在武汉做开发,那里全部用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"0xaa98c00e0xd46f0x4e9e0xaf0x970xc80x240xa00x290xe40xa4)
看看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 万连文 阅读(3963) 评论(7)  编辑 收藏 引用 所属分类: MFC

FeedBack:
# re: MFC应用集成老技术自动化(Automation)
2006-08-31 20:57 | 漂舟
好文 ,
“一直喜欢讲体系,学习技术,总是想把握住整个体系”,
支持这一点,这段时间没做项目,
潜心在做研究 ?
程序我没看,只看你文字介绍就相当不错了,
今天从办公室才回来一会,
边吃方便面边看,  回复  更多评论
  
# re: MFC应用集成老技术自动化(Automation)
2006-08-31 21:01 | 漂舟
“逐渐沦为代码机器,
不敢于改革自己现有的编程模式,
把思维禁锢在一个很小的范围”
偶深有感触,差点就变成这种类型的Coder了,
每天为了快速完成特定的业务,没精力研究其它更多的东西,
只有在晚上下班后,疲倦了都还要强坚持看书,
羡慕你,经常做做研究,学学宏观的东西,
真爽
  回复  更多评论
  
# re: MFC应用集成老技术自动化(Automation)
2006-08-31 21:29 | 万连文
现在不知道是工作还是学习,可能都算,在北京遇到一个编程前辈,指点我,现在主要做MFC/ATL/.NET/ActiveX混合编程框架,有时间我就搞点古老玩意。  回复  更多评论
  
# re: MFC应用集成老技术自动化(Automation)
2006-08-31 21:58 | 漂舟
得到"编程前辈“的指点,
这一点太好了啊,
可以在宏观上、大的策略上,或者编程之路上少走点弯路,
或走上条”捷径“,
我一直想找机会摆脱当前环境,
想找个有能人的地方,好好学学,
我们公司是私人性质的小公司,
我在里面都还算是软件项目"带头大哥",真惭愧,
你机遇比较好,再加上勤奋,
前途无量,
女朋友也会有更好的 :)

我喜欢看MFC源码 ,这段时间比较多的在研究C++各项技术  回复  更多评论
  
# re: MFC应用集成老技术自动化(Automation)
2006-08-31 22:14 | 万连文
注意利用MFC、.NET等向导学习技术,注意学会利用MSDN学习技术、注意向身边有思想的人学习技术是我总结的学习技术的方法。2004年10月8日进入公司做项目,掐指一算快2年,对自己技术的提高还算满意。深刻体会到一句话:编程不扎实做上十年根本无法谈上技术大师。MFC的Frame框架、文档视图、控制条等源码部分都值得反复学习。  回复  更多评论
  
# re: MFC应用集成老技术自动化(Automation)
2006-08-31 23:27 | 漂舟
”注意向身边有思想的人学习技术“,
同感,特别是那些经验老道的程序员,
或系统分析员,项目开发总设计师,
只是我周围的生活圈,
像这类的长者太少了。  回复  更多评论
  
# re: MFC应用集成老技术自动化(Automation)
2008-12-24 11:04 | lijinyan3000
好,写的相当好!!!  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


简历下载
联系我

<2006年8月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(66)

随笔分类

随笔档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜