[Attributes] 탭에서 'Interface'(Dual or Custom), 'Aggregation', 'Support ISupportErrorInfo', 'Support Connection Points'등을 선택할 수 있다.
[Miscellaneous] 탭에서 [Add control based on] 콤보 상자에서 원하는 표준 컨트롤을 선택할 수 있다.
[Stock Properties] 탭에서 스톡 프로퍼티를 추가한다.
4. 프로퍼티 페이지 추가
접기
interface ICircleCtrl : IDispatch
{
[propput, id(DISPID_BACKCOLOR)]
HRESULT BackColor([in]OLE_COLOR clr);
[propget, id(DISPID_BACKCOLOR)]
HRESULT BackColor([out,retval]OLE_COLOR* pclr);
[propputref, id(DISPID_FONT)]
HRESULT Font([in]IFontDisp* pFont);
[propput, id(DISPID_FONT)]
HRESULT Font([in]IFontDisp* pFont);
[propget, id(DISPID_FONT)]
HRESULT Font([out, retval]IFontDisp** ppFont);
[propput, id(DISPID_FORECOLOR)] HRESULT ForeColor([in]OLE_COLOR clr); [propget, id(DISPID_FORECOLOR)] HRESULT ForeColor([out,retval]OLE_COLOR* pclr);
[propput, id(DISPID_CAPTION)]
HRESULT Caption([in]BSTR strCaption);
[propget, id(DISPID_CAPTION)]
HRESULT Caption([out,retval]BSTR* pstrCaption);
[propget, id(1), helpstring("property FlashColor")] HRESULT FlashColor([out, retval] OLE_COLOR *pVal);
[propput, id(1), helpstring("property FlashColor")] HRESULT FlashColor([in] OLE_COLOR newVal);
[id(2), helpstring("method Flash")] HRESULT Flash();
};
class ATL_NO_VTABLE CCircleCtrl :
...
public CProxy_ICircleCtrlEvents< CCircleCtrl >
{
public:
CCircleCtrl()
{
// {
// 스톡 프로퍼티 m_bstrCaption = _T("Click Here"); m_clrBackColor = RGB(255, 255, 255); m_clrForeColor = RGB(0, 0, 0); // 사용자 정의 프로퍼티 m_clrFlashColor = RGB(255, 0, 0); m_bFlash = FALSE;
// }
}
...
BEGIN_COM_MAP(CCircleCtrl)
...
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
BEGIN_PROP_MAP(CCircleCtrl)
...
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
PROP_ENTRY("BackColor", DISPID_BACKCOLOR, CLSID_StockColorPage) PROP_ENTRY("ForeColor", DISPID_FORECOLOR, CLSID_StockColorPage)
PROP_ENTRY("Caption", DISPID_CAPTION, CLSID_CircleProp ) PROP_ENTRY("Font", DISPID_FONT, CLSID_StockFontPage) // Example entries
...
END_PROP_MAP()
BEGIN_CONNECTION_POINT_MAP(CCircleCtrl)
CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
CONNECTION_POINT_ENTRY(D IID__ICircleCtrlEvents)
END_CONNECTION_POINT_MAP()
BEGIN_MSG_MAP(CCircleCtrl)
...
DEFAULT_REFLECTION_HANDLER()
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUP)
END_MSG_MAP()
...
// ICircleCtrl
public:
STDMETHOD(Flash)(); STDMETHOD(get_FlashColor)(/*[out, retval]*/ OLE_COLOR *pVal); STDMETHOD(put_FlashColor)(/*[in]*/ OLE_COLOR newVal);
HRESULT OnDraw(ATL_DRAWINFO& di)
{
// {
if(m_bFlash) FillFlashColor(di); else DefaultDraw(di); m_Rect = *(RECT*)di.prcBounds;
// }
/* RECT& rc = *(RECT*)di.prcBounds;
Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
LPCTSTR pszText = _T("ATL 3.0 : CircleCtrl");
TextOut(di.hdcDraw,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
pszText,
lstrlen(pszText));
*/
return S_OK;
}
OLE_COLOR m_clrBackColor; CComBSTR m_bstrCaption; CComPtr<IFontDisp> m_pFont; OLE_COLOR m_clrForeColor;
LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// TODO : Add Code for message handler. Call DefWindowProc if necessary.
// {
OLE_XPOS_PIXELS x = LOWORD(lParam); OLE_XPOS_PIXELS y = HIWORD(lParam); if (InCircle(x, y)) { Fire_ClickInside(x, y); m_bFlash = TRUE; FireViewChange(); }
// }
return 0;
}
LRESULT OnLButtonUP(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// TODO : Add Code for message handler. Call DefWindowProc if necessary.
// {
if(m_bFlash) { m_bFlash = FALSE; FireViewChange(); }
// }
return 0;
}
private: RECT m_Rect; bool InCircle(OLE_XPOS_PIXELS x, OLE_XPOS_PIXELS y); void DefaultDraw(ATL_DRAWINFO& di); void FillFlashColor(ATL_DRAWINFO& di); bool m_bFlash; OLE_COLOR m_clrFlashColor;
};
STDMETHODIMP CCircleCtrl::get_FlashColor(OLE_COLOR *pVal) { // TODO: Add your implementation code here // { *pVal = m_clrFlashColor; // } return S_OK; } STDMETHODIMP CCircleCtrl::put_FlashColor(OLE_COLOR newVal) { // TODO: Add your implementation code here // { m_clrFlashColor = newVal; // } return S_OK; }
STDMETHODIMP CCircleCtrl::Flash() { // TODO: Add your implementation code here // { m_bFlash = TRUE; FireViewChange(); Sleep(50); m_bFlash = FALSE; FireViewChange(); // } return S_OK; }
void CCircleCtrl::FillFlashColor(ATL_DRAWINFO& di) { RECT rc = *(RECT*)di.prcBounds; COLORREF color; HBRUSH hBrush; HGDIOBJ hOldBrush, hOldPen; // 검정색 펜 선택 hOldPen = SelectObject(di.hdcDraw, GetStockObject(BLACK_PEN)); // BackColor 브러시 선택 OleTranslateColor(m_clrBackColor, NULL, &color); hBrush = CreateSolidBrush(color); hOldBrush = SelectObject(di.hdcDraw, hBrush); // 사각형 그리기 (전체 화면을 지움) Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); // BackColor 브러시 삭제 SelectObject(di.hdcDraw, hOldBrush); DeleteObject(hBrush); // FlashColor 브러시 선택 OleTranslateColor(m_clrFlashColor, NULL, &color); hBrush = CreateSolidBrush(color); hOldBrush = SelectObject(di.hdcDraw, hBrush); // 원 그리기 Ellipse(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); // DC 복원 SelectObject(di.hdcDraw, hOldPen); SelectObject(di.hdcDraw, hOldBrush); // FlashColor 브러시 삭제 DeleteObject(hBrush); } void CCircleCtrl::DefaultDraw(ATL_DRAWINFO& di) { USES_CONVERSION; RECT rc = *(RECT*)di.prcBounds; COLORREF color; HBRUSH hBrush; HGDIOBJ hOldBrush, hOldPen, hOldFont=NULL; // 검정색 펜 선택 hOldPen = SelectObject(di.hdcDraw, GetStockObject(BLACK_PEN)); // BackColor 브러시 선택 OleTranslateColor(m_clrBackColor, NULL, &color); hBrush = CreateSolidBrush(color); hOldBrush = SelectObject(di.hdcDraw, hBrush); // 사각형 그리기 (전체 화면을 지움) Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); // 원 그리기 Ellipse(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); // 스톡 프로퍼티 Font 선택 if(m_pFont) { CComPtr<IFont> pFont; m_pFont->QueryInterface(IID_IFont, (void**)&pFont); HFONT hfont; pFont->get_hFont(&hfont); hOldFont = SelectObject(di.hdcDraw, hfont); } // 텍스트 그리기 OleTranslateColor(m_clrForeColor, NULL, &color); SetTextColor(di.hdcDraw, color); SetBkMode(di.hdcDraw, TRANSPARENT); DrawTextW(di.hdcDraw, m_bstrCaption, -1, (LPRECT)&rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); // DC 복원 if(hOldFont) SelectObject(di.hdcDraw, hOldFont); SelectObject(di.hdcDraw, hOldBrush); SelectObject(di.hdcDraw, hOldPen); // BackColor 브러시 삭제 DeleteObject(hBrush); } bool CCircleCtrl::InCircle(OLE_XPOS_PIXELS x, OLE_XPOS_PIXELS y) { // 반지름 계산 double a = (m_Rect.right - m_Rect.left) / 2; double b = (m_Rect.bottom - m_Rect.top) / 2; // 중심점 계산 double cx = x - (m_Rect.left + m_Rect.right) / 2; double cy = y - (m_Rect.top + m_Rect.bottom) / 2; // 타원의 공식 적용 return ((cx * cx) / (a * a) + (cy * cy) / (b * b) <= 1); }
class ATL_NO_VTABLE CCircleProp :
...
public CDialogImpl<CCircleProp>
{
...
BEGIN_MSG_MAP(CCircleProp)
...
COMMAND_HANDLER(IDC_EDIT1, EN_CHANGE, OnChangeEdit1)
END_MSG_MAP()
...
STDMETHODIMP CCircleProp::Apply(void)
{
ATLTRACE(_T("CCircleProp::Apply\n"));
USES_CONVERSION;
for (UINT i = 0; i < m_nObjects; i++)
{
// Do something interesting here
// ICircCtl* pCirc;
// m_ppUnk[i]->QueryInterface(IID_ICircCtl, (void**)&pCirc);
// pCirc->put_Caption(CComBSTR("something special"));
// pCirc->Release();
// {
TCHAR szCaption[100]; CComBSTR bstrCaption; GetDlgItemText(IDC_EDIT1, szCaption, sizeof(szCaption)); bstrCaption = T2OLE(szCaption); ICircleCtrl* pCirc; m_ppUnk[i]->QueryInterface(__uuidof(ICircleCtrl), (void**)&pCirc); pCirc->put_Caption(bstrCaption); pCirc->Release();
// }
}
m_bDirty = FALSE;
return S_OK;
}
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// TODO : Add Code for message handler. Call DefWindowProc if necessary.
// {
USES_CONVERSION; for (UINT i = 0; i < m_nObjects; i++) { CComBSTR bstrCaption; ICircleCtrl* pCirc; m_ppUnk[i]->QueryInterface(__uuidof(ICircleCtrl), (void**)&pCirc); pCirc->get_Caption(&bstrCaption); pCirc->Release(); SetDlgItemText(IDC_EDIT1, OLE2T(bstrCaption)); }
// }
return 0;
}
LRESULT OnChangeEdit1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { // TODO : Add Code for control notification handler. // { SetDirty(TRUE); // } return 0; }
};
접기