📄 mfccirclectl.cpp
字号:
// MfcCircleCtl.cpp : Implementation of the CMfcCircleCtrl ActiveX Control class.
#include "stdafx.h"
#include "MfcAxCtl.h"
#include "MfcCircleCtl.h"
#include "MfcCirclePpg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CMfcCircleCtrl, COleControl)
/////////////////////////////////////////////////////////////////////////////
// Message map
BEGIN_MESSAGE_MAP(CMfcCircleCtrl, COleControl)
//{{AFX_MSG_MAP(CMfcCircleCtrl)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Dispatch map
BEGIN_DISPATCH_MAP(CMfcCircleCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CMfcCircleCtrl)
DISP_PROPERTY_NOTIFY(CMfcCircleCtrl, "CircleShape", m_circleShape, OnCircleShapeChanged, VT_BOOL)
DISP_PROPERTY_NOTIFY(CMfcCircleCtrl, "FlashColor", m_flashColor, OnFlashColorChanged, VT_COLOR)
DISP_PROPERTY_EX(CMfcCircleCtrl, "CircleOffset", GetCircleOffset, SetCircleOffset, VT_I2)
DISP_STOCKPROP_CAPTION()
DISP_STOCKPROP_FONT()
DISP_STOCKPROP_FORECOLOR()
DISP_STOCKPROP_BACKCOLOR()
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CMfcCircleCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
/////////////////////////////////////////////////////////////////////////////
// Event map
BEGIN_EVENT_MAP(CMfcCircleCtrl, COleControl)
//{{AFX_EVENT_MAP(CMfcCircleCtrl)
EVENT_CUSTOM("ClickIn", FireClickIn, VTS_XPOS_PIXELS VTS_YPOS_PIXELS)
EVENT_CUSTOM("ClickOut", FireClickOut, VTS_XPOS_PIXELS VTS_YPOS_PIXELS)
//}}AFX_EVENT_MAP
END_EVENT_MAP()
/////////////////////////////////////////////////////////////////////////////
// Property pages
// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CMfcCircleCtrl, 3)
PROPPAGEID(CMfcCirclePropPage::guid)
PROPPAGEID(CLSID_CColorPropPage)
PROPPAGEID(CLSID_CFontPropPage)
END_PROPPAGEIDS(CMfcCircleCtrl)
/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CMfcCircleCtrl, "MFCAXCTL.MfcCircleCtrl.1",
0x104add88, 0x68b8, 0x11d4, 0xa5, 0x4d, 0, 0x50, 0xba, 0xdb, 0x14, 0xa3)
/////////////////////////////////////////////////////////////////////////////
// Type library ID and version
IMPLEMENT_OLETYPELIB(CMfcCircleCtrl, _tlid, _wVerMajor, _wVerMinor)
/////////////////////////////////////////////////////////////////////////////
// Interface IDs
const IID BASED_CODE IID_DMfcCircle =
{ 0x104add86, 0x68b8, 0x11d4, { 0xa5, 0x4d, 0, 0x50, 0xba, 0xdb, 0x14, 0xa3 } };
const IID BASED_CODE IID_DMfcCircleEvents =
{ 0x104add87, 0x68b8, 0x11d4, { 0xa5, 0x4d, 0, 0x50, 0xba, 0xdb, 0x14, 0xa3 } };
/////////////////////////////////////////////////////////////////////////////
// Control type information
static const DWORD BASED_CODE _dwMfcCircleOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CMfcCircleCtrl, IDS_MFCCIRCLE, _dwMfcCircleOleMisc)
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::CMfcCircleCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CMfcCircleCtrl
BOOL CMfcCircleCtrl::CMfcCircleCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: Verify that your control follows apartment-model threading rules.
// Refer to MFC TechNote 64 for more information.
// If your control does not conform to the apartment-model rules, then
// you must modify the code below, changing the 6th parameter from
// afxRegApartmentThreading to 0.
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_MFCCIRCLE,
IDB_MFCCIRCLE,
afxRegApartmentThreading,
_dwMfcCircleOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::CMfcCircleCtrl - Constructor
CMfcCircleCtrl::CMfcCircleCtrl()
{
InitializeIIDs(&IID_DMfcCircle, &IID_DMfcCircleEvents);
// TODO: Initialize your control's instance data here.
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::~CMfcCircleCtrl - Destructor
CMfcCircleCtrl::~CMfcCircleCtrl()
{
// TODO: Cleanup your control's instance data here.
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::OnDraw - Drawing function
void CMfcCircleCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
CBrush* pOldBrush;
CBrush bkBrush(TranslateColor(GetBackColor()));
CPen* pOldPen;
CRect rc = rcBounds;
CFont* pOldFont;
TEXTMETRIC tm;
const CString& strCaption = InternalGetText();
// 设置文字颜色和透明背景模式
pdc->SetTextColor(TranslateColor(GetForeColor()));
pdc->SetBkMode(TRANSPARENT);
// 使用背景色绘制背景
pdc->FillRect(rcBounds, &bkBrush);
// 使用黑色笔绘制圆的轮廓并用被景色填充
GetDrawRect(&rc);
pOldBrush = pdc->SelectObject(&bkBrush);
pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
pdc->Ellipse(rc);
// 使用公共字体属性和前景颜色绘制文本
pOldFont = SelectStockFont(pdc);
GetStockTextMetrics(&tm);
pdc->SetTextAlign(TA_CENTER | TA_TOP);
pdc->ExtTextOut((rc.left + rc.right) / 2, (rc.top + rc.bottom - tm.tmHeight) / 2,
ETO_CLIPPED, rc, strCaption, strCaption.GetLength(), NULL);
pdc->SelectObject(pOldFont);
pdc->SelectObject(pOldPen);
pdc->SelectObject(pOldBrush);
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::DoPropExchange - Persistence support
void CMfcCircleCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
PX_Bool(pPX, _T("CircleShape"), m_circleShape, TRUE);
PX_Short(pPX, _T("CircleOffset"), m_circleOffset, 0);
PX_Long(pPX, _T("FlashColor"), (long &)m_flashColor, RGB(0xFF, 0x00, 0x00));
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::OnResetState - Reset control to default state
void CMfcCircleCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
// TODO: Reset any other control state here.
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl::AboutBox - Display an "About" box to the user
void CMfcCircleCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_MFCCIRCLE);
dlgAbout.DoModal();
}
/////////////////////////////////////////////////////////////////////////////
// CMfcCircleCtrl message handlers
void CMfcCircleCtrl::OnCircleShapeChanged()
{
// TODO: Add notification handler code
// 强制刷新控件
InvalidateControl();
SetModifiedFlag();
}
short CMfcCircleCtrl::GetCircleOffset()
{
// TODO: Add your property handler here
return m_circleOffset;
}
void CMfcCircleCtrl::SetCircleOffset(short nNewValue)
{
// TODO: Add your property handler here
if ((m_circleOffset != nNewValue) &&
m_circleShape && InBounds(nNewValue))
{
m_circleOffset = nNewValue;
SetModifiedFlag();
InvalidateControl();
}
}
BOOL CMfcCircleCtrl::InBounds(short nOffset)
{
CRect rc;
int diameter;
int length;
int cx,cy;
// 得到控件绘图区域的大小
GetControlSize(&cx, &cy);
// 根据控件绘图区域大小计算圆的半径
if (cx > cy)
{
length = cx;
diameter = cy;
}
else
{
length = cy;
diameter = cx;
}
// 判断圆是否超出绘图区
if (nOffset < 0)
nOffset = -nOffset;
return (diameter / 2 + nOffset) <= (length / 2);
}
void CMfcCircleCtrl::OnFlashColorChanged()
{
// TODO: Add notification handler code
SetModifiedFlag();
}
void CMfcCircleCtrl::FlashColor(CDC *pdc)
{
CBrush* pOldBrush;
CBrush flashBrush(TranslateColor(m_flashColor));
CPen* pOldPen;
CRect rc;
GetClientRect(rc);
GetDrawRect(&rc);
pOldBrush = pdc->SelectObject(&flashBrush);
pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
pdc->Ellipse(rc);
pdc->SelectObject(pOldPen);
pdc->SelectObject(pOldBrush);
}
void CMfcCircleCtrl::GetDrawRect(CRect *rc)
{
if (m_circleShape)
{
int cx = rc->right - rc->left;
int cy = rc->bottom - rc->top;
if (cx > cy)
{
rc->left += (cx - cy) / 2;
rc->right = rc->left + cy;
// offset circle in bounding rect
rc->left += m_circleOffset;
rc->right += m_circleOffset;
}
else
{
rc->top += (cy - cx) / 2;
rc->bottom = rc->top + cx;
// offset circle in bounding rect
rc->bottom -= m_circleOffset;
rc->top -= m_circleOffset;
}
}
}
BOOL CMfcCircleCtrl::InCircle(CPoint &point)
{
CRect rc;
GetClientRect(rc);
GetDrawRect(&rc);
// Determine radii
double a = (rc.right - rc.left) / 2;
double b = (rc.bottom - rc.top) / 2;
// Determine x, y
double x = point.x - (rc.left + rc.right) / 2;
double y = point.y - (rc.top + rc.bottom) / 2;
// Apply ellipse formula
return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
}
void CMfcCircleCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDC* pdc;
// Flash the color of the control if within the ellipse.
if (InCircle(point))
{
pdc = GetDC();
FlashColor(pdc);
ReleaseDC(pdc);
// 激发ClickIn事件
FireClickIn(point.x, point.y);
}
else
// 激发ClickOut事件
FireClickOut(point.x, point.y);
COleControl::OnLButtonDown(nFlags, point);
}
void CMfcCircleCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDC* pdc;
// Flash the color of the control if within the ellipse.
if (InCircle(point))
{
pdc = GetDC();
FlashColor(pdc);
ReleaseDC(pdc);
// 激发ClickIn事件
FireClickIn(point.x, point.y);
}
else
// 激发ClickOut事件
FireClickOut(point.x, point.y);
COleControl::OnLButtonDblClk(nFlags, point);
}
void CMfcCircleCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
// Redraw the control.
if (InCircle(point))
InvalidateControl();
COleControl::OnLButtonUp(nFlags, point);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -