home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / controls / smiley / smilectl / smilectl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  9.0 KB  |  325 lines

  1. // SmileCtl.cpp : Implementation of the CSmileCtrl OLE control class.
  2.  
  3. #include "stdafx.h"
  4. #include "Smile.h"
  5. #include "SmileCtl.h"
  6. #include "SmilePpg.h"
  7.  
  8.  
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14.  
  15.  
  16. IMPLEMENT_DYNCREATE(CSmileCtrl, COleControl)
  17.  
  18.  
  19. /////////////////////////////////////////////////////////////////////////////
  20. // Message map
  21.  
  22. BEGIN_MESSAGE_MAP(CSmileCtrl, COleControl)
  23.     //{{AFX_MSG_MAP(CSmileCtrl)
  24.     ON_WM_LBUTTONDOWN()
  25.     //}}AFX_MSG_MAP
  26.     ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
  27. END_MESSAGE_MAP()
  28.  
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // Dispatch map
  32.  
  33. BEGIN_DISPATCH_MAP(CSmileCtrl, COleControl)
  34.     //{{AFX_DISPATCH_MAP(CSmileCtrl)
  35.     DISP_PROPERTY_NOTIFY(CSmileCtrl, "Sad", m_bSad, OnSadChanged, VT_BOOL)
  36.     DISP_FUNCTION(CSmileCtrl, "Beep", Beep, VT_EMPTY, VTS_NONE)
  37.     DISP_FUNCTION(CSmileCtrl, "Wink", Wink, VT_EMPTY, VTS_BOOL)
  38.     DISP_STOCKPROP_BACKCOLOR()
  39.     DISP_STOCKPROP_FONT()
  40.     DISP_STOCKPROP_FORECOLOR()
  41.     DISP_STOCKPROP_CAPTION()
  42.     DISP_STOCKPROP_BORDERSTYLE()
  43.     //}}AFX_DISPATCH_MAP
  44. #ifndef _RUNTIME
  45.     DISP_FUNCTION_ID(CSmileCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
  46. #endif
  47. END_DISPATCH_MAP()
  48.  
  49.  
  50. /////////////////////////////////////////////////////////////////////////////
  51. // Event map
  52.  
  53. BEGIN_EVENT_MAP(CSmileCtrl, COleControl)
  54.     //{{AFX_EVENT_MAP(CSmileCtrl)
  55.     EVENT_CUSTOM("Outside", FireOutside, VTS_NONE)
  56.     EVENT_CUSTOM("Inside", FireInside, VTS_XPOS_PIXELS  VTS_YPOS_PIXELS)
  57.     //}}AFX_EVENT_MAP
  58. END_EVENT_MAP()
  59.  
  60.  
  61. /////////////////////////////////////////////////////////////////////////////
  62. // Property pages
  63.  
  64. // TODO: Add more property pages as needed.  Remember to increase the count!
  65. #ifndef _RUNTIME
  66. BEGIN_PROPPAGEIDS(CSmileCtrl, 3)
  67.     PROPPAGEID(CSmilePropPage::guid)
  68. #ifdef _USRDLL
  69.     PROPPAGEID(CSmileColorPropPage::guid)
  70.     PROPPAGEID(CSmileFontPropPage::guid)
  71. #else
  72.     PROPPAGEID(CLSID_CColorPropPage)
  73.     PROPPAGEID(CLSID_CFontPropPage)
  74. #endif
  75. END_PROPPAGEIDS(CSmileCtrl)
  76. #endif
  77.  
  78. /////////////////////////////////////////////////////////////////////////////
  79. // Initialize class factory and guid
  80.  
  81. IMPLEMENT_OLECREATE_EX(CSmileCtrl, "SMILE.SmileCtrl.1",
  82.     0x175cb003, 0xbeed, 0x11ce, 0x96, 0x11, 0, 0xaa, 0, 0x4a, 0x75, 0xcf)
  83.  
  84.  
  85. /////////////////////////////////////////////////////////////////////////////
  86. // Type library ID and version
  87.  
  88. IMPLEMENT_OLETYPELIB(CSmileCtrl, _tlid, _wVerMajor, _wVerMinor)
  89.  
  90.  
  91. /////////////////////////////////////////////////////////////////////////////
  92. // Interface IDs
  93.  
  94. const IID BASED_CODE IID_DSmile =
  95.         { 0x175cb001, 0xbeed, 0x11ce, { 0x96, 0x11, 0, 0xaa, 0, 0x4a, 0x75, 0xcf } };
  96. const IID BASED_CODE IID_DSmileEvents =
  97.         { 0x175cb002, 0xbeed, 0x11ce, { 0x96, 0x11, 0, 0xaa, 0, 0x4a, 0x75, 0xcf } };
  98.  
  99.  
  100. /////////////////////////////////////////////////////////////////////////////
  101. // Control type information
  102.  
  103. static const DWORD BASED_CODE _dwSmileOleMisc =
  104.     OLEMISC_ACTIVATEWHENVISIBLE |
  105.     OLEMISC_SETCLIENTSITEFIRST |
  106.     OLEMISC_INSIDEOUT |
  107.     OLEMISC_CANTLINKINSIDE |
  108.     OLEMISC_RECOMPOSEONRESIZE;
  109.  
  110. IMPLEMENT_OLECTLTYPE(CSmileCtrl, IDS_Smile, _dwSmileOleMisc)
  111.  
  112.  
  113. /////////////////////////////////////////////////////////////////////////////
  114. // CSmileCtrl::CSmileCtrlFactory::UpdateRegistry -
  115. // Adds or removes system registry entries for CSmileCtrl
  116.  
  117. BOOL CSmileCtrl::CSmileCtrlFactory::UpdateRegistry(BOOL bRegister)
  118. {
  119.     if (bRegister)
  120.         return AfxOleRegisterControlClass(
  121.             AfxGetInstanceHandle(),
  122.             m_clsid,
  123.             m_lpszProgID,
  124.             IDS_Smile,
  125.             IDB_Smile,
  126.             FALSE,                      //  Not insertable
  127.             _dwSmileOleMisc,
  128.             _tlid,
  129.             _wVerMajor,
  130.             _wVerMinor);
  131.     else
  132.         return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
  133. }
  134.  
  135.  
  136. /////////////////////////////////////////////////////////////////////////////
  137. // CSmileCtrl::CSmileCtrl - Constructor
  138.  
  139. CSmileCtrl::CSmileCtrl()
  140. {
  141.     InitializeIIDs(&IID_DSmile, &IID_DSmileEvents);
  142.  
  143.     m_bWink = FALSE;
  144. }
  145.  
  146.  
  147. /////////////////////////////////////////////////////////////////////////////
  148. // CSmileCtrl::~CSmileCtrl - Destructor
  149.  
  150. CSmileCtrl::~CSmileCtrl()
  151. {
  152.     // TODO: Cleanup your control's instance data here.
  153. }
  154.  
  155.  
  156. /////////////////////////////////////////////////////////////////////////////
  157. // CSmileCtrl::OnDraw - Drawing function
  158.  
  159. #define X(x) (int)(xLeft + (x)*xScale/100)  // Scaling macros
  160. #define Y(y) (int)(yTop + (y)*yScale/100)   // so scale is 0 - 100
  161. #define CX(x) (int)((x)*xScale/100)
  162. #define CY(y) (int)((y)*yScale/100)
  163.  
  164. void CSmileCtrl::OnDraw(
  165.             CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
  166. {
  167.     long xLeft = rcBounds.left;         // Use with scaling macros
  168.     long yTop = rcBounds.top;
  169.     long xScale = rcBounds.Width();
  170.     long yScale = rcBounds.Height();
  171.  
  172.     int iPenWidth = max(CX(5), CY(5)); // Pen width based on control size
  173.     CBrush brushBack;                  // Background brush
  174.     CBrush brushBlack;
  175.     CBrush brushYellow;
  176.     CPen penBlack(PS_SOLID, iPenWidth, RGB(0x00,0x00,0x00));
  177.     CPen penNull(PS_NULL, 0, (COLORREF)0);  // Null pen for drawing filled ellipses
  178.     COLORREF crBack = TranslateColor(GetBackColor());   //Use BackColor
  179.     brushBack.CreateSolidBrush(crBack);                 //Stock Property
  180.     brushBlack.CreateSolidBrush(RGB(0x00,0x00,0x00));
  181.     brushYellow.CreateSolidBrush(RGB(0xff,0xff,0x00));
  182.  
  183.     pdc->FillRect(rcBounds, &brushBack);                // Clear background
  184.  
  185.     CPen* pPenSave = pdc->SelectObject(&penBlack);
  186.     CBrush* pBrushSave = pdc->SelectObject(&brushYellow);
  187.     pdc->Ellipse(X(10), Y(15), X(90), Y(95));           // Head
  188.  
  189.     if (m_bSad)                                         // Use Sad
  190.     {                                                   // Custom Property
  191.         pdc->Arc(X(25), Y(70), X(75), Y(140),           // Sad Mouth
  192.                X(65), Y(75), X(35), Y(75));
  193.     }
  194.     else
  195.     {
  196.         pdc->Arc(X(25), Y(10), X(75), Y(80),            // Smile mouth
  197.                X(35), Y(70), X(65), Y(70));
  198.     }
  199.  
  200.  
  201.     pdc->SelectObject(&penNull);                        // No draw width
  202.     pdc->SelectObject(&brushBlack);
  203.  
  204.     if (m_bWink)                                        // Left Eye
  205.     {
  206.         iPenWidth = max(CX(1), CY(1));
  207.         CPen penThin(PS_SOLID, iPenWidth, RGB(0x00,0x00,0x00));
  208.         CPen* pThick = pdc->SelectObject(&penThin);
  209.  
  210.         pdc->MoveTo(X(57), Y(35));
  211.         pdc->LineTo(X(65), Y(50));
  212.         pdc->MoveTo(X(57), Y(50));
  213.         pdc->LineTo(X(65), Y(35));
  214.         pdc->SelectObject(pThick);
  215.     }
  216.     else
  217.     {
  218.         pdc->Ellipse(X(57), Y(35), X(65), Y(50));
  219.     }
  220.  
  221.     pdc->Ellipse(X(35), Y(35), X(43), Y(50));           // Right eye
  222.     pdc->Ellipse(X(46), Y(43), X(54), Y(58));           // Nose
  223.  
  224.     pdc->SetBkMode(TRANSPARENT);                        // Use ForeColor
  225.     pdc->SetTextColor(TranslateColor(GetForeColor()));  // Stock Property
  226.  
  227.     SelectStockFont(pdc);                               // Use Font
  228.                                                         // Stock Property
  229.     CRect rect = rcBounds;
  230.     pdc->DrawText(InternalGetText(), -1, rect,          // Use Caption
  231.         DT_SINGLELINE | DT_CENTER | DT_TOP);            // Stock Propery
  232.  
  233.     pdc->SelectObject(pBrushSave);
  234.     pdc->SelectObject(pPenSave);
  235. }
  236.  
  237.  
  238. /////////////////////////////////////////////////////////////////////////////
  239. // CSmileCtrl::DoPropExchange - Persistence support
  240.  
  241. void CSmileCtrl::DoPropExchange(CPropExchange* pPX)
  242. {
  243.     ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
  244.     COleControl::DoPropExchange(pPX);
  245.  
  246.     PX_Bool(pPX, _T("Sad"), m_bSad, FALSE);
  247.  
  248. }
  249.  
  250.  
  251. /////////////////////////////////////////////////////////////////////////////
  252. // CSmileCtrl::OnResetState - Reset control to default state
  253.  
  254. void CSmileCtrl::OnResetState()
  255. {
  256.     COleControl::OnResetState();  // Resets defaults found in DoPropExchange
  257.  
  258.     // TODO: Reset any other control state here.
  259. }
  260.  
  261.  
  262. /////////////////////////////////////////////////////////////////////////////
  263. // CSmileCtrl::AboutBox - Display an "About" box to the user
  264.  
  265. #ifndef _RUNTIME
  266. void CSmileCtrl::AboutBox()
  267. {
  268.     CDialog dlgAbout(IDD_ABOUTBOX_Smile);
  269.     dlgAbout.DoModal();
  270. }
  271. #endif
  272.  
  273. /////////////////////////////////////////////////////////////////////////////
  274. // CSmileCtrl message handlers
  275.  
  276. void CSmileCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  277. {
  278.     CRect rcBounds;
  279.     GetClientRect(&rcBounds);
  280.  
  281.     long xLeft = rcBounds.left; //Required by X() and Y() macros
  282.     long yTop = rcBounds.top;
  283.     long xScale = rcBounds.Width();
  284.     long yScale = rcBounds.Height();
  285.  
  286.     if (InEllipse(point, X(10), Y(15), X(90), Y(95)))
  287.         FireInside((short)point.x, (short)point.y);
  288.     else
  289.         FireOutside();
  290.  
  291.     COleControl::OnLButtonDown(nFlags, point);
  292. }
  293.  
  294. //Simple Ellipse Hit-Testing
  295. BOOL CSmileCtrl::InEllipse(const CPoint& pt,
  296.     int x1, int y1, int x2, int y2)
  297. {
  298.     // Determine radii
  299.     double a = (x2 - x1) / 2;
  300.     double b = (y2 - y1) / 2;
  301.  
  302.     // Determine x, y
  303.     double x = pt.x - (x1 + x2) / 2;
  304.     double y = pt.y - (y1 + y2) / 2;
  305.  
  306.     // Apply ellipse formula
  307.     return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
  308. }
  309.  
  310. void CSmileCtrl::OnSadChanged()
  311. {
  312.     InvalidateControl();
  313. }
  314.  
  315. void CSmileCtrl::Beep()
  316. {
  317.     MessageBeep(0);
  318. }
  319.  
  320. void CSmileCtrl::Wink(BOOL bWink)
  321. {
  322.     m_bWink = bWink;
  323.     InvalidateControl();
  324. }
  325.