1. 程式人生 > >如何在 ActiveX 控制元件中使用字型

如何在 ActiveX 控制元件中使用字型

字型的使用是ActiveX控制元件製作過程中不可缺少的部分。本文將深入淺出地介紹在ActiveX控制元件中製作過程中如何使用字型。本文所提及的ActiveX控制元件製作是指利用VC++6.0的MFC ActiveX ControlWizard 工具,用其它方法制作 ActiveX 控制元件本文不作討論。
  本文專門設定了一些例程,以便您能夠更好地掌握這些內容。這些例程都是完整的ActiveX控制元件製作原始碼。為了突出重點,本文僅對字型使用相關部分的原始碼作較詳細的介紹,其餘部分的程式碼本文不作過多討論。字型作為一種屬性在ActiveX控制元件中使用,與其它屬性沒有區別,同樣分為庫存屬性和自定義屬性,本文將分四個部分進行介紹。

第一部分 在控制元件中使用庫存字型(Stock Font)屬性

使用ClassWizard 新增 Font庫存屬性的步驟:

  1. 開啟控制元件工程, 單擊View選單的ClassWizard開啟ClassWizard;
  2. 單擊Automation標籤;
  3. 在Class Name框,選擇你的控制元件類名;
  4. 單擊Add Property;
  5. 在 External name框, 單擊Font;
  6. 單擊 OK;
  7. 單擊 OK確認你的選擇並關閉 ClassWizard;

ClassWizard將在控制元件類的執行檔案的dispatch對映表中加入下列行:

DISP_STOCKPROP_FONT()

另外, ClassWizard 在.ODL 檔案中加入下列行:

[id(DISPID_FONT), bindable] IFontDisp* Font;

例程1:Label.ocx

  下面,我們舉一個具體的例項詳細演示如何在控制元件中新增Font庫存屬性。您可以下載該例程進行編譯生成 .ocx 控制元件,並測試該控制元件。
我們將要製作的控制元件取名Label.ocx,模仿VB工具箱中的Label控制元件。該控制元件增強了VC++工具箱中的Static Text控制元件的有限的功能,您可以方便地在您的工程中使用。例程的工程名也取名為Label。

建立Label工程

  開啟Visual C++ 6.0,單擊File選單的New,彈出New對話方塊。在對話方塊中選擇MFC ActiveX ControlWizard,並輸入工程名Label,單擊OK按鈕,關閉該對話方塊並彈出MFC ActiveX ControlWizard-Step 1 of 2對話方塊。如圖1-1。


圖1-1

  接受MFC ActiveX ControlWizard-Step 1 of 2對話方塊所有預設設定,單擊Next按鈕,關閉該視窗同時彈出MFC ActiveX ControlWizard-Step 2 of 2對話方塊。繼續接受MFC ActiveX ControlWizard-Step 2 of 2對話方塊所有預設設定,單擊Finish按鈕。
繼續單擊OK 按鈕,Label工程建立完成,我們將繼續對該工程進行修改。使用ClassWizard 給控制元件增加庫存屬性Caption,BackColor,ForeColor,Font。

  1. 單擊View選單的ClassWizard開啟 ClassWizard;
  2. 單擊Automation標籤;
  3. Class Name下拉列表框選擇CLabelCtrl,單擊 Add Property;
  4. 在External name框中,單擊Caption;
  5. 單擊OK;
  6. 單擊OK確認你的選擇並關閉ClassWizard;

我們已經給控制元件增加了庫存屬性Caption,該屬性用以設定Label控制元件的文字內容。按上述同樣操作,依次新增庫存屬性BackColor,ForeColor,Font。這3個屬性分別用以設定Label控制元件的背景色,前景色以及字型的屬性。如圖1-2。


圖1-2

新增顏色屬性頁和字型屬性頁

開啟工程的LabelCtl.cpp檔案,將其中的如下程式碼進行修改:

BEGIN_PROPPAGEIDS(CLabelCtrl, 1)
PROPPAGEID(CLabelPropPage::guid)
END_PROPPAGEIDS(CLabelCtrl)

修改後的程式碼:

BEGIN_PROPPAGEIDS(CLabelCtrl, 3) // 具體個數由實際情況而定
PROPPAGEID(CLabelPropPage::guid)//系統自帶的屬性頁
PROPPAGEID(CLSID_CColorPropPage) //加入Color屬性頁
PROPPAGEID(CLSID_CFontPropPage) //加入Font屬性頁
END_PROPPAGEIDS(CLabelCtrl) 

修改系統自帶的屬性頁

  開啟系統自帶的屬性頁資源IDD_PROPPAGE_LABEL,將靜態文字框IDC_STATIC的內容改為"Caption:",新增一個編輯框(Edit Box)控制元件,控制元件ID為IDC_CAPTION。如圖1-3


圖1-3

  按下"Ctrl+W"組合鍵開啟ClassWizard,選中Member Variables標籤,Class name:下拉列表框選擇CLabelPropPage,Control IDs:選中IDC_CAPTION,單擊Add Variable…按鈕,彈出Add Member Variable對話方塊。
在Add Member Variable對話方塊中,Member variable name:框輸入m_caption,Category選擇Value,Variable type:框選擇CString,Optional property name:框選擇Caption,單擊OK按鈕。如圖1-4。


圖1-4

再次單擊OK按鈕關閉ClassWizard。上述操作,編輯框IDC_CAPTION與Caption屬性之間建立了聯絡。您可以通過修改編輯框的內容來改變控制元件Caption的屬性值。

修改OnDraw函式

修改後的OnDraw函式如下:

void CLabelCtrl::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());
     // GetBackColor(),GetForeColor()分別得到背景色和前景色
     // GetBackColor(),GetForeColor()返回型別為OLE_COLOR
     // TranslateColor函式將OLE_COLOR型別轉換為COLORREF型別

	CBrush brush(colorBack);
	pdc->FillRect(rcBounds, &brush);
     //背景色填充整個控制元件
	pdc->SetBkMode(TRANSPARENT);
     //設定透明背景色
	pdc->SetTextColor(colorFore);
     //前景色設定為字型顏色
	const CString& strCaption = InternalGetText();
     //獲得庫存屬性Caption的值
	CFont* pOldFont;
	pOldFont = SelectStockFont(pdc);
     //裝置上下文中選擇字型物件
	RECT rect;
	::CopyRect(&rect,rcBounds);
	pdc->DrawText(strCaption,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
     //單行,水平居中,垂直居中顯示
	pdc->SelectObject(pOldFont);
}

  Label控制元件的製作已經完成了,您可以方便地改變字型的大小、型別、顏色以及控制元件的背景色。當然,您還可以進一步完善該控制元件,更加方便您的使用。

第二部分 在控制元件中使用自定義的字型(Custom Font)屬性

  除了庫存字型屬性Font外, ActiveX控制元件還允許使用自定義的字型屬性。新增一個自定義字型屬性,要完成一個自定義字型屬性,你應該首先使用 ClassWizard 新增自定義字型屬性,然後對程式碼作一些修改。下面將描述怎樣給一個控制元件新增自定義屬性(假設控制元件的名字為Sample):
使用 ClassWizard 新增自定義字型屬性

  1. 開啟 控制元件工程,單擊View選單的ClassWizard開啟 ClassWizard;
  2. 單擊Automation標籤;
  3. 單擊 Add Property;
  4. 在External name框中,輸入屬性名(在本例中,假設輸入的自定義屬性名為HeadingFont);
  5. 在Implementation框中,單擊Get/Set Methods;
  6. 在Return Type框中,選擇LPFONTDISP作為屬性型別;
  7. 單擊OK;
  8. 單擊OK確認你的選擇並關閉ClassWizard;

  ClassWizard 將產生相應的程式碼把自定義屬性HeadingFont新增到CSampleCtrl類中和 SAMPLE.ODL檔案中。既然 HeadingFont是一個 Get/Set 屬性型別,ClassWizard 修改CSampleCtrl 類的dispatch 對映表來包括一個DISP_PROPERTY_EX 巨集入口:

BEGIN_DISPATCH_MAP(CSampleCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CSampleCtrl)
DISP_PROPERTY_EX(CSampleCtrl, "HeadingFont", GetHeadingFont,
   SetHeadingFont, VT_DISPATCH)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()      
  DISP_PROPERTY_EX 巨集把HeadingFont屬性名和它的相應的CSampleCtrl類的Get / Set 方法(GetHeadingFont and SetHeadingFont)聯絡起來。 ClassWizard 也在控制元件的標頭檔案(.H)為GetHeadingFont 和 SetHeadingFont函式新增宣告 ,並在控制元件的執行檔案(.CPP)新增模板函式:
LPFONTDISP CSampleCtrl::GetHeadingFont() 
{
 // TODO: Add your property handler here
 return NULL;
}
void CSampleCtrl::SetHeadingFont(LPFONTDISP newValue)
{
 // TODO: Add your property handler here
 SetModifiedFlag();
}      
最後, ClassWizard修改控制元件的 .ODL 檔案,為HeadingFont 屬性新增一個入口:
[id(1)] IFontDisp* HeadingFont;

修改控制元件程式碼

  現在你已經為控制元件添加了HeadingFont屬性,你必須對控制元件的標頭檔案和執行檔案進行修改以完全支援新的屬性。在控制元件的標頭檔案(.H),新增一個protected成員變數的宣告:

protected:
CFontHolder m_fontHeading;

在控制元件的執行檔案(.CPP)中,如下操作:在控制元件的建構函式中初始化 m_fontHeading。

CSampleCtrl::CSampleCtrl( ) : m_fontHeading( &m_xFontNotification )
{
    // [...body of constructor...]
}      
宣告一個靜態FONTDESC結構,該結構包含預設的字型屬性。
static const FONTDESC _fontdescHeading =
  { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE( 12 ), FW_BOLD, 
     ANSI_CHARSET, FALSE, FALSE, FALSE };      
在控制元件的DoPropExchange 成員函式,新增一個PX_Font函式的呼叫,提供自定義字型屬性的初始化和持久化。
void CSampleCtrl::DoPropExchange(CPropExchange* pPX)
{
   COleControl::DoPropExchange(pPX);
    // [...other PX_ function calls...]
    PX_Font(pPX, _T("HeadingFont"), m_fontHeading, &_fontdescHeading);
}      
完成控制元件的GetHeadingFont成員函式。
LPFONTDISP CSampleCtrl::GetHeadingFont( )
{
    return m_fontHeading.GetFontDispatch( );
}      
完成控制元件的SetHeadingFont成員函式
void CSampleControl::SetHeadingFont( LPFONTDISP newValue )
{
    m_fontHeading.InitializeFont( &_fontdescHeading, newValue);
    OnFontChanged();    //notify any changes
    SetModifiedFlag( );
}      
修改控制元件的OnDraw成員函式,定義一個變數控制以前選擇的字型。
CFont* pOldHeadingFont;     
修改控制元件的OnDraw成員函式,新增下列程式碼,在裝置上下文中選擇自定義的字型。
pOldHeadingFont = SelectFontObject(pdc, m_fontHeading);      
修改控制元件的OnDraw成員函式,字型使用完後恢復原字型到裝置上下文。
pdc->SelectObject(pOldHeadingFont);      
新增標準字型屬性頁自定義字型屬性設定完成後,應新增標準字型屬性頁,允許控制元件使用者更改控制元件當前的字型。為標準字型屬性頁增加屬性頁的ID號, 在BEGIN_PROPPAGEIDS巨集後新增如下行:
PROPPAGEID(CLSID_CFontPropPage)      
完成這些工作後,重新編譯工程。

例程2:Label1.ocx

  例程2的Label1控制元件與例程1的Label控制元件在功能實現上沒有任何區別,只是在改變字型特性時,不再使用庫存字型屬性Font,而是使用自定義字型屬性CaptionFont。下面我們將結合Label1控制元件介紹如何在控制元件中使用自定義屬性。
開啟Visual C++ 6.0,按照例程1的操作步驟新建Label1工程,象例程1那樣接受所有預設設定, 完成Label1工程建立。如圖2-1。


圖2-1

使用ClassWizard 給控制元件增加庫存屬性BackColor,ForeColor,Caption

  1. 單擊View選單的ClassWizard開啟 ClassWizard;
  2. 單擊Automation標籤;
  3. Class Name下拉列表框選擇CLabel1Ctrl,單擊 Add Property;
  4. 在External name框中,單擊BackColor;
  5. 單擊OK;
  6. 單擊OK確認你的選擇並關閉ClassWizard;

  按上述同樣操作,新增庫存屬性ForeColor,Caption。BackColor,ForeColor,Caption這三個屬性分別用來設定Label1控制元件的背景色,前景色和字串內容。如圖2-2。


圖2-2

使用ClassWizard 給控制元件增加自定義屬性CaptionFont

  1. 單擊View選單的ClassWizard開啟 ClassWizard;
  2. 單擊Automation標籤;
  3. Class Name下拉列表框選擇CLabel1Ctrl,單擊 Add Property;
  4. 在External name框中,輸入自定義屬性名CaptionFont;
  5. 在Implementation框中,單擊Get/Set methods;
  6. 在Return Type框中,選擇LPFONTDISP作為屬性型別;
  7. 單擊OK;
  8. 單擊OK確認你的選擇並關閉ClassWizard;

如圖2-3


圖2-3
 

修改控制元件程式碼

在控制元件的標頭檔案(Label1Ctl.h),新增一個protected成員變數的宣告:

protected:
CFontHolder m_fontCaption;

如圖2-4。


圖2-4

在控制元件的執行檔案(.CPP)中,如下操作:在控制元件的建構函式中初始化 m_fontCaption。

CLabel1Ctrl::CLabel1Ctrl(): m_fontCaption(&m_xFontNotification)
{
  InitializeIIDs(&IID_DLabel1, &IID_DLabel1Events);
  // 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_Font函式的呼叫,提供自定義字型屬性的初始化和持久化。

void CLabel1Ctrl::DoPropExchange(CPropExchange* pPX)
{
  ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  COleControl::DoPropExchange(pPX);
  PX_Font(pPX, _T("CaptionFont"), m_fontCaption, &_fontdescCaption);
}

完成控制元件的GetCaptionFont成員函式。

LPFONTDISP CLabel1Ctrl::GetCaptionFont() 
{
  // TODO: Add your property handler here
  return m_fontCaption.GetFontDispatch();
}

完成控制元件的SetHeadingFont成員函式

void CLabel1Ctrl::SetCaptionFont(LPFONTDISP newValue) 
{
	// TODO: Add your property handler here
    m_fontCaption.InitializeFont(&_fontdescCaption,newValue);
	OnFontChanged();
	SetModifiedFlag();
}
修改控制元件的OnDraw成員函式,
void CLabel1Ctrl::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);
     //前景色設定為字型顏色
	const CString& strCaption = InternalGetText();
     //獲得庫存屬性Caption的值
	CFont* pOldFont;
	pOldFont = SelectFontObject(pdc,m_fontCaption);
     //裝置上下文中選擇字型物件
	RECT rect;
	::CopyRect(&rect,rcBounds);
	pdc->DrawText(strCaption,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
     //單行,水平居中,垂直居中顯示
	pdc->SelectObject(pOldFont);
}
新增顏色屬性頁和字型屬性頁開啟工程的Label1Ctl.cpp檔案,將其中的如下程式碼進行修改:
BEGIN_PROPPAGEIDS(CLabel1Ctrl, 1)
	PROPPAGEID(CLabelPropPage::guid)
END_PROPPAGEIDS(CLabel1Ctrl)
修改後的程式碼:
BEGIN_PROPPAGEIDS(CLabel1Ctrl, 3) // 具體個數由實際情況而定
	PROPPAGEID(CLabel1PropPage::guid)//系統自帶的屬性頁
	PROPPAGEID(CLSID_CColorPropPage) //加入Color屬性頁
	PROPPAGEID(CLSID_CFontPropPage) //加入Font屬性頁
END_PROPPAGEIDS(CLabel1Ctrl) 
修改系統自帶的屬性頁

  開啟系統自帶的屬性頁資源IDD_PROPPAGE_LABEL1,將靜態文字框IDC_STATIC的內容改為"Caption:",新增一個編輯框(Edit Box)控制元件,控制元件ID為IDC_CAPTION。如圖2-5。


圖2-5

  按下"Ctrl+W"組合鍵開啟ClassWizard,選中Member Variables標籤,Class name:下拉列表框選擇CLabel1PropPage,Control IDs:選中IDC_CAPTION,單擊Add Variable…按鈕,彈出Add Member Variable對話方塊。
  在Add Member Variable對話方塊中,Member variable name:框輸入m_caption,Category選擇Value,Variable type:框選擇CString,Optional property name:框選擇Caption,單擊OK按鈕。
再次單擊OK按鈕關閉ClassWizard。
  上述操作,編輯框IDC_CAPTION與Caption屬性之間建立了聯絡。您可以通過修改編輯框的內容來改變控制元件Caption的屬性值。
編譯並構建Label1.ocx控制元件。