天天看点

如何在ActiveX控件中使用字体4

如何在ActiveX控件中使用字体4

添加颜色属性页和字体属性页

  打开工程的LabelEx0Ctl.cpp文件,将其中的如下代码进行修改:

BEGIN_PROPPAGEIDS(CLabelEx0Ctrl, 1)    PROPPAGEID(CLabelEx0PropPage::guid) END_PROPPAGEIDS(CLabelEx0Ctrl)

修改后的代码:

BEGIN_PROPPAGEIDS(CLabelEx0Ctrl, 3) // 具体个数由实际情况而定    PROPPAGEID(CLabelEx0PropPage::guid)//系统自带的属性页    PROPPAGEID(CLSID_CColorPropPage) //加入Color属性页    PROPPAGEID(CLSID_CFontPropPage) //加入Font属性页 END_PROPPAGEIDS(CLabelEx0Ctrl)

修改系统自带的属性页

  打开系统自带的属性页资源IDD_PROPPAGE_LABELEx0,把属性页的尺寸由250×62调整为250×110。删除原有的静态文本框,重新添加9个静态文本框,静态文本框的内容依次为"CaptionUp:", "CaptionMiddle:","CaptionDown:","XUp:","Yup:","XMiddle:","YMiddle:","XDown:","YDown:"。添加9个对应的编辑框(Edit Box)控件,控件ID依次为IDC_CAPTIONUP,IDC_CAPTIONMIDDLE,IDC_CAPTIONDOWN,IDC_XUP,IDC_YUP,IDC_XMIDDLE,IDC_YMIDDLE,IDC_XDOWN,IDC_YDOWN。其中,IDC_CAPTIONUP,IDC_CAPTIONMIDDLE,IDC_CAPTIONDOWN分别用于输入上标,中间,下标的文本内容;IDC_XUP,IDC_YUP,IDC_XMIDDLE,IDC_YMIDDLE,IDC_XDOWN,IDC_YDOWN分别用于输入上标,中间,下标的文本的坐标位置。如图3-1。

如何在ActiveX控件中使用字体4

图3-1

  按下"Ctrl+W"组合键打开ClassWizard,选中Member Variables标签,Class name:下拉列表框选择CLabelEx0PropPage,Control IDs:选中IDC_CAPTIONUP,单击Add Variable…按钮,弹出Add Member Variable对话框。

  在Add Member Variable对话框中,Member variable name:框输入m_captionUp,Category选择Value,Variable type:框选择CString,Optional property name:框选择CaptionUp,单击OK按钮。重复上述操作,为其余8个编辑控件建立添加相应的成员变量。对应关系如下表:

  控件ID   Member variable name   Category   Variable type   Optional property name
  IDC_CAPTIONUP   m_captionUp   Value   CString   CaptionUp
  IDC_CAPTIONMIDDLE   m_captionMiddle   Value   CString   CaptionMiddle
  IDC_CAPTIONDOWN   m_captionDown   Value   CString   CaptionDown
  IDC_XUP   m_xUp   Value   long   XUp
  IDC_YUP   m_yUp   Value   long   YUp
  IDC_XMIDDLE   m_xMiddle   Value   long   XMiddle
  IDC_YMIDDLE   m_yMiddle   Value   long   YMiddle
  IDC_XDOWN   m_xDown   Value   long   XDown
  IDC_YDOWN   m_yDown   Value   long   YDown

  再次单击OK按钮关闭ClassWizard。修改控件代码在控件的头文件(LabelEx0Ctl.h),添加三个protected成员变量的声明:

protected: CFontHolder m_fontUp; CFontHolder m_fontMiddle; CFontHolder m_fontDown;

在控件的执行文件(LabelEx0Ctl.CPP)中,如下操作:在控件的构造函数中初始化

m_fontUp, m_fontMiddle, m_fontDown。

CLabelEx0Ctrl::CLabelEx0Ctrl():m_fontUp(&m_xFontNotification), m_fontMiddle(&m_xFontNotification),m_fontDown(&m_xFontNotification) {    InitializeIIDs(&IID_DLabelEx0, &IID_DLabelEx0Events);    // TODO: Initialize your control''s instance data here. }

声明一个静态FONTDESC结构,该结构包含缺省的字体属性。

static const FONTDESC _fontdescCaption =   { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE( 12 ), FW_BOLD,    ANSI_CHARSET, FALSE, FALSE, FALSE };

在控件的DoPropExchange 成员函数,添加PX_函数的调用。

void CLabelEx0Ctrl::DoPropExchange(CPropExchange* pPX) {    ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));    COleControl::DoPropExchange(pPX);    // TODO: Call PX_ functions for each persistent custom property.    PX_Font(pPX, _T("FontUp"), m_fontUp, &_fontdescCaption);    PX_Font(pPX, _T("FontMiddle"), m_fontMiddle, &_fontdescCaption);    PX_Font(pPX, _T("FontDown"), m_fontDown, &_fontdescCaption);    PX_Long(pPX,_T("XUp"),m_xUp,0);    PX_Long(pPX,_T("YUp"),m_yUp,0);    PX_Long(pPX,_T("XMiddle"),m_xMiddle,0);    PX_Long(pPX,_T("YMiddle"),m_yMiddle,20);    PX_Long(pPX,_T("XDown"),m_xDown,0);    PX_Long(pPX,_T("YDown"),m_yDown,30);    PX_String(pPX, _T("CaptionUp"), m_captionUp, _T("上标"));    PX_String(pPX, _T("CaptionMiddle"), m_captionMiddle, _T("中间"));    PX_String(pPX, _T("CaptionDown"), m_captionDown, _T("下标")); }

完成控件的成员函数

void CLabelEx0Ctrl::OnCaptionUpChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnCaptionMiddleChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnCaptionDownChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnXUpChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnYUpChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnXMiddleChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnYMiddleChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnXDownChanged() {    InvalidateControl();    SetModifiedFlag(); } void CLabelEx0Ctrl::OnYDownChanged() {    InvalidateControl();    SetModifiedFlag(); } LPFONTDISP CLabelEx0Ctrl::GetFontUp() {    return m_fontUp.GetFontDispatch(); } void CLabelEx0Ctrl::SetFontUp(LPFONTDISP newValue) {    m_fontUp.InitializeFont(&_fontdescCaption,newValue);    OnFontChanged();    SetModifiedFlag(); } LPFONTDISP CLabelEx0Ctrl::GetFontMiddle() {    return m_fontMiddle.GetFontDispatch(); } void CLabelEx0Ctrl::SetFontMiddle(LPFONTDISP newValue) {    m_fontMiddle.InitializeFont(&_fontdescCaption,newValue);    OnFontChanged();    SetModifiedFlag(); } LPFONTDISP CLabelEx0Ctrl::GetFontDown() {    return m_fontDown.GetFontDispatch(); } void CLabelEx0Ctrl::SetFontDown(LPFONTDISP newValue) {    m_fontDown.InitializeFont(&_fontdescCaption,newValue);    OnFontChanged();    SetModifiedFlag(); }

修改OnDraw函数,修改后的OnDraw函数如下:

void CLabelExCtrl::OnDraw(        CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid) {    // TODO: Replace the following code with your own drawing code.    COLORREF colorBack=TranslateColor(GetBackColor());    COLORREF colorFore=TranslateColor(GetForeColor());    CBrush brush(colorBack);    pdc->FillRect(rcBounds, &brush);    pdc->SetBkMode(TRANSPARENT);    pdc->SetTextColor(colorFore);    CFont* pOldFont;    RECT rect;    ::CopyRect(&rect,rcBounds);    pOldFont = SelectFontObject(pdc, m_fontUp);    pdc->TextOut(m_xUp,m_yUp,m_captionUp);    SelectFontObject(pdc, m_fontMiddle);    pdc->TextOut(m_xMiddle,m_yMiddle,m_captionMiddle);    SelectFontObject(pdc, m_fontDown);    pdc->TextOut(m_xDown,m_yDown,m_captionDown);    pdc->SelectObject(pOldFont); }

LabelEx0控件的制作已经完成了。您可以对它进行测试,并使用它制作形如"m3/h"样式的标签。

第四部分 优化代码,合理地使用多种字体

  上例中三个字体对象使用同一IFontNotification实现,不能具体区分控件字体对象的通知。如果想区分哪个字体已更改,可以使用以下方法:

  为控件的每个字体对象各创建一个单独的IFontNotification接口实现。此技术使您只需更新使用最近修改的字体的一个或多个字符串,从而优化了绘制代码。以下将以修改例程3 LabelEx0的字体属性FontUp为例来说明如何为第二个字体属性实现单独的通知接口所必需的步骤。

  实现新的字体通知接口

  若要区分两个或多个字体的通知,必须为控件中使用的每个字体各实现一个新的通知接口。以下各节介绍如何通过修改控件头文件和实现文件来实现新的字体通知接口。

  向头文件中添加的内容

  在控件头文件(CLabelEx0Ctrl.H)中,添加下列代码:

DECLARE_INTERFACE_MAP() //声明接口映射 BEGIN_INTERFACE_PART(FontUpNotify,IPropertyNotifySink)//声明实现接口IPropertyNotifySink的嵌套类    INIT_INTERFACE_PART(CLabelEx0Ctrl,FontUpNotify)    STDMETHOD(OnRequestEdit)(DISPID);    STDMETHOD(OnChanged)(DISPID); END_INTERFACE_PART(FontUpNotify)

这样,CLabelEx0Ctrl中多了一个嵌套类XFontUpNotify,以及它的一个变量m_xFontUpNotify。在CLabelEx0Ctrl的实现文件中加入该嵌套类的实现:

//映射接口IPropertyNotifySink到相应的嵌套类 BEGIN_INTERFACE_MAP(CLabelEx0Ctrl,COleControl) INTERFACE_PART(CLabelEx0Ctrl,IID_IPropertyNotifySink,FontUpNotify) END_INTERFACE_MAP() STDMETHODIMP_(ULONG) CLabelEx0Ctrl::XFontUpNotify::AddRef() {    METHOD_PROLOGUE_EX(CLabelEx0Ctrl,FontUpNotify)      return (ULONG)pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) CLabelEx0Ctrl::XFontUpNotify::Release() {    METHOD_PROLOGUE_EX(CLabelEx0Ctrl,FontUpNotify)      return (ULONG)pThis->ExternalRelease(); } STDMETHODIMP CLabelEx0Ctrl::XFontUpNotify::QueryInterface(REFIID iid,LPVOID FAR* ppvObj) {    METHOD_PROLOGUE_EX(CLabelEx0Ctrl,FontUpNotify)      return (HRESULT)pThis->ExternalQueryInterface(&iid,ppvObj); } STDMETHODIMP CLabelEx0Ctrl::XFontUpNotify::OnChanged(DISPID) {    METHOD_PROLOGUE_EX(CLabelEx0Ctrl,FontUpNotify)      pThis->InvalidateControl();    return NOERROR; } STDMETHODIMP CLabelEx0Ctrl::XFontUpNotify::OnRequestEdit(DISPID) {    return NOERROR; }

  在CLabelEx0Ctrl类的构造函数代码中,将m_fontUp(&m_xFontNotification)更改为m_fontUp(&m_xFontUpNotify)。对项目执行完这些更改后,重新生成项目,并使用测试容器测试接口。

例程4:LabelEx.ocx

  例程4的控件名称为LabelEx.ocx,它是例程3代码的优化,实现与例程3完全相同的功能。打开Visual C++ 6.0,新建LabelEx工程,接受所有默认设置,完成LabelEx工程创建。完成所有与例程3完全相同的操作,完成后再作如下改动和补充:

  向控件头文件(CLabelExCtrl.H)中添加下列代码

DECLARE_INTERFACE_MAP() //声明接口映射 BEGIN_INTERFACE_PART(FontUpNotify,IPropertyNotifySink) INIT_INTERFACE_PART(CLabelExCtrl,FontUpNotify)    STDMETHOD(OnRequestEdit)(DISPID);    STDMETHOD(OnChanged)(DISPID); END_INTERFACE_PART(FontUpNotify)    BEGIN_INTERFACE_PART(FontMiddleNotify,IPropertyNotifySink)    INIT_INTERFACE_PART(CLabelExCtrl,FontMiddleNotify)    STDMETHOD(OnRequestEdit)(DISPID);    STDMETHOD(OnChanged)(DISPID);    END_INTERFACE_PART(FontMiddleNotify)    BEGIN_INTERFACE_PART(FontDownNotify,IPropertyNotifySink)    INIT_INTERFACE_PART(CLabelExCtrl,FontDownNotify)    STDMETHOD(OnRequestEdit)(DISPID);    STDMETHOD(OnChanged)(DISPID);    END_INTERFACE_PART(FontDownNotify) 在CLabelExCtrl的实现文件中加入该嵌套类的实现 BEGIN_INTERFACE_MAP(CLabelExCtrl,COleControl) INTERFACE_PART(CLabelExCtrl,IID_IPropertyNotifySink,FontUpNotify) INTERFACE_PART(CLabelExCtrl,IID_IPropertyNotifySink,FontMiddleNotify) INTERFACE_PART(CLabelExCtrl,IID_IPropertyNotifySink,FontDownNotify) END_INTERFACE_MAP() STDMETHODIMP_(ULONG) CLabelExCtrl::XFontUpNotify::AddRef() {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontUpNotify)      return (ULONG)pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) CLabelExCtrl::XFontUpNotify::Release() {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontUpNotify)      return (ULONG)pThis->ExternalRelease(); } STDMETHODIMP CLabelExCtrl::XFontUpNotify::QueryInterface(REFIID iid,LPVOID FAR* ppvObj) {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontUpNotify)      return (HRESULT)pThis->ExternalQueryInterface(&iid,ppvObj); } STDMETHODIMP CLabelExCtrl::XFontUpNotify::OnChanged(DISPID) {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontUpNotify)      pThis->InvalidateControl();    return NOERROR; } STDMETHODIMP CLabelExCtrl::XFontUpNotify::OnRequestEdit(DISPID) {    return NOERROR; } STDMETHODIMP_(ULONG) CLabelExCtrl::XFontMiddleNotify::AddRef() {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontMiddleNotify)      return (ULONG)pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) CLabelExCtrl::XFontMiddleNotify::Release() {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontMiddleNotify)      return (ULONG)pThis->ExternalRelease(); } STDMETHODIMP CLabelExCtrl::XFontMiddleNotify::QueryInterface(REFIID iid,LPVOID FAR* ppvObj) {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontMiddleNotify)      return (HRESULT)pThis->ExternalQueryInterface(&iid,ppvObj); } STDMETHODIMP CLabelExCtrl::XFontMiddleNotify::OnChanged(DISPID) {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontMiddleNotify)      pThis->InvalidateControl();    return NOERROR; } STDMETHODIMP CLabelExCtrl::XFontMiddleNotify::OnRequestEdit(DISPID) {    return NOERROR; } STDMETHODIMP_(ULONG) CLabelExCtrl::XFontDownNotify::AddRef() {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontDownNotify)      return (ULONG)pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) CLabelExCtrl::XFontDownNotify::Release() {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontDownNotify)      return (ULONG)pThis->ExternalRelease(); } STDMETHODIMP CLabelExCtrl::XFontDownNotify::QueryInterface(REFIID iid,LPVOID FAR* ppvObj) {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontDownNotify)      return (HRESULT)pThis->ExternalQueryInterface(&iid,ppvObj); } STDMETHODIMP CLabelExCtrl::XFontDownNotify::OnChanged(DISPID) {    METHOD_PROLOGUE_EX(CLabelExCtrl,FontDownNotify)      pThis->InvalidateControl();    return NOERROR; } STDMETHODIMP CLabelExCtrl::XFontDownNotify::OnRequestEdit(DISPID) {    return NOERROR; }

CLabelExCtrl类的构造函数的代码作如下改动

CLabelExCtrl::CLabelExCtrl():m_fontUp(&m_xFontUpNotify), m_fontMiddle(&m_xFontMiddleNotify),m_fontDown(&m_xFontDownNotify) {    InitializeIIDs(&IID_DLabelEx, &IID_DLabelExEvents);    // TODO: Initialize your control''s instance data here. }