다음을 통해 공유


MFC ActiveX 컨트롤: 글꼴 사용

ActiveX 컨트롤에 텍스트가 표시되면 컨트롤 사용자가 글꼴 속성을 변경하여 텍스트 모양을 변경할 수 있습니다. 글꼴 속성은 글꼴 개체로 구현되며 주식 또는 사용자 지정의 두 가지 유형 중 하나일 수 있습니다. 스톡 글꼴 속성은 속성 추가 마법사를 사용하여 추가할 수 있는 미리 포함된 글꼴 속성입니다. 사용자 지정 글꼴 속성은 미리 지정되지 않으며 컨트롤 개발자는 속성의 동작 및 사용을 결정합니다.

이 문서에서는 다음 항목을 다룹니다.

Stock Font 속성 사용

스톡 글꼴 속성은 COleControl 클래스에 의해 미리 포함됩니다. 또한 표준 글꼴 속성 페이지도 사용할 수 있으므로 사용자가 글꼴 개체의 이름, 크기 및 스타일과 같은 다양한 특성을 변경할 수 있습니다.

의 GetFont, SetFontInternalGetFont 함수를 통해 글꼴 개체에 액세스합니다COleControl. 컨트롤 사용자는 다른 Get/Set 속성과 동일한 방식으로 및 SetFont 함수를 통해 GetFont 글꼴 개체에 액세스합니다. 컨트롤 내에서 글꼴 개체에 액세스해야 하는 경우 함수를 InternalGetFont 사용합니다.

MFC ActiveX 컨트롤: 속성에서 설명한 대로 속성 추가 마법사를 사용하면 주식 속성을 쉽게 추가할 수 있습니다. 글꼴 속성을 선택하면 속성 추가 마법사가 컨트롤의 디스패치 맵에 주식 글꼴 항목을 자동으로 삽입합니다.

속성 추가 마법사를 사용하여 stock Font 속성을 추가하려면

  1. 컨트롤의 프로젝트를 로드합니다.

  2. 클래스 뷰에서 컨트롤의 라이브러리 노드를 확장합니다.

  3. 컨트롤의 인터페이스 노드(라이브러리 노드의 두 번째 노드)를 마우스 오른쪽 단추로 클릭하여 바로 가기 메뉴를 엽니다.

  4. 바로 가기 메뉴에서 추가를 클릭한 다음, 속성 추가를 클릭합니다.

    그러면 속성 추가 마법사가 열립니다.

  5. 속성 이름 상자에서 글꼴을 클릭합니다.

  6. Finish를 클릭합니다.

속성 추가 마법사는 컨트롤 클래스 구현 파일에 있는 컨트롤의 디스패치 맵에 다음 줄을 추가합니다.

DISP_STOCKPROP_FONT()

또한 속성 추가 마법사는 컨트롤에 다음 줄을 추가합니다. IDL 파일:

[id(DISPID_FONT)] IFontDisp* Font;

stock Caption 속성은 stock Font 속성 정보를 사용하여 그릴 수 있는 텍스트 속성의 예입니다. 스톡 캡션 속성을 컨트롤에 추가하면 stock Font 속성에 사용되는 단계와 비슷한 단계가 사용됩니다.

속성 추가 마법사를 사용하여 스톡 Caption 속성을 추가하려면

  1. 컨트롤의 프로젝트를 로드합니다.

  2. 클래스 뷰에서 컨트롤의 라이브러리 노드를 확장합니다.

  3. 컨트롤의 인터페이스 노드(라이브러리 노드의 두 번째 노드)를 마우스 오른쪽 단추로 클릭하여 바로 가기 메뉴를 엽니다.

  4. 바로 가기 메뉴에서 추가를 클릭한 다음, 속성 추가를 클릭합니다.

    그러면 속성 추가 마법사가 열립니다.

  5. 속성 이름 상자에서 Caption을 클릭합니다.

  6. Finish를 클릭합니다.

속성 추가 마법사는 컨트롤 클래스 구현 파일에 있는 컨트롤의 디스패치 맵에 다음 줄을 추가합니다.

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 속성 특성과 함께 표시됩니다.

컨트롤에서 사용자 지정 글꼴 속성 사용

Stock Font 속성 외에도 ActiveX 컨트롤에는 사용자 지정 글꼴 속성이 있을 수 있습니다. 사용자 지정 글꼴 속성을 추가하려면 다음을 수행해야 합니다.

사용자 지정 글꼴 속성 구현

사용자 지정 글꼴 속성을 구현하려면 속성 추가 마법사를 사용하여 속성을 추가한 다음 코드를 일부 수정합니다. 다음 섹션에서는 샘플 컨트롤에 사용자 지정 HeadingFont 속성을 추가하는 방법을 설명합니다.

속성 추가 마법사를 사용하여 사용자 지정 글꼴 속성을 추가하려면
  1. 컨트롤의 프로젝트를 로드합니다.

  2. 클래스 뷰에서 컨트롤의 라이브러리 노드를 확장합니다.

  3. 컨트롤의 인터페이스 노드(라이브러리 노드의 두 번째 노드)를 마우스 오른쪽 단추로 클릭하여 바로 가기 메뉴를 엽니다.

  4. 바로 가기 메뉴에서 추가를 클릭한 다음, 속성 추가를 클릭합니다.

    그러면 속성 추가 마법사가 열립니다.

  5. 속성 이름 상자에 속성의 이름을 입력합니다. 이 예제에서는 HeadingFont를 사용합니다.

  6. 구현 형식에서 Get/Set 메서드를 클릭합니다.

  7. 속성 형식 상자에서 속성 형식에 대한 IDispatch*를 선택합니다.

  8. Finish를 클릭합니다.

속성 추가 마법사는 클래스 및 SAMPLE에 HeadingFont 사용자 지정 속성을 CSampleCtrl 추가하는 코드를 만듭니다. IDL 파일입니다. HeadingFont Get/Set 속성 형식이므로 속성 추가 마법사는 DISP_PROPERTY_EX_ID DISP_PROPERTY_EX 매크로 항목을 포함하도록 클래스의 디스패치 맵을 수정합니다CSampleCtrl.

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

DISP_PROPERTY_EX 매크로는 속성 이름을 해당 CSampleCtrl 클래스 Get 및 Set 메서드 GetHeadingFont 와 연결 HeadingFont 합니다SetHeadingFont. 속성 값의 형식도 지정됩니다. 이 경우 VT_FONT.

속성 추가 마법사는 컨트롤 헤더 파일()에도 선언을 추가합니다. 및 SetHeadingFont 함수에 GetHeadingFont 대한 H를 사용하고 해당 함수 템플릿을 컨트롤 구현 파일()에 추가합니다. 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 속성 페이지의 속성 페이지 ID를 추가하려면 BEGIN_PROPPAGEIDS 매크로 뒤에 다음 줄을 삽입합니다.

PROPPAGEID(CLSID_CFontPropPage)

또한 BEGIN_PROPPAGEIDS 매크로의 count 매개 변수를 하나씩 증가시켜야 합니다. 다음 줄에서는 이 작업을 보여 줍니다.

BEGIN_PROPPAGEIDS(CMyAxFontCtrl, 2)

이러한 변경이 완료되면 전체 프로젝트를 다시 빌드하여 추가 기능을 통합합니다.

글꼴 알림 처리

대부분의 경우 컨트롤은 글꼴 개체의 특성이 수정된 시기를 알아야 합니다. 각 글꼴 개체는 인터페이스COleControl의 멤버 함수 IFontNotification 를 호출하여 변경될 때 알림을 제공할 수 있습니다.

컨트롤이 stock Font 속성을 사용하는 경우 해당 알림은 의 COleControl멤버 함수에 OnFontChanged 의해 처리됩니다. 사용자 지정 글꼴 속성을 추가할 때 동일한 구현을 사용하도록 할 수 있습니다. 이전 섹션의 예제에서는 m_fontHeading 멤버 변수를 초기화할 때 &m_xFontNotification 전달하여 이 작업을 수행했습니다.

Implementing multiple font object interfaces.
여러 글꼴 개체 인터페이스 구현

위 그림의 실선은 두 글꼴 개체가 동일한 구현 IFontNotification을 사용하고 있음을 보여줍니다. 변경된 글꼴을 구분하려는 경우 문제가 발생할 수 있습니다.

컨트롤의 글꼴 개체 알림을 구분하는 한 가지 방법은 컨트롤의 각 글꼴 개체에 대한 인터페이스의 IFontNotification 별도 구현을 만드는 것입니다. 이 기술을 사용하면 최근에 수정된 글꼴을 사용하는 문자열 또는 문자열만 업데이트하여 그리기 코드를 최적화할 수 있습니다. 다음 섹션에서는 두 번째 Font 속성에 대해 별도의 알림 인터페이스를 구현하는 데 필요한 단계를 보여 줍니다. 두 번째 글꼴 속성은 이전 섹션에서 추가된 속성으로 간주됩니다 HeadingFont .

새 글꼴 알림 인터페이스 구현

둘 이상의 글꼴 알림을 구분하려면 컨트롤에 사용되는 각 글꼴에 대해 새 알림 인터페이스를 구현해야 합니다. 다음 섹션에서는 컨트롤 헤더 및 구현 파일을 수정하여 새 글꼴 알림 인터페이스를 구현하는 방법을 설명합니다.

헤더 파일에 추가

컨트롤 헤더 파일(. 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;
}

AddRef 인터페이스의 IPropertyNotifySink 메서드 및 Release ActiveX 컨트롤 개체에 대 한 참조 수를 추적 합니다. 컨트롤이 인터페이스 포인터에 대한 액세스를 가져오면 컨트롤이 참조 횟수를 증가하도록 호출 AddRef 합니다. 컨트롤이 포인터로 완료되면 전역 메모리 블록을 해제하기 위해 호출될 수 있는 GlobalFree 것과 거의 동일한 방식으로 호출Release됩니다. 이 인터페이스에 대한 참조 수가 0으로 이동하면 인터페이스 구현을 해제할 수 있습니다. 이 예제에서 함수는 QueryInterface 특정 개체의 IPropertyNotifySink 인터페이스에 대한 포인터를 반환합니다. 이 함수를 사용하면 ActiveX 컨트롤이 개체를 쿼리하여 지원하는 인터페이스를 확인할 수 있습니다.

프로젝트가 변경된 후 프로젝트를 다시 빌드하고 테스트 컨테이너를 사용하여 인터페이스를 테스트합니다. 테스트 컨테이너에 액세스하는 방법은 테스트 컨테이너로 속성 및 이벤트 테스트 를 참조하세요.

참고 항목

MFC ActiveX 컨트롤
MFC ActiveX 컨트롤: ActiveX 컨트롤에서 그림 사용하기
MFC ActiveX 컨트롤: 스톡 속성 페이지 사용