null第6章 ActiveX与OLE第6章 ActiveX与OLE部件库的基本概念
ActiveX的概念
ActiveX控件的使用
OLE的基本概念
OLE容器与OLE服务器部件库的
部件库的内容VC++提供部件:弥补AppWizard中没有或不便提供的功能
例如,对话框条、状态条、属性页、密码
ActiveX控件:现成的ActiveX控件
用户自定义部件:以类为单位保存的部件,供其它的程序重用对话框条的使用对话框条的使用DialogBar将对话框作成工具条形式
Project->Add To Project->Visual C++ Component,从列表中选择DialogBar
从Resource View中修改DialogBar状态条的使用状态条的使用Status bar是窗口底端的说明部分,如果要显示日期和时间,可使用部件库中的状态条
Project->Add To Project->Visual C++ Component,从列表中选择Status bar,并选定日期和时间
从Resource View中修改Status bar属性页与Wizard(1)属性页与Wizard(1)属性页是几个对话框的集合,用户可以显示任意对话框,并进行相应的操作
Wizard是几个对话框的集合,但不是同时显示这些对话框,而是按顺序逐个显示属性页与Wizard(2)属性页与Wizard(2)Project->Add To Project->Visual C++ Component,从列表中选择Property Sheet
建立菜单项ID_PAGE_PROPERTY
在菜单ID_PAGE_PROPERTY上添加函数CMyPropertySheet Sheet;
Sheet.DoModal();属性页与Wizard(3)属性页与Wizard(3)Project->Add To Project->Visual C++ Component,从列表中选择Property Sheet
建立菜单项ID_PAGE_WIZARD
在菜单ID_PAGE_WIZARD上添加函数属性页与Wizard(4)属性页与Wizard(4)ActiveX的概念(1)ActiveX的概念(1)ActiveX:对象链接与嵌入(OLE)的扩展
ActiveX文档
ActiveX文档是OLE文档扩展,包括4种COM接口:IOleDocument、IOleDocumentView、IOleCommandTarget与IPrint
ActiveX文档可以包含多个页
ActiveX文档显示在浏览器(例如IE)或其它容器(Binder)ActiveX的概念(2)ActiveX的概念(2)ActiveX控件
ActiveX控件是OLE控件的扩展,不仅可以嵌入网页,还可用于非网络应用程序
DCOM
DCOM是COM在网络中的扩展,以在网络中使用与交换对象
Internet Monikers
Internet Monikers是一种资源对象,例如URL Monikers与异步MonikersActiveX的概念(3)ActiveX的概念(3)ActiveX超链接
在HTML文件中激活非HTML文件,例如Word、Excel与PowerPoint等
ActiveX服务器扩展
实际上是ISAPI,增强服务器功能。ISAPI只能通过CGI实现,它可以通过DLL实现
ActiveX脚本
将OLE自动化引入Internet,可使用的脚本包括:VBScript与JavaScriptActiveX控件(1)ActiveX控件(1)ActiveX控件是程序封装的、可重用的控件
ActiveX容器使用接口与ActiveX控件交流
ActiveX控件使用
接口,不局限于某种特定的程序语言,很多开发工具都可以使用ActiveX控件(2)ActiveX控件(2)ActiveX控件与它的容器通信,控件容器使用ActiveX接口ActiveX控件(3)ActiveX控件(3)ActiveX事件(event):控件发送给包含控件的应用程序的消息
ActiveX属性(property):与控件相关的一些属性,例如颜色或按钮高度
ActiveX
(method):由控件提供的、控件容器调用的函数添加ActiveX控件(1)添加ActiveX控件(1)Project->Add to Project->Components and Controls->Registered ActiveX Controls
用户可像使用其它控件一样,开始使用新添加的ActiveX控件添加ActiveX控件(2)添加ActiveX控件(2)ActiveX控件的建立过程ActiveX控件的建立过程建立ActiveX控件
增加控件属性与属性页
增加控件事件
增加控件方法
注册ActiveX控件
使用ActiveX控件ActiveX控件的建立(1)ActiveX控件的建立(1)建立ActiveX控件工程
ActiveX控件是以.OCX为后缀
用户创建控件与系统提供控件一样
通过AppWizard工具,用户可以建立项目文件,自动生成ActiveX控件代码框架,在此基础上实现ActiveX控件ActiveX控件的建立(2)ActiveX控件的建立(2)ActiveX控件的建立(3)ActiveX控件的建立(3)_DClock与_DClockEvents是控件的接口
CClockApp是COleControlModule的派生类ActiveX控件的建立(4)ActiveX控件的建立(4)CClockCtrl是COleControl派生类
CClockPropPage是COlePropertyPage派生类ActiveX控件的测试(1)ActiveX控件的测试(1)ActiveX Control Test Container
Web BrowserActiveX控件的测试(2)ActiveX控件的测试(2)在容器中添加ActiveX控件ActiveX控件的测试(3)ActiveX控件的测试(3)在CClockCtrl::OnDraw()中
在CClockCtrl::OnCreate()中
SetTimer(1,1000,NULL);
在CClockCtrl::OnTimer()中
Invalidate();CTime time=CTime::GetCurrentTime();
CString str=time.Format("%H:%M:%S");
pDC->TextOut(0,0,str);ActiveX控件的测试(4)ActiveX控件的测试(4)ActiveX控件属性(1)ActiveX控件属性(1)在ClassWizard中选择AutomationActiveX控件属性(2)ActiveX控件属性(2)增加BackColor和ForeColor标准属性
在CClockCtrl::OnDraw()中CBrush bkBrush(TranslateColor (GetBackColor()));
pdc->FillRect(rcBounds,&bkBrush);
pdc->SetBkMode(TRANSPARENT);
pdc->SetTextColor(TranslateColor (GetForeColor()));ActiveX控件属性(3)ActiveX控件属性(3)AppWizard生成ActiveX程序时,自动生成属性页(General与Extended)
通过增加属性页ID增加页面,系统提供一些标准页面,例如调色板(CLSID_CColorPropPage)BEGIN_PROPPAGEIDS(CClockCtrl,1)
PROPPAGEID(CClockPropPage::guid)
END_PROPPAGEIDS(CClockCtrl)ActiveX控件属性(4)ActiveX控件属性(4)增加标准属性页BEGIN_PROPPAGEIDS(CClockCtrl,2)
PROPPAGEID(CClockPropPage::guid)
PROPPAGEID(CLSID_CColorPropPage)
END_PROPPAGEIDS(CClockCtrl)ActiveX控件属性(5)ActiveX控件属性(5)增加定制属性
在ClassWizard中选择Automation
选择Add Property按钮
选择Member Variable
填写属性的名称、类型、变量和通知函数ActiveX控件属性(6)ActiveX控件属性(6)增加Interval定制属性,每隔m_Interval更新
在CClockCtrl::OnCreate()中
SetTimer(1,m_interval,NULL);
在CClockCtrl::OnIntervalChanged()中if(m_interval<0)
{ MessageBox(“Interval Error!");
m_interval=1000; }
KillTimer(1);
SetTimer(1,m_interval,NULL);ActiveX控件属性(7)ActiveX控件属性(7)修改定制属性页
在ResourceView中选择IDD_PROPPAGE_CLOCK
增加编辑框控件IDC_INTERVAL
为IDC_INTERVAL关联变量m_updateInterval
为IDC_INTERVAL关联属性IntervalActiveX控件属性(8)ActiveX控件属性(8)ActiveX控件方法ActiveX控件方法ActiveX控件方法是控件成员函数,为应用程序提供更多控制手段
标准控件方法包括:Refresh与DoClick
自定义控件方法的过程:输入方法名称和编写函数代码
void CClockCtrl::Hello()
{
MessageBox("Hello World!");
}ActiveX控件事件(1)ActiveX控件事件(1)ActiveX标准事件
Click、DblClick、Error、KeyDown、KeyPress、KeyUp、MouseDown、MouseUp、 MouseMove、ReadyStateChangeActiveX控件事件(2)ActiveX控件事件(2)ActiveX自定义事件
增加事件NewMinute
在CClockCtrl::OnDraw()中CTime time=CTime::GetCurrentTime();
if(time.GetSecond()==0)
{
FireNewMinute();
}ActiveX控件注册ActiveX控件注册ACtiveX控件使用前必须注册
ActiveX容器可注册控件与取消注册ActiveX控件的使用(1)ActiveX控件的使用(1)静态方式增加ActiveX控件ActiveX控件的使用(2)ActiveX控件的使用(2)增加ActiveX控件事件
为Clock控件增加对应的变量
在CTestDlg::OnClickClockctrl()中
MessageBox("Control is clicked!");
在CTestDlg::OnNewMinuteClockctrl()中
MessageBox("New minute!");ActiveX控件的使用(3)ActiveX控件的使用(3)在CTestDlg中增加变量
在CTestDlg::OnTest()中private:
CClock m_clock;m_clock.Create("Clock",WS_CHILD|WS_VISIBLE,CRect(50,50,150,100),this,123);
m_clock.Hello();
m_clock.SetBackColor(RGB(0,0,255));
m_clock.SetForeColor(RGB(255,0,0));ActiveX控件的使用(4)ActiveX控件的使用(4)动态方式增加ActiveX控件ActiveX
库(1)ActiveX模板库(1)ATL(ActiveX Template Library)是一组基于C++类的模板,专门用于创建COM对象
ATL提供对COM接口的支持,不需要外部DLL与C++运行库。ATL可以创建ActiveX控件、自动化服务器与其他COM对象ActiveX模板库(2)ActiveX模板库(2)Dynamic Link Library(DLL):进程中服务器方式,与容器在同一地址空间运行,访问COM接口不需额外开销
Executable(EXE):进程外服务器方式,作为可执行文件在自己地址空间运行,创建每个服务器对象均启动新拷贝
Service(EXE):业务服务器方式,作为操作系统后台运行的服务启动ActiveX模板库(3)ActiveX模板库(3)ATL的使用过程OLE的概念(1)OLE的概念(1)OLE 1.0是对象链接与嵌入技术,提供处理复合文档的方法,在文档中保存不同类型数据,这些数据由不同程序生成
OLE 2.0是基于对象服务的体系,它能扩展、定制与增强,主要服务包括:OLE文档、OLE控件、OLE自动化、Monikers、结构化存储、统一数据传输等OLE的概念(2)OLE的概念(2)部件对象模型(COM)是OLE的基础,为OLE提供编程模型与标准。COM对象支持封装、多态性与重用,它关心与其他对象接口(IUnknown)
OLE文档是以结构化存储方式保存对象的复合文档,主要接口包括:IOleItemContainer、IPeristFile、IOleInPlaceActiveFrame、IOleInPlaceObject与IOleInPlaceSite
OLE控件是可嵌入容器的可重用部件,在编译或运行时设置属性OLE的概念(3)OLE的概念(3)OLE自动化提供控制其它程序的方法,通过宏或脚本。自动化客户是控制程序,自动化服务器是被控制程序。客户使用IDispatch接口
Monikers提供在文件中定位对象的方法,例如为链接的对象创建Monkiers,主要包括5种:File、Item、Generic composite、Anti与PointerOLE的概念(4)OLE的概念(4)结构化存储提供在文件中组织数据的方法,以便多种程序向一个文件写入数据。结构化存储使用的接口:IPeristStorage、IStorage与IStream
统一数据传输(UDT)提供将数据从存储位置传输到处理位置方法,通过IDataObject接口提供数据传输服务:剪贴板、拖放、链接与嵌入OLE的概念(5)OLE的概念(5)容器程序与服务器程序OLE容器(1)OLE容器(1)OLE容器是用于创建OLE文档的程序,可将内容嵌入或链接到文档中
AppWizard生成容器
COleTestApp
COleTestView
COleTestDoc
COleTestCntrItem
CMainFrameOLE容器(2)OLE容器(2)COleTestView类
OnDraw:是否重绘OLE项
IsSelected:指定OLE项是否选中
OnInsertObject:菜单中的“插入新对象”
OnSetFocus:将焦点移到被激活的OLE项
COleTestCntrItem类
OnChange:容器如何响应OLE项修改
OnGetItemPosition:获得OLE项位置
OnChangeItemPosition:改变OLE项位置OLE容器(3)OLE容器(3)OLE容器的例子(10,10,210,210)OLE容器(4)OLE容器(4)实现OLE项矩形存储
public: CRect m_rect;
在CCntrItem构造函数中
m_rect.SetRect(10,10,310,310);
在CCntrItem::OnGetItemPosition()中
rPosition=m_rect;OLE容器(5)OLE容器(5)在CCntrItem::OnChangeItemPosition()中
在CCntrItem::Serialize()中GetDocument()->UpdateAllViews(NULL);
m_rect=rectPos;
GetDocument()->SetModifiedFlag();if(ar.IsStoring())
ar<
>m_rect;OLE容器(6)OLE容器(6)命中测试函数CMy222CntrItem* CMy222View::HitTestItems(CPoint point)
{
CMy222Doc* pDoc=GetDocument();
CMy222CntrItem* pHitItem=NULL;
CMy222CntrItem* pItem;
POSITION pos=pDoc->GetStartPosition();
while(pos!=NULL)
{ pItem=(CMy222CntrItem *)pDoc->GetNextItem(pos);
if(pItem->m_rect.PtInRect(point))
pHitItem=pItem; }
return pHitItem;
}OLE容器(7)OLE容器(7)选择函数void CMy222View::SetSelection(CMy222CntrItem* pItem)
{
if(pItem==NULL||m_pSelection!=pItem)
{
COleClientItem* pActiveItem=GetDocument()-> GetInPlaceActiveItem(this);
if(pActiveItem!=NULL&&pActiveItem!=pItem)
pActiveItem->Close();
}
Invalidate();
m_pSelection=pItem;
}OLE容器(8)OLE容器(8)鼠标单击选中OLE项-OnLButtonDown()CMy222CntrItem* pHitItem=HitTestItems(point);
SetSelection(pHitItem);
if(pHitItem!=NULL)
{ CRectTracker tracker;
SetTracker(pHitItem,&tracker);
UpdateWindow();
if(tracker.Track(this,point))
{ Invalidate();
pHitItem->m_rect=tracker.m_rect;
GetDocument()->SetModifiedFlag(); }
}OLE容器(9)OLE容器(9)设置跟踪函数void CMy222View::SetTracker(CMy222CntrItem *pItem, CRectTracker *pTracker)
{ pTracker->m_rect=pItem->m_rect;
if(pItem==m_pSelection)
pTracker->m_nStyle|=CRectTracker::resizeInside;
if(pItem->GetType()==OT_LINK)
pTracker->m_nStyle|=CRectTracker::dottedLine;
else
pTracker->m_nStyle|=CRectTracker::solidLine;
if(pItem->GetItemState()==COleClientItem:: openState||pItem->GetItemState()==COleClientItem:: activeUIState)
pTracker->m_nStyle|=CRectTracker::hatchInside; }OLE容器(10)OLE容器(10)鼠标双击打开OLE项-OnLButtonDblClk()
改变鼠标形状-OnSetCursor()if(m_pSelection!=NULL)
{ m_pSelection->DoVerb(GetKeyState(VK_CONTROL) <0?OLEIVERB_OPEN:OLEIVERB_PRIMARY,this); }if(pWnd==this&&m_pSelection!=NULL)
{ CRectTracker tracker;
SetTracker(m_pSelection,&tracker);
if(tracker.SetCursor(this,nHitTest))
return TRUE; }OLE容器(11)OLE容器(11)绘制多个OLE项-OnDraw()POSITION pos=pDoc->GetStartPosition();
CMy222CntrItem * pItem;
while (pos!=NULL)
{
pItem=(CMy222CntrItem *)pDoc->GetNextItem(pos);
pItem->Draw(pDC,pItem->m_rect);
CRectTracker tracker;
SetTracker(pItem,&tracker);
tracker.Draw(pDC);
}OLE容器(12)OLE容器(12)添加删除功能-ID_EDIT_DELvoid CMy222View::OnEditDel()
{
if(m_pSelection!=NULL)
{ m_pSelection->Delete();
m_pSelection=NULL;
GetDocument()->UpdateAllViews(NULL); }
}
void CMy222View::OnUpdateEditDel(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSelection!=NULL);
}OLE容器(13)OLE容器(13)OLE容器的例子OLE服务器(1)OLE服务器(1)小型服务器(mini-server):不能独立运行,只能通过容器启动
全服务器(full-server):既可以作为独立的程序运行,又可以由容器启动,可以同时支持多个容器
自动化服务器(automation-server):使程序可以操纵另一个程序创建的对象OLE服务器(2)OLE服务器(2)全服务器的例子
CFullApp类:生成用于注册的OLE标识符,初始化OLE库与打开模板,检查是否作为服务启动
CFullDoc类:当容器启动服务器、创建链接项时,构造复合文档并返回CFullSrvItem
CInPlaceFrame类:服务器的边框窗口
CFullView类:服务器的视图
CFullSrvItem类:服务器的OLE接口OLE服务器(3)OLE服务器(3)自动化服务器(1)自动化服务器(1)通过AppWizard生成程序,第3步选中None与Automation
AfxOleInit初始化OLE库
COleTemplateServer::ConnectTemplate关联模板与COleTemplateServer
COleTemplateServer::RegisterAll
对象描述文件AutoServer.odl,包含自动化对象、属性与方法自动化服务器(2)自动化服务器(2)在CAutoServerDoc中增加变量
在CAutoServerDoc构造函数中
在CAutoServerDoc::Serialize()中if(ar.IsStoring())
ar<>m_point>>m_string; CString m_string; CPoint m_point;m_point=CPoint(50,50);
m_string=_T("自动化");自动化服务器(3)自动化服务器(3)在CAutoServerView::OnDraw()中
在CAutoServerDoc中添加Refresh()中pDC->TextOut(pDoc->m_point.x,pDoc-> m_point.y,pDoc->m_string);UpdateAllViews(NULL);
SetModifiedFlag();自动化服务器(4)自动化服务器(4)添加自动化属性:直接与间接方式
使用Get/Set方法间接添加m_point
GetX():return (short)m_point.x;
SetX():m_point.x=nNewValue; Refresh();
直接添加m_string
External Name:text
OnTextChanged():Refresh();
手工去除重复m_string自动化服务器(5)自动化服务器(5)添加自动化方法
RefreshWindow:与Refresh相同,根据m_point与m_string的值更新视图
SetProps:设置m_point与m_string,并更新视图
ShowWindow:显示自动化服务器边框窗口,自动化服务器被自动化客户激活,默认不显示边框窗口自动化服务器(6)自动化服务器(6)SetProps方法void CAutoServerDoc::SetProps(short x, short y, LPCTSTR text)
{
m_point.x=x;
m_point.y=y;
m_string=text;
Refresh();
}自动化服务器(7)自动化服务器(7)ShowWindows方法void CAutoServerDoc::ShowWindows()
{
POSITION pos=GetFirstViewPosition();
CView* pView=GetNextView(pos);
if(pView!=NULL)
{ CFrameWnd* pWnd=pView->GetParentFrame();
pWnd->ActivateFrame(SW_SHOW);
pWnd=pWnd->GetParentFrame();
if(pWnd!=NULL)
pWnd->ActivateFrame(SW_SHOW); }
}自动化服务器(8)自动化服务器(8)自动化服务器的例子自动化客户(1)自动化客户(1)创建自动化客户的过程
创建一个自动化客户(Automation)
创建COleDispatchDriver派生类
添加自动化对象变量(IAutoServer m_autoServer)
修改对话框模板
为对话框中的控件定义成员变量
定义并实现消息处理函数自动化客户(2)自动化客户(2)创建COleDispatchDriver派生类自动化客户(3)自动化客户(3)设计对话框控件自动化客户(4)自动化客户(4)在CAutoClientDlg::OnCreate()中if(!m_autoServer.CreateDispatch(_T ("Autoserver.Document")))
{
MessageBox("Cannot Create AutoServer!");
return -1;
}
m_autoServer.ShowWindows();自动化客户(5)自动化客户(5)在CAutoClientDlg::OnSettext()中
在CAutoClientDlg::OnSetx()中
在CAutoClientDlg::OnSety()中GetDlgItemText(IDC_TEXT,m_Text);
m_autoServer.SetText(m_Text);m_X=(short)GetDlgItemInt(IDC_X);
m_autoServer.SetX(m_X);m_Y=(short)GetDlgItemInt(IDC_Y);
m_autoServer.SetY(m_Y);自动化客户(6)自动化客户(6)第6次作业第6次作业设计一个多媒体播放程序,要求至少具有以下功能:
使用系统提供的WMPPlayer4控件
播放avi与mpg格式的视频文件
播放mp3与wav格式的音频文件
实现打开、播放、暂停/继续与停止功能谢谢大家谢谢大家