home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / CIRC2.PAK / CIRC2CTL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  9.8 KB  |  407 lines

  1. // circ2ctl.cpp : Implementation of the CCirc2Ctrl OLE control class.
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "circ2.h"
  15. #include "circ2ctl.h"
  16. #include "circ2ppg.h"
  17.  
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char BASED_CODE THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24.  
  25. IMPLEMENT_DYNCREATE(CCirc2Ctrl, COleControl)
  26.  
  27.  
  28. /////////////////////////////////////////////////////////////////////////////
  29. // Message map
  30.  
  31. BEGIN_MESSAGE_MAP(CCirc2Ctrl, COleControl)
  32.     //{{AFX_MSG_MAP(CCirc2Ctrl)
  33.     ON_WM_LBUTTONDOWN()
  34.     ON_WM_LBUTTONDBLCLK()
  35.     ON_WM_LBUTTONUP()
  36.     ON_WM_SIZE()
  37.     //}}AFX_MSG_MAP
  38.     ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  39. END_MESSAGE_MAP()
  40.  
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // Dispatch map
  44.  
  45. BEGIN_DISPATCH_MAP(CCirc2Ctrl, COleControl)
  46.     //{{AFX_DISPATCH_MAP(CCirc2Ctrl)
  47.     DISP_PROPERTY(CCirc2Ctrl, "FlashColor", m_flashColor, VT_COLOR)
  48.     DISP_PROPERTY_NOTIFY(CCirc2Ctrl, "CircleShape", m_circleShape, OnCircleShapeChanged, VT_BOOL)
  49.     DISP_PROPERTY_EX(CCirc2Ctrl, "CircleOffset", GetCircleOffset, SetCircleOffset, VT_I2)
  50.     DISP_STOCKPROP_BACKCOLOR()
  51.     //}}AFX_DISPATCH_MAP
  52.     DISP_FUNCTION_ID(CCirc2Ctrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
  53. END_DISPATCH_MAP()
  54.  
  55.  
  56. /////////////////////////////////////////////////////////////////////////////
  57. // Event map
  58.  
  59. BEGIN_EVENT_MAP(CCirc2Ctrl, COleControl)
  60.     //{{AFX_EVENT_MAP(CCirc2Ctrl)
  61.     EVENT_CUSTOM("ClickIn", FireClickIn, VTS_XPOS_PIXELS  VTS_YPOS_PIXELS)
  62.     EVENT_CUSTOM("ClickOut", FireClickOut, VTS_NONE)
  63.     //}}AFX_EVENT_MAP
  64. END_EVENT_MAP()
  65.  
  66.  
  67. /////////////////////////////////////////////////////////////////////////////
  68. // Property pages
  69.  
  70. // TODO: Add more property pages as needed.  Remember to increase the count!
  71. BEGIN_PROPPAGEIDS(CCirc2Ctrl, 1)
  72.     PROPPAGEID(CCirc2PropPage::guid)
  73. END_PROPPAGEIDS(CCirc2Ctrl)
  74.  
  75.  
  76. /////////////////////////////////////////////////////////////////////////////
  77. // Initialize class factory and guid
  78.  
  79. IMPLEMENT_OLECREATE_EX(CCirc2Ctrl, "CIRC2.Circ2Ctrl.1",
  80.     0x9dbafcca, 0x592f, 0x101b, 0x85, 0xce, 0x0, 0x60, 0x8c, 0xec, 0x29, 0x7b)
  81.  
  82.  
  83. /////////////////////////////////////////////////////////////////////////////
  84. // Type library ID and version
  85.  
  86. IMPLEMENT_OLETYPELIB(CCirc2Ctrl, _tlid, _wVerMajor, _wVerMinor)
  87.  
  88.  
  89. /////////////////////////////////////////////////////////////////////////////
  90. // Interface IDs
  91.  
  92. const IID BASED_CODE IID_DCirc2 =
  93.         { 0x9dbafccb, 0x592f, 0x101b, { 0x85, 0xce, 0x0, 0x60, 0x8c, 0xec, 0x29, 0x7b } };
  94. const IID BASED_CODE IID_DCirc2Events =
  95.         { 0x9dbafccc, 0x592f, 0x101b, { 0x85, 0xce, 0x0, 0x60, 0x8c, 0xec, 0x29, 0x7b } };
  96.  
  97.  
  98. /////////////////////////////////////////////////////////////////////////////
  99. // Control type information
  100.  
  101. static const DWORD BASED_CODE _dwCirc2OleMisc =
  102.     OLEMISC_ACTIVATEWHENVISIBLE |
  103.     OLEMISC_SETCLIENTSITEFIRST |
  104.     OLEMISC_INSIDEOUT |
  105.     OLEMISC_CANTLINKINSIDE |
  106.     OLEMISC_RECOMPOSEONRESIZE;
  107.  
  108. IMPLEMENT_OLECTLTYPE(CCirc2Ctrl, IDS_CIRC2, _dwCirc2OleMisc)
  109.  
  110.  
  111. /////////////////////////////////////////////////////////////////////////////
  112. // CCirc2Ctrl::CCirc2CtrlFactory::UpdateRegistry -
  113. // Adds or removes system registry entries for CCirc2Ctrl
  114.  
  115. BOOL CCirc2Ctrl::CCirc2CtrlFactory::UpdateRegistry(BOOL bRegister)
  116. {
  117.     if (bRegister)
  118.         return AfxOleRegisterControlClass(
  119.             AfxGetInstanceHandle(),
  120.             m_clsid,
  121.             m_lpszProgID,
  122.             IDS_CIRC2,
  123.             IDB_CIRC2,
  124.             FALSE,                      //  Not insertable
  125.             _dwCirc2OleMisc,
  126.             _tlid,
  127.             _wVerMajor,
  128.             _wVerMinor);
  129.     else
  130.         return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  131. }
  132.  
  133.  
  134. /////////////////////////////////////////////////////////////////////////////
  135. // CCirc2Ctrl::CCirc2Ctrl - Constructor
  136.  
  137. CCirc2Ctrl::CCirc2Ctrl()
  138. {
  139.     InitializeIIDs(&IID_DCirc2, &IID_DCirc2Events);
  140.  
  141.     // TODO: Initialize your control's instance data here.
  142. }
  143.  
  144.  
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CCirc2Ctrl::~CCirc2Ctrl - Destructor
  147.  
  148. CCirc2Ctrl::~CCirc2Ctrl()
  149. {
  150.     // TODO: Cleanup your control's instance data here.
  151. }
  152.  
  153.  
  154. /////////////////////////////////////////////////////////////////////////////
  155. // CCirc2Ctrl::OnDraw - Drawing function
  156.  
  157. void CCirc2Ctrl::OnDraw(
  158.             CDC* pdc, const CRect& rcBounds, const CRect&)
  159. {
  160.     CBrush* pOldBrush;
  161.     CBrush bkBrush(TranslateColor(GetBackColor()));
  162.     CPen* pOldPen;
  163.     CRect rc = rcBounds;
  164.  
  165.     // Paint the background using the BackColor property
  166.     pdc->FillRect(rcBounds, &bkBrush);
  167.  
  168.     // Draw the ellipse using the BackColor property and a black pen
  169.     GetDrawRect(&rc);
  170.     pOldBrush = pdc->SelectObject(&bkBrush);
  171.     pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
  172.     pdc->Ellipse(rc);
  173.     pdc->SelectObject(pOldPen);
  174.     pdc->SelectObject(pOldBrush);
  175. }
  176.  
  177.  
  178. /////////////////////////////////////////////////////////////////////////////
  179. // CCirc2Ctrl::DoPropExchange - Persistence support
  180.  
  181. void CCirc2Ctrl::DoPropExchange(CPropExchange* pPX)
  182. {
  183.     ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  184.     COleControl::DoPropExchange(pPX);
  185.  
  186.     PX_Bool(pPX, _T("CircleShape"), m_circleShape, TRUE);
  187.     PX_Short(pPX, _T("CircleOffset"), m_circleOffset, 0);
  188.     PX_Long(pPX, _T("FlashColor"), (long &)m_flashColor, RGB(0xFF, 0x00, 0x00));
  189. }
  190.  
  191.  
  192. /////////////////////////////////////////////////////////////////////////////
  193. // CCirc2Ctrl::OnResetState - Reset control to default state
  194.  
  195. void CCirc2Ctrl::OnResetState()
  196. {
  197.     COleControl::OnResetState();  // Resets defaults found in DoPropExchange
  198.  
  199.     // TODO: Reset any other control state here.
  200. }
  201.  
  202.  
  203. /////////////////////////////////////////////////////////////////////////////
  204. // CCirc2Ctrl::AboutBox - Display an "About" box to the user
  205.  
  206. void CCirc2Ctrl::AboutBox()
  207. {
  208.     CDialog dlgAbout(IDD_ABOUTBOX_CIRC2);
  209.     dlgAbout.DoModal();
  210. }
  211.  
  212.  
  213. /////////////////////////////////////////////////////////////////////////////
  214. // CCirc2Ctrl message handlers
  215.  
  216.  
  217. void CCirc2Ctrl::OnCircleShapeChanged()
  218. {
  219.     SetModifiedFlag();
  220.  
  221.     // force the control to redraw itself
  222.     InvalidateControl();
  223.  
  224.     // reset the circle offset, if necessary
  225.     if (m_circleShape)
  226.         SetCircleOffset(0);
  227. }
  228.  
  229.  
  230. void CCirc2Ctrl::GetDrawRect(CRect* rc)
  231. {
  232.     if (m_circleShape)
  233.     {
  234.         int cx = rc->right - rc->left;
  235.         int cy = rc->bottom - rc->top;
  236.  
  237.         if (cx > cy)
  238.         {
  239.             rc->left += (cx - cy) / 2;
  240.             rc->right = rc->left + cy;
  241.  
  242.             // offset circle in bounding rect
  243.             rc->left += m_circleOffset;
  244.             rc->right += m_circleOffset;
  245.         }
  246.         else
  247.         {
  248.             rc->top += (cy - cx) / 2;
  249.             rc->bottom = rc->top + cx;
  250.  
  251.             // offset circle in bounding rect
  252.             rc->bottom -= m_circleOffset;
  253.             rc->top -= m_circleOffset;
  254.         }
  255.     }
  256. }
  257.  
  258.  
  259. short CCirc2Ctrl::GetCircleOffset()
  260. {
  261.     return m_circleOffset;
  262. }
  263.  
  264.  
  265. void CCirc2Ctrl::SetCircleOffset(short nNewValue)
  266. {
  267.     // Validate the specified offset value
  268.     if ((m_circleOffset != nNewValue) && m_circleShape && InBounds(nNewValue))
  269.     {
  270.         m_circleOffset = nNewValue;
  271.         SetModifiedFlag();
  272.         InvalidateControl();
  273.     }
  274. }
  275.  
  276.  
  277. BOOL CCirc2Ctrl::InBounds(short nOffset)
  278. {
  279.     int diameter;
  280.     int length;
  281.     int cx;
  282.     int cy;
  283.  
  284.     GetControlSize(&cx, &cy);
  285.  
  286.     if (cx > cy)
  287.     {
  288.         length = cx;
  289.         diameter = cy;
  290.     }
  291.     else
  292.     {
  293.         length = cy;
  294.         diameter = cx;
  295.     }
  296.     if (nOffset < 0)
  297.         nOffset = (short) -nOffset;
  298.     return (diameter / 2 + nOffset) <= (length / 2);
  299. }
  300.  
  301.  
  302. void CCirc2Ctrl::OnLButtonDown(UINT nFlags, CPoint point)
  303. {
  304.     CDC* pdc;
  305.  
  306.     // Flash the color of the control if within the ellipse.
  307.     if (InCircle(point))
  308.     {
  309.         pdc = GetDC();
  310.         FlashColor(pdc);
  311.         ReleaseDC(pdc);
  312.  
  313.         // Fire the ClickIn event
  314.         FireClickIn(point.x, point.y);
  315.     }
  316.     else
  317.         // Fire the ClickOut event
  318.         FireClickOut();
  319.  
  320.     COleControl::OnLButtonDown(nFlags, point);
  321. }
  322.  
  323.  
  324. void CCirc2Ctrl::OnLButtonDblClk(UINT nFlags, CPoint point)
  325. {
  326.     CDC* pdc;
  327.  
  328.     // Flash the color of the control if within the ellipse.
  329.     if (InCircle(point))
  330.     {
  331.         pdc = GetDC();
  332.         FlashColor(pdc);
  333.         ReleaseDC(pdc);
  334.     }
  335.  
  336.     COleControl::OnLButtonDblClk(nFlags, point);
  337. }
  338.  
  339.  
  340. void CCirc2Ctrl::OnLButtonUp(UINT nFlags, CPoint point)
  341. {
  342.     // Redraw the control.
  343.     if (InCircle(point))
  344.         InvalidateControl();
  345.  
  346.     COleControl::OnLButtonUp(nFlags, point);
  347. }
  348.  
  349.  
  350. BOOL CCirc2Ctrl::InCircle(CPoint& point)
  351. {
  352.     CRect rc;
  353.     GetClientRect(rc);
  354.     GetDrawRect(&rc);
  355.  
  356.     // Determine radii
  357.     double a = (rc.right - rc.left) / 2;
  358.     double b = (rc.bottom - rc.top) / 2;
  359.  
  360.     // Determine x, y
  361.     double x = point.x - (rc.left + rc.right) / 2;
  362.     double y = point.y - (rc.top + rc.bottom) / 2;
  363.  
  364.     // Apply ellipse formula
  365.     return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
  366. }
  367.  
  368.  
  369. void CCirc2Ctrl::FlashColor(CDC* pdc)
  370. {
  371.     CBrush* pOldBrush;
  372.     CBrush flashBrush(TranslateColor(m_flashColor));
  373.     CPen* pOldPen;
  374.     CRect rc;
  375.  
  376.     GetClientRect(rc);
  377.     GetDrawRect(&rc);
  378.     pOldBrush = pdc->SelectObject(&flashBrush);
  379.     pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
  380.     pdc->Ellipse(rc);
  381.     pdc->SelectObject(pOldPen);
  382.     pdc->SelectObject(pOldBrush);
  383. }
  384.  
  385.  
  386. BOOL CCirc2Ctrl::OnMapPropertyToPage(DISPID dispid, LPCLSID lpclsid,
  387.     BOOL* pbPageOptional)
  388. {
  389.     switch(dispid)
  390.     {
  391.         case dispidFlashColor:
  392.             *lpclsid = CLSID_CColorPropPage;
  393.             *pbPageOptional = TRUE;
  394.             return TRUE;
  395.     }
  396.     return COleControl::OnMapPropertyToPage(dispid, lpclsid, pbPageOptional);
  397. }
  398.  
  399. void CCirc2Ctrl::OnSize(UINT nType, int cx, int cy) 
  400. {
  401.     COleControl::OnSize(nType, cx, cy);
  402.     
  403.     // If circle shape is true & cicrle does not fit in new size, reset the offset
  404.     if (m_circleShape && !InBounds(GetCircleOffset()))
  405.         SetCircleOffset(0);
  406. }
  407.