孙鑫VC学习(第18课--ACTIVEX控件)

来源:互联网 发布:火眼金睛软件怎么安装 编辑:程序博客网 时间:2024/04/30 08:54

容器和服务器程序

n      容器应用程序是可以嵌入或链接对象的应用程序。Word就是容器应用程序。

n      服务器应用程序是创建对象并且当对象被双击时,可以被启动的应用程序。Excel就是服务器应用程序。

 ActiveX控件的四种属性

n      Stock:为每个控件提供的标准属性,如字体或颜色。

n      Ambient:围绕控件的环境属性——已被置入容器的属性。这些属性不能被更改,但控件可以使用它们调整自己的属性。

n      Extended:这些是由容器处理的属性,一般包括大小和在屏幕上的位置。

n      Custom:由控件开发者添加的属性。

切换到VB的运行环境中。VB做为ACTIVEX控件测试容器;

VB中加载ACTIVEX控件:选择工程下面的组件:

选择MICROSOFT WINSOCK CONTROL 6.0

(。OCXACTIVEX控件的后缀名,但是ACTIVEX控件的后缀名不一定是.OCX,也可以是其它的名字,比如。DLL),选上后,点确定。

选择VIEW下的OBJECT BROWSER。在所有库的下拉列表中,选择MSWINSOCKLIB。可以看到WINSOCK控件出来了。其中,绿色控件表示方法。小手表示控件属性。闪电表,示事件。一个典型ACTIVEX控件会有这三个属性。ACTIVEX控件好处:把常用的功能封装到ACTIVEX控件中,提供给程序开发使用。

新建一个工程,选择MFCMFC ACTIVEX CONTROLWIZARD,名字是TEST。(开发一个时钟控件)。保持缺省,完成。

平放的小勺是接口。外部的函数通过接口去访问控件的属性和方法。在接口中定义的所有函数都是纯虚函数。通过接口调用的函数是调用CTestCtrl中真正实现的函数。编译一个,会在DEBUG目录下有一个TEST.OCX,这就是控件,要用的话,把它放到要用的目录下面。不能!运行程序,因为它必须要有一个容器。选择ACTIVEX CONTROL TEST CONTAINER

选择EDIT下面的INSERT NEW CONTROL…….出现下面的图,选择我们的TEST CONTROL。(VC编译环境中)

 

下面是VB环境中:

 

ACTIVEX要先注册,再能使用。

要想删除ACTIVEX的注册信息:

运行regsvr32 /u/u表示反注册,然后将TEST.OCX拉到regsvr32 /u后面),弹出:

 

这时候就找不到TEST ACTIVEX控件了。

要想再注册,用上面同样的方法,但是/u要取消。这时弹出的消息如下

 

这时再找,就可以找到TEST.OCX了。

VC中的TOOLS菜单下的REGISTER CONTROL也可以达到上面的效果。

控件使用之间,都要注册。

在控件上面输出当前时间。

代码如下:

void CTestCtrl::OnDraw(

                    CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)

{

      // TODO: Replace the following code with your own drawing code.

      CTime t = CTime::GetCurrentTime();

   CString strtime=t.Format("%H:%M:%S");

      pdc->TextOut(0,0,strtime);

      //系统下面自动加的这两句代码是为了填充背景和画椭圆的。

      //pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

      //pdc->Ellipse(rcBounds);

}

编译的时候要先将测试中的TEST控件删除。

上面这段代码的时间是静止的,不会动,下面创建一个动态的时钟。

int CTestCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

      if (COleControl::OnCreate(lpCreateStruct) == -1)

             return -1;

      

      // TODO: Add your specialized creation code here

      SetTimer(1,1000,NULL);

      return 0;

}

void CTestCtrl::OnTimer(UINT nIDEvent)

{

      // TODO: Add your message handler code here and/or call default

      Invalidate();

下面这句也可以:

InvalidateControl();

二者等效。

      COleControl::OnTimer(nIDEvent);

}

这时时间动起来了。

下面为控件添加设置前景色和背景色。

 

然后再增加前景色。

void CTestCtrl::OnDraw(

                    CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)

{

      // TODO: Replace the following code with your own drawing code. 

      COLORREF bkcolor=TranslateColor(GetBackColor( ));

      CBrush brush(bkcolor);

      pdc->FillRect(rcBounds,&brush);

 

      COLORREF txcolor=TranslateColor(GetForeColor( ));

      pdc->SetTextColor(txcolor);

      pdc->SetBkMode(TRANSPARENT);

 

      CTime t = CTime::GetCurrentTime();

   CString strtime=t.Format("%H:%M:%S");

      pdc->TextOut(0,0,strtime);

      //系统下面自动加的这两句代码是为了填充背景和画椭圆的。

      //pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

      //pdc->Ellipse(rcBounds);

}

通常一个ACTIVEX控件会提供自己属性页。

TestCtl.cpp:

BEGIN_PROPPAGEIDS(CTestCtrl, 2)

      PROPPAGEID(CTestPropPage::guid)//guid表示全局唯一标识符。

      PROPPAGEID(CLSID_CColorPropPage)//颜色属性页

END_PROPPAGEIDS(CTestCtrl)

 

这时属性页就出现了。

下面给控件添加一个自定义的属性:

增加一个时间间隔的属性。

 

 

void CTestCtrl::OnIntervalChanged()

{

      // TODO: Add notification handler code

   if (m_interval<0 || m_interval>6000)

   {

             m_interval=1000;

   }

      else

      {

             m_interval=m_interval/1000*1000;//将用户输入取整,2345-2000.

             KillTimer(1);//销毁先前的定时器

             SetTimer(1,m_interval,NULL);//设置新的定时器

      }

      SetModifiedFlag();

}

接下来将自定义的属性在属性表单中进行设置。

IDD_PROPPAGE_TEST中:

 

并为EDIT它关联一个short型的m_timeinterval

 

下面的interval是外部名称。

下面是运行结果:

 

下面给控件添加方法:

 

 

void CTestCtrl::Hello()

{

      // TODO: Add your dispatch handler code here

   MessageBox("hello world!");

}

 

接下来给控件添加一个事件:

 

[ uuid(00E87A5D-986C-4FF9-BE79-C3F0F96AA13C),

        helpstring("Test Control"), control ]

      coclass Test

      {

             [default] dispinterface _DTest;

             [default, source] dispinterface _DTestEvents;//表示控件用这个接口来发送通知事件,这个接口不是控件本身实现的接口。

      };//source表示_DTestEvents是一个源接口,是由窗口来实现的。

这时测试:

 

下面增加一个自定义的事件:

_DTestEvents上右击弹出下面对话框:

 

void CTestCtrl::OnDraw中添加:

if (0==t.GetSecond())

      {

             FireNewminute();

      }

测试结果:

 

新的一分钟到达时,事件发送了。

当添加自定义的事件时,一定要在事件发生时,去发出事件通知。标准事件时,MFC自动帮我们实现。

将文件设置前景色,背景色,时间间隔,然后保存,再次打开,发现时间间隔没有保存下来(前景色和背景色都保持下来),说明时间间隔没有持久性。

void CTestCtrl::DoPropExchange(CPropExchange* pPX)//此函数是做持久性的。

{

      ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));

      COleControl::DoPropExchange(pPX);

 

      // TODO: Call PX_ functions for each persistent custom property.

      PX_Short(pPX, "interval", m_interval,1000);

}

int CTestCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

      if (COleControl::OnCreate(lpCreateStruct) == -1)

             return -1;

      

      // TODO: Add your specialized creation code here

      SetTimer(1,m_interval,NULL);

      return 0;

}

接下来再看一个问题:

VB中做测试,当通过属性页改变时间间隔时,VB窗口中的属性时间间隔并没有随之改变。这主要是因为自定义的属性在发生改变时,没有通知容器,让容器调整。

 

由上图可以看出,间隔的属性调度ID1.

void CTestCtrl::OnIntervalChanged()

{

      // TODO: Add notification handler code

   if (m_interval<0 || m_interval>6000)

   {

             m_interval=1000;

   }

      else

      {

             m_interval=m_interval/1000*1000;//将用户输入取整,2345-2000.

             KillTimer(1);//销毁先前的定时器

             SetTimer(1,m_interval,NULL);//设置新的定时器

             BoundPropertyChanged(1);

      }

      SetModifiedFlag();

}

VB中,可以在设计时,也可以在运行时改变控件的属性。在设计时,时间值不动,在运行时,时间值才改变。容器知道自己是在设计是还是在运行时。

void CTestCtrl::OnTimer(UINT nIDEvent)

{

      // TODO: Add your message handler code here and/or call default

      if(AmbientUserMode())//运行时

      {

        InvalidateControl();

      }

      COleControl::OnTimer(nIDEvent);

}

当编写完ACTIVEX后,可以选择

 

编译,就可以生成一个发行版的OCX控件,在发行模式下进行编译时,VC程序会做一些优化,同时生成的可执行文件比较小。下面做一个VC的测试程序,用来访问我们做的ACTIVEX控件。

新建一个MFC的对话框程序(TestTest

在对话框上点击右键,插入ACTIVEX控件,选择我们刚刚建立的TEST控件。放置一个,然后右击它,可以看到相应的属性。

还可以通过工程下面的添加到工程(组件和控件),选择ACTIVEX

上面都是通过静态增加的,下面动态增加一个。在对话框上面增加一个按钮,当点击这个按钮的时候,动态的增加一个时钟控件。

CTestTestDlg增加:

private:

      CTest m_clock;

在头文件中:#include "test.h"

void CTestTestDlg::OnButton1()

{

      // TODO: Add your control notification handler code here

      m_clock.Create("windowname",WS_VISIBLE|WS_CHILD,CRect(0,0,100,70),this,123);

      m_clock.Hello();

      m_clock.SetBackColor(RGB(255,0,0));

      m_clock.SetForeColor(RGB(0,255,0));

      m_clock.SetInterval(m_clock.GetInterval()*2);

}

下面是对事件进行响应:

 

void CTestTestDlg::OnnewminuteTestctrl3()

{

      // TODO: Add your control notification handler code here

      MessageBox("newminute!");

}

对于一个动态创建的控件,去响应它的事件对象:

在创建的时候,给它分配了一个ID号,根据这个ID号,自己写。

下面是我写的:

由于创建时,控件ID选为123,修改代码如下:

TestTestDlg.h中:

afx_msg void Onnewminute123();

TestTestDlg.cpp中:

BEGIN_EVENTSINK_MAP(CTestTestDlg, CDialog)

   //{{AFX_EVENTSINK_MAP(CTestTestDlg)

      ON_EVENT(CTestTestDlg, IDC_TESTCTRL3, 1 /* newminute */, OnnewminuteTestctrl3, VTS_NONE)

      ON_EVENT(CTestTestDlg, 123, 1 /* newminute */, Onnewminute123, VTS_NONE)

      //}}AFX_EVENTSINK_MAP

END_EVENTSINK_MAP()

void CTestTestDlg::Onnewminute123()

{

   MessageBox("newminute123!");

}

 

 

 注:
1。不用注册控件,在VB和VC中都能看到产生的.ocx控件,只有当显示的调用regsvr32 /u时,在VB和VC中不能看到控件了。
2.在OnDraw函数中设置了背景色和前景色后,在VB面板中可以看到这两个属性并进行设置了(可以生效)。pdc->SetBkMode

(TRANSPARENT);在pdc->SetTextColor(TranslateColor(GetForeColor()));这句前面还是后面无所谓。
3.PROPPAGEID(CLSID_CColorPropPage)是给ACTIVEX控件添加(系统定义好的)属性页。增加一个时间间隔的属性(自定义的属性

页)
4.添加系统事件时直接添加,不需要写代码。添加自定义的事件时,要在事件发生时,去发出事件通知。通知名字就是外部名字。
5.PX_Short(pPX, "interval", m_interval,1000);BoundPropertyChanged();
6.AmbientUserMode( );
7.要动态的添加控件,也要先静态的把这个控件加入到MFC程序中。
8.例子中实现的是对123控件当新的一分钟到来时的响应。如果这个控件ID不是123,而是ID_形式,则在resource.h中要定义它值。

若写click事件,可参照一个现成的来写。
9.为时钟控件添加的属性有:前景色(ForeColor)和背景色(BackColor)(通过Add Property添加,标准属性(Stock),函数

GetBackColor和SetBackColor都是系统自动加上去的,并且系统提供系统画面和串行化操作)。自定义属性interval(通过Add

Property添加,类型为short,Variable name为m_interval,Notification是系统自动加的:OnIntervalChanged,Implementation为

Member variable),要自己写代码、加属性页(加属性页时,关联的成员变量名字要和自定义的属性名字一样,就可以实现系统自

动关联)和实现串行化工作。添加方法时,选择Add Method.然后为方法添加响应函数。为控件添加事件时,选择ActiveX Events

的Add Event.可以添加系统的事件,也可以添加自定义的事件(当添加自定义的事件时,一定要在事件发生时,去发出事件通知。

标准事件时,MFC自动帮我们实现)。
10.将时间间隔持久性:DoPropExchange中的PX_来实现。通知容器:BoundPropertyChanged。设计还是运行时判断函数:AmbientUserMode。

 

原创粉丝点击