總愛嘮叨幾句(只關心技術的人可以跳過,^_^)
來北京前,在武漢做開發,那里全部用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
萬連文 閱讀(4345)
評論(7) 編輯 收藏 引用 所屬分類:
MFC