如何在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。

圖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.
}