用MFC开发ActiveX控件注意事项

属性页使 ActiveX 控件用户得以查看和更改 ActiveX 控件属性。可通过调用控件属性对话框访问这些属性。该对话框包含一个或多个属性页,这些属性页提供自定义的图形界面用于查看和编辑控件属性。

ActiveX 控件属性页以两种方式显示:

  • 当调用控件的 Properties 谓词 (OLEIVERB_PROPERTIES) 时,控件打开包含控件属性页的有模式属性对话框。
  • 容器可以显示自己的无模式对话框,该对话框显示选定控件的属性页。

“属性”对话框(如下图所示)由以下部分组成:显示当前属性页的区域,在属性页之间切换的选项卡,以及执行常规任务的按钮集合;其中常规任务指诸如关闭属性页对话,取消所做的任何更改,或立即将任何更改应用到 ActiveX 控件等任务。

“属性”对话框

本文介绍与在 ActiveX 控件中使用属性页相关的主题。这些主题包括:

  • 实现 ActiveX 控件的默认属性页
  • 将控件添加到属性页
  • 自定义 DoDataExchange 函数

实现默认属性页

如果使用“ActiveX 控件向导”创建控件项目,则“ActiveX 控件向导”会为从 COlePropertyPage 派生的控件提供一个默认的属性页类。最初,该属性页是空白的,但可以将任何对话框控件或控件集添加到其中。由于“ActiveX 控件向导”在默认情况下只创建一个属性页类,必须使用“类视图”创建其他属性页类(也从COlePropertyPage 派生)。实现属性页(本例中为默认属性页)的过程分三步:

实现属性页

  1. COlePropertyPage 派生的类添加到控件项目。如果项目是用“ActiveX 控件向导”创建的(如在本例中),则存在默认属性页类。
  2. 使用“对话框编辑器”将任何控件添加到属性页模板。
  3. 自定义从 COlePropertyPage 派生的类的 DoDataExchange 函数,以在属性页控件与 ActiveX 控件之间交换值。

为举例说明,下列过程使用一个名为“Sample”的简单控件。“Sample”是用“ActiveX 控件向导”创建的,且只包含常用 Caption 属性。

将控件添加到属性页

将控件添加到属性页

  1. 在控件项目打开时,打开“资源视图”。
  2. 双击“Dialog”目录图标。
  3. 打开 IDD_PROPPAGE_SAMPLE 对话框。

    “ActiveX 控件向导”将项目名称追加到对话框 ID 的末尾(在本例中为“Sample”)。

  4. 将选定的控件从工具箱拖放到对话框区域。
  5. 在本例中,文本标签 (Label) 控件“Caption :”和具有 IDC_CAPTION 标识符的编辑框控件已经足够。
  6. 在工具栏上,单击“保存”保存更改。

用户界面已修改,现在需要链接编辑框与 Caption 属性。在下一节中通过编辑 CSamplePropPage::DoDataExchange 函数完成此操作。

自定义 DoDataExchange 函数

属性页 DoDataExchange 函数使您得以将属性页值与控件中的实际属性值链接。若要建立链接,必须将适当的属性页字段映射到它们各自的控件属性。

使用属性页 DDP_ 函数实现这些映射。DDP_ 函数的运行与标准 MFC 对话框中使用的DDX_ 函数相似,但有一处例外。除对成员变量的引用外,DDP_ 函数还使用控件属性的名称。下面是属性页的DoDataExchange 函数中的一个典型项。

DDP_Text(pDX, IDC_CAPTION, m_caption, _T("Caption"));

此函数使用 DDP_TEXT 函数将属性页的 m_caption 成员变量与 Caption 相关联。

插入属性页控件后,需要使用 DDP_Text 函数在属性页控件 IDC_CAPTION 与实际控件属性 Caption 之间建立链接(如前所述)。

其他对话框控件类型(如复选框、单选按钮和列表框)也可以使用 DDP 函数。下表列出了完整的属性页 DDP_ 函数集及各函数的作用:


ActiveX控件添加的属性有:

一:常用属性(系统自定义的,可直接使用),例如BackColor等。

二:成员变量(一般都是在定义它的时候会自动为工程建立一个变量,同时为它生成一个更改了该变量值后发生变化的函数,里"TextAlign"为例,生成的该相应函数为:

在.h头文件中:

void OnTextAlignChanged(void);
LONG m_TextAlign;

在.CPP文件中:

void CAnEasyValueCtrl::OnTextAlignChanged(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加属性处理程序代码
    InvalidateControl();
SetModifiedFlag();
}

三:Get/Set函数,即把相应的属性编程一个get函数和一个set函数。(以一个MaxValue为例)

这是在.h同文件中生成的相应的函数声明:

LONG GetMaxValule(void);
void SetMaxValule(LONG newVal);

以下是在.CPP文件中的实现:

LONG CAnEasyValueCtrl::GetMaxValule(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加调度处理程序代码
    return m_MaxValue;
//return 0;
}

void CAnEasyValueCtrl::SetMaxValule(LONG newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加属性处理程序代码
    if (newVal>m_MaxValue)
    {
   m_MaxValue=newVal;
    }
if (m_CurValue>m_MaxValue)
{
   m_CurValue=m_MaxValue;
}
InvalidateControl();
SetModifiedFlag();
}

在ActiveX控件中添加的事件为内联函数,即只在.h头文件中有定义(如果需要有相应的操作就在此添加操作),在需要响应该事件的地方调用它即可,以ValueIsMax为例:

在.h同文件中相应的:

void ValueIsMax(LONG* pMaxValue)
{
   FireEvent(eventidValueIsMax, EVENT_PARAM(VTS_PI4), pMaxValue);
   DoClick();   //添加的操作
   ABeep();   //添加的操作
}

在ActiveX中添加方法:

添加的方法类似于我们为工程添加到函数一样,在.h和CPP文件中都有相应的声明和实现,在需要调用该方法的地方调用即可(在我看来其实就跟成员函数没区别,只是这是在ActiveX总是这样说的)以ABeep为例:

在.h头文件中:

Protected:

void ABeep(void);

在CPP文件中:

void CAnEasyValueCtrl::ABeep(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加调度处理程序代码
MessageBeep((UINT)-1);
}

添加属性页(有常用属性页和自定义属性页):

添加的属性页最好跟系统默认的属性页的大小一致,否则越界就不美观也不好操作,为了防止出现这情况,可点击系统为该工程生成的默认对话框,然后复制在粘贴,这样一个跟系统默认大小的对话框就建成了。在这个属性页中可以添加自己想要的跟工程属性相关的控件,以关联属性,用以设置和查看控件的属性。(如果需要的属性不多,可直接在系统默认生成的那个属性页中添加自己的关联控件即可,这样可省去很多的麻烦,默认的属性页一般是控件名加上PropertyPage)设置好对话框中的控件后就为该对话框添加添加类,它的基类必须是:OlePropertyPage否则不能实现添加好类后还必须跟控件关联,必要再相应的添加属性页的地方添加上给属性页,以为例:

// 属性页

// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CAnEasyValueCtrl, 2)
PROPPAGEID(CAnEasyValuePropPage::guid)
PROPPAGEID(CAnEasyValueOtherPropertyPage::guid)            //字定义属性页
END_PROPPAGEIDS(CAnEasyValueCtrl)

这样操作后只是让属性页跟控件关联了,还必须进行如下操作:

为属性页添加好对应的变量,并在生成的下列函数中添加红色字体的代码,以关联控件的属性。

void CAnEasyValuePropPage::DoDataExchange(CDataExchange* pDX)          //注意这里是系统默认的属性页的地方,而非自定义的属性页位置。
{

DDX_Text(pDX, IDC_EDIT_Caption, m_Capture);
DDX_Text(pDX, IDC_EDIT_MaxValue, m_MaxValue);
DDX_Text(pDX, IDC_EDIT_CurValue, m_CurValue);
DDX_Text(pDX, IDC_EDIT_MinValue, m_MinValue);
DDX_Radio(pDX, IDC_RADIO_Left, m_Align);

DDP_Text(pDX,IDC_EDIT_Caption,m_Capture,_T("Caption"));          //DDP_是对属性页的控件变量和控件的属性的关联的映射,这样,在属性页中更改相应的值就能反映到到控件,也可通过属性页查看控件的设置值。
DDP_Text(pDX,IDC_EDIT_MaxValue,m_MaxValue,_T("MaxValue"));
DDP_Text(pDX,IDC_EDIT_CurValue,m_CurValue,_T("CurrentValue"));
DDP_Text(pDX,IDC_EDIT_MinValue,m_MinValue,_T("MinValue"));
DDP_Radio(pDX,IDC_RADIO_Left,m_Align,_T("TextAlign"));
//必须放在最后,否则不能实现转换
DDP_PostProcessing(pDX);
    //这个很关键,默认生成是在该函数的第一条语句,必须手动移动该语句到末尾,否则不能实现真正的转换,即转换不成功。

}

这样做了后还不能正常显示属性页,如果此时生成工程会出现Debug,但编译成功,可以使用该控件,只是在控件的属性页中没有我们自己添加的属性页,更改属性就更不用说了。要正常显示,须进行如下操作:

一:在资源的String Table中添加自己想要显示的属性页的标题:

ID                            值       Caption

IDS_OTHER_PPG   3        附加的自定义属性页

二:在生成的自定义的属性页的CPP文件中的注册函数中的相应的操作:

// CAnEasyValueOtherPropertyPage::CAnEasyValueOtherPropertyPageFactory::UpdateRegistry -
// 添加或移除 CAnEasyValueOtherPropertyPage 的系统注册表项

BOOL CAnEasyValueOtherPropertyPage::CAnEasyValueOtherPropertyPageFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: 定义页类型的字符串资源;用 ID 替换下面的“0”。

if (bRegister)
   return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
    m_clsid, IDS_OTHER_PPG);       //必须这样操作,否则无法识别
else
   return AfxOleUnregisterClass(m_clsid, NULL);
}
三:在生成的自定义的属性页的CPP文件中的构造函数中的相应的操作:

// CAnEasyValueOtherPropertyPage::CAnEasyValueOtherPropertyPage - 构造函数

// TODO: 定义页标题的字符串资源;用 ID 替换下面的“0”。

CAnEasyValueOtherPropertyPage::CAnEasyValueOtherPropertyPage() :
COlePropertyPage(IDD, IDS_OTHER_PPG)       //必须这样操作,否则无法识别

{
    
}

添加常用属性页,只需在CPP源文件添加属性页的地方直接添加相应的属性页名称即可,系统已为我们自动实现了所以操作,如果需要使用这些默认属性页里的控件关联,只需添加相应是常用属性和方法即可。常用属性页有3个,在CPP中添加位置如下:

// 属性页

// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CAnEasyValueCtrl, 4)
PROPPAGEID(CAnEasyValuePropPage::guid)
PROPPAGEID(CLSID_CFontPropPage)
PROPPAGEID(CLSID_CColorPropPage)
PROPPAGEID(CLSID_CPicturePropPage)
END_PROPPAGEIDS(CAnEasyValueCtrl)

http://hi.baidu.com/luojianwen4201/blog/item/ee6a938bc593f21fc9fc7a68.html/cmtid/b4503507119f22c37b89478b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值