次の方法で共有


MFC ActiveX コントロール: フォントの使用

ActiveX コントロールにテキストが表示される場合は、フォント プロパティを変更することで、コントロール ユーザーにテキストの外観の変更を許可できます。 フォント プロパティはフォント オブジェクトとして実装され、ストックまたはカスタムの 2 種類のいずれかになります。 ストック フォント プロパティは、プロパティの追加ウィザードを使用して追加できる、事前に実装されたフォント プロパティです。 カスタム フォント プロパティは事前実装されておらず、コントロール開発者がプロパティの動作と使用方法を決定します。

この記事では、次のトピックについて説明します。

Stock Font プロパティの使用

Stock Font プロパティは、 COleControl クラスによって事前実装されます。 さらに、標準の Font プロパティ ページも使用でき、ユーザーはフォント オブジェクトのさまざまな属性 (名前、サイズ、スタイルなど) を変更できます。

COleControlGetFontSetFontInternalGetFont 関数を使用してフォント オブジェクトにアクセスします。 コントロール ユーザーは、他の Get/Set プロパティと同じ方法で、 GetFont および SetFont 関数を使用してフォント オブジェクトにアクセスします。 コントロール内からフォント オブジェクトへのアクセスが必要な場合は、 InternalGetFont 関数を使用します。

「MFC ActiveX コントロール: プロパティ」で説明したように、プロパティの追加ウィザードを使用すると、ストック プロパティを簡単に追加できます。 Font プロパティを選択すると、プロパティの追加ウィザードによってストック Font エントリがコントロールのディスパッチ マップに自動的に挿入されます。

プロパティの追加ウィザードを使用してストック Font プロパティを追加するには

  1. コントロールのプロジェクトを読み込みます。

  2. クラス ビューで、コントロールのライブラリ ノードを展開します。

  3. コントロールのインターフェイス ノード (ライブラリ ノードの 2 番目のノード) を右クリックして、ショートカット メニューを開きます。

  4. ショートカット メニューの [ 追加 ] をクリックし、[ プロパティの追加] をクリックします。

    プロパティの追加ウィザードが開きます。

  5. [ プロパティ名] ボックスで、[ フォント] をクリックします。

  6. [完了] をクリックします。

プロパティの追加ウィザードは、コントロール クラスの実装ファイルにあるコントロールのディスパッチ マップに次の行を追加します。

DISP_STOCKPROP_FONT()

さらに、プロパティの追加ウィザードは、コントロールに次の行を追加します。IDL ファイル:

[id(DISPID_FONT)] IFontDisp* Font;

stock Caption プロパティは、ストック Font プロパティ情報を使用して描画できるテキスト プロパティの例です。 コントロールに stock Caption プロパティを追加すると、stock Font プロパティに使用されるものと同様の手順が使用されます。

プロパティの追加ウィザードを使用してストック キャプション プロパティを追加するには

  1. コントロールのプロジェクトを読み込みます。

  2. クラス ビューで、コントロールのライブラリ ノードを展開します。

  3. コントロールのインターフェイス ノード (ライブラリ ノードの 2 番目のノード) を右クリックして、ショートカット メニューを開きます。

  4. ショートカット メニューの [ 追加 ] をクリックし、[ プロパティの追加] をクリックします。

    プロパティの追加ウィザードが開きます。

  5. [ プロパティ名] ボックスで、[ キャプション] をクリックします。

  6. [完了] をクリックします。

プロパティの追加ウィザードは、コントロール クラスの実装ファイルにあるコントロールのディスパッチ マップに次の行を追加します。

DISP_STOCKPROP_CAPTION()

OnDraw 関数の変更

OnDrawの既定の実装では、コントロールに表示されるすべてのテキストに Windows システム フォントが使用されます。 つまり、デバイス コンテキストにフォント オブジェクトを選択して、 OnDraw コードを変更する必要があります。 これを行うには、 COleControl::SelectStockFont を呼び出し、次の例に示すように、コントロールのデバイス コンテキストを渡します。

CFont* pOldFont;
TEXTMETRIC tm;
const CString& strCaption = InternalGetText();

pOldFont = SelectStockFont(pdc);
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
pdc->GetTextMetrics(&tm);
pdc->SetTextAlign(TA_CENTER | TA_TOP);
pdc->ExtTextOut((rcBounds.left + rcBounds.right) / 2,
(rcBounds.top + rcBounds.bottom - tm.tmHeight) / 2,
ETO_CLIPPED, rcBounds, strCaption, strCaption.GetLength(), NULL);

pdc->SelectObject(pOldFont);

OnDraw関数がフォント オブジェクトを使用するように変更されると、コントロール内のすべてのテキストがコントロールの stock Font プロパティの特性と共に表示されます。

コントロールでのカスタム フォント プロパティの使用

ストック Font プロパティに加えて、ActiveX コントロールにはカスタム フォント プロパティを設定できます。 カスタム フォント プロパティを追加するには、次の手順を実行する必要があります。

カスタム フォント プロパティの実装

カスタム Font プロパティを実装するには、プロパティの追加ウィザードを使用してプロパティを追加し、コードにいくつかの変更を加えます。 次のセクションでは、カスタム HeadingFont プロパティを Sample コントロールに追加する方法について説明します。

プロパティの追加ウィザードを使用してカスタム Font プロパティを追加するには
  1. コントロールのプロジェクトを読み込みます。

  2. クラス ビューで、コントロールのライブラリ ノードを展開します。

  3. コントロールのインターフェイス ノード (ライブラリ ノードの 2 番目のノード) を右クリックして、ショートカット メニューを開きます。

  4. ショートカット メニューの [ 追加 ] をクリックし、[ プロパティの追加] をクリックします。

    プロパティの追加ウィザードが開きます。

  5. [ プロパティ名] ボックスに、プロパティの名前を入力します。 この例では、 HeadingFont を使用します

  6. [実装の種類] で、[Get/Set メソッド] をクリックします。

  7. [ プロパティの種類 ] ボックスで、プロパティの種類として [IDispatch* を選択します。

  8. [完了] をクリックします。

プロパティの追加ウィザードは、CSampleCtrl クラスと SAMPLE にHeadingFontカスタム プロパティを追加するコードを作成します。IDL ファイル。 HeadingFontは Get/Set プロパティ型であるため、プロパティの追加ウィザードは、CSampleCtrl クラスのディスパッチ マップを変更して、DISP_PROPERTY_EX_ID DISP_PROPERTY_EXマクロ エントリを含めます。

DISP_PROPERTY_EX_ID(CMyAxFontCtrl, "HeadingFont", dispidHeadingFont,
   GetHeadingFont, SetHeadingFont, VT_DISPATCH)

DISP_PROPERTY_EX マクロは、 HeadingFont プロパティ名を、対応する CSampleCtrl クラスの Get メソッドと Set メソッド、 GetHeadingFont メソッド、および SetHeadingFontに関連付けます。 プロパティ値の型も指定されます。この場合は、VT_FONT。

プロパティの追加ウィザードでは、コントロール ヘッダー ファイル (.H) を使用して、 GetHeadingFont 関数と SetHeadingFont 関数のテンプレートをコントロール実装ファイル (.CPP):

IDispatch* CWizardGenCtrl::GetHeadingFont(void)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());

   // TODO: Add your dispatch handler code here

   return NULL;
}

void CWizardGenCtrl::SetHeadingFont(IDispatch* /*pVal*/)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());

   // TODO: Add your property handler code here

   SetModifiedFlag();
}

最後に、プロパティの追加ウィザードによってコントロールが変更されます。 HeadingFont プロパティのエントリを追加して IDL ファイルを作成します。

[id(1)] IDispatch* HeadingFont;

コントロール コードの変更

HeadingFont プロパティをコントロールに追加したら、新しいプロパティを完全にサポートするために、コントロール ヘッダーと実装ファイルにいくつかの変更を加える必要があります。

コントロール ヘッダー ファイル (.H)、保護されたメンバー変数の次の宣言を追加します。

protected:
   CFontHolder m_fontHeading;

コントロール実装ファイル (.CPP)、次の操作を行います。

  • コントロール コンストラクターで m_fontHeading を初期化します。

    CMyAxFontCtrl::CMyAxFontCtrl()
       : m_fontHeading(&m_xFontNotification)
    {
       InitializeIIDs(&IID_DNVC_MFC_AxFont, &IID_DNVC_MFC_AxFontEvents);
    }
    
  • フォントの既定の属性を含む静的 FONTDESC 構造体を宣言します。

    static const FONTDESC _fontdescHeading =
    { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE(12), FW_BOLD,
      ANSI_CHARSET, FALSE, FALSE, FALSE };
    
  • コントロール DoPropExchange メンバー関数で、 PX_Font 関数の呼び出しを追加します。 これにより、カスタム Font プロパティの初期化と永続化が提供されます。

    void CMyAxFontCtrl::DoPropExchange(CPropExchange* pPX)
    {
       ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
       COleControl::DoPropExchange(pPX);
    
       // [...other PX_ function calls...]
       PX_Font(pPX, _T("HeadingFont"), m_fontHeading, &_fontdescHeading);
    }
    
  • メンバー関数 GetHeadingFont コントロールの実装を完了します。

    IDispatch* CMyAxFontCtrl::GetHeadingFont(void)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       return m_fontHeading.GetFontDispatch();
    }
    
  • メンバー関数 SetHeadingFont コントロールの実装を完了します。

    void CMyAxFontCtrl::SetHeadingFont(IDispatch* pVal)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       m_fontHeading.InitializeFont(&_fontdescHeading, pVal);
       OnFontChanged();    //notify any changes
       SetModifiedFlag();
    }
    
  • コントロール OnDraw メンバー関数を変更して、以前に選択したフォントを保持する変数を定義します。

    CFont* pOldHeadingFont;
    
  • コントロール OnDraw メンバー関数を変更し、フォントを使用する場所に次の行を追加して、デバイス コンテキストにカスタム フォントを選択します。

    pOldHeadingFont = SelectFontObject(pdc, m_fontHeading);
    
  • コントロール OnDraw メンバー関数を変更し、フォントの使用後に次の行を追加して、前のフォントをデバイス コンテキストに戻します。

    pdc->SelectObject(pOldHeadingFont);
    

カスタム Font プロパティが実装されたら、標準の Font プロパティ ページを実装し、コントロール ユーザーがコントロールの現在のフォントを変更できるようにする必要があります。 標準の Font プロパティ ページのプロパティ ページ ID を追加するには、BEGIN_PROPPAGEIDS マクロの後に次の行を挿入します。

PROPPAGEID(CLSID_CFontPropPage)

また、BEGIN_PROPPAGEIDS マクロの count パラメーターを 1 ずつインクリメントする必要があります。 次の行は、これを示しています。

BEGIN_PROPPAGEIDS(CMyAxFontCtrl, 2)

これらの変更が行われた後、プロジェクト全体を再構築して追加の機能を組み込みます。

フォント通知の処理

ほとんどの場合、コントロールは、フォント オブジェクトの特性が変更されたタイミングを認識する必要があります。 各フォント オブジェクトは、COleControlによって実装されるIFontNotification インターフェイスのメンバー関数を呼び出すことによって、変更されたときに通知を提供できます。

コントロールが stock Font プロパティを使用している場合、その通知はCOleControlOnFontChangedメンバー関数によって処理されます。 カスタム フォント プロパティを追加するときに、同じ実装を使用させることができます。 前のセクションの例では、これは、m_fontHeading メンバー変数を初期化するときに &m_xFontNotificationを渡すことによって実現されました。

複数のフォント オブジェクト インターフェイスの実装。
複数のフォント オブジェクト インターフェイスの実装

上の図の実線は、両方のフォント オブジェクトが同じ実装の IFontNotificationを使用していることを示しています。 これにより、変更されたフォントを区別する場合に問題が発生する可能性があります。

コントロールのフォント オブジェクト通知を区別する 1 つの方法は、コントロール内のフォント オブジェクトごとに、 IFontNotification インターフェイスの個別の実装を作成することです。 この手法を使用すると、最近変更されたフォントを使用する文字列のみを更新して、描画コードを最適化できます。 次のセクションでは、2 番目の Font プロパティに個別の通知インターフェイスを実装するために必要な手順を示します。 2 番目の font プロパティは、前のセクションで追加された HeadingFont プロパティと見なされます。

新しいフォント通知インターフェイスの実装

2 つ以上のフォントの通知を区別するには、コントロールで使用されるフォントごとに新しい通知インターフェイスを実装する必要があります。 次のセクションでは、コントロール ヘッダーと実装ファイルを変更して、新しいフォント通知インターフェイスを実装する方法について説明します。

ヘッダー ファイルへの追加

コントロール ヘッダー ファイル (.H) クラス宣言に次の行を追加します。

protected:
   BEGIN_INTERFACE_PART(HeadingFontNotify, IPropertyNotifySink)
      INIT_INTERFACE_PART(CMyAxFontCtrl, HeadingFontNotify)
      STDMETHOD(OnRequestEdit)(DISPID);
   STDMETHOD(OnChanged)(DISPID);
   END_INTERFACE_PART(HeadingFontNotify)

これにより、HeadingFontNotifyと呼ばれるIPropertyNotifySink インターフェイスの実装が作成されます。 この新しいインターフェイスには、 OnChangedという名前のメソッドが含まれています。

実装ファイルへの追加

(コントロール コンストラクター内の) 見出しフォントを初期化するコードで、&m_xFontNotification を &m_xHeadingFontNotify に変更します。 次のコードを追加します。

STDMETHODIMP_(ULONG) CMyAxFontCtrl::XHeadingFontNotify::AddRef()
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      return 1;
}
STDMETHODIMP_(ULONG) CMyAxFontCtrl::XHeadingFontNotify::Release()
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      return 0;
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::QueryInterface(REFIID iid, LPVOID FAR* ppvObj)
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IPropertyNotifySink))
      {
         *ppvObj = this;
         AddRef();
         return NOERROR;
      }
   return ResultFromScode(E_NOINTERFACE);
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::OnChanged(DISPID)
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      pThis->InvalidateControl();
   return NOERROR;
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::OnRequestEdit(DISPID)
{
   return NOERROR;
}

IPropertyNotifySink インターフェイスのAddRefメソッドとReleaseメソッドは、ActiveX コントロール オブジェクトの参照カウントを追跡します。 コントロールがインターフェイス ポインターへのアクセスを取得すると、コントロールは参照カウントをインクリメントするために AddRef を呼び出します。 ポインターを使用してコントロールが終了すると、グローバル メモリ ブロックを解放するためにGlobalFreeが呼び出されるのとほぼ同じ方法で、Releaseが呼び出されます。 このインターフェイスの参照カウントが 0 になると、インターフェイスの実装を解放できます。 この例では、 QueryInterface 関数は、特定のオブジェクトの IPropertyNotifySink インターフェイスへのポインターを返します。 この関数を使用すると、ActiveX コントロールはオブジェクトに対してクエリを実行して、サポートされているインターフェイスを決定できます。

これらの変更がプロジェクトに加えられたら、プロジェクトをリビルドし、テスト コンテナーを使用してインターフェイスをテストします。 Test Container にアクセスする方法について詳しくは、「 テスト コンテナーでのプロパティとイベントのテスト 」をご覧ください。

こちらも参照ください

MFC ActiveX コントロール
MFC ActiveX コントロール: ActiveX コントロールでの画像の使用
MFC ActiveX コントロール: ストック プロパティ ページの使用