home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / card / cardctl.cpp < prev    next >
C/C++ Source or Header  |  1997-10-05  |  21KB  |  840 lines

  1. //=--------------------------------------------------------------------------=
  2. // CardCtl.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 - 1997 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. //
  13. //
  14. #include "IPServer.H"
  15.  
  16. #include "Guids.H"
  17. #include "LocalObj.H"
  18. #include "Util.H"
  19. #include "Globals.H"
  20. #include "Resource.H"
  21. #include "cardctl.H"
  22.  
  23. #include "carddraw.h"
  24.  
  25. extern HBITMAP cardcacheMem[];
  26. extern CRITICAL_SECTION drawCritSec;
  27.  
  28. // for ASSERT and FAIL
  29. //
  30. SZTHISFILE
  31.  
  32. WCHAR wszImage [] = L"Card";
  33.  
  34. //=--------------------------------------------------------------------------=
  35. // all the events in this control
  36. //
  37. // TODO: add events here ...
  38. //
  39.  
  40. static VARTYPE rgMouse[] = { VT_I2, VT_I2, VT_I4, VT_I4 };
  41. enum { MouseMove=0, MouseDown, MouseUp, Click, DblClick };
  42.  
  43. static EVENTINFO rgEvents [] = {
  44.     { DISPID_MOUSEMOVE, 4, rgMouse },
  45.     { DISPID_MOUSEDOWN, 4, rgMouse },
  46.     { DISPID_MOUSEUP, 4, rgMouse },
  47.     { DISPID_CLICK, 0, NULL },
  48.     { DISPID_DBLCLICK, 0, NULL },
  49. };
  50.  
  51. //=--------------------------------------------------------------------------=
  52. // array describing all of our property pages.  these clsids are typically
  53. // in guids.h
  54. //
  55. // TODO: add any additional property page guids here ...
  56. //
  57. const GUID *rgCardPropPages [] = {
  58.     &CLSID_CardGeneralPage
  59. };
  60.  
  61. //=--------------------------------------------------------------------------=
  62. // Custum Verb information
  63. //
  64. // TODO: add any custom verbs here in an array, using the VERBINFO structure.
  65. //       then mark the controld def'n in CardCtl.H with
  66. //       this verb array
  67. //
  68.  
  69.  
  70. //=--------------------------------------------------------------------------=
  71. // CCardControl::CCardControl
  72. //=--------------------------------------------------------------------------=
  73. // "Being born is like being kidnapped.  And then sold into slavery."
  74. //    - andy warhol (1928 - 87)
  75. //
  76. // Parameters:
  77. //    IUnknown *        - [in]
  78. //
  79. // Notes:
  80. //
  81. #pragma warning(disable:4355)  // using 'this' in constructor
  82. CCardControl::CCardControl
  83. (
  84.     IUnknown *pUnkOuter
  85. )
  86. : COleControl(pUnkOuter, OBJECT_TYPE_CTLCARD, (IDispatch *)this)
  87. {
  88.     static SIZEL size = { CCardDraw::CardSizeX, CCardDraw::CardSizeY };
  89.  
  90.     m_number = DefaultNumber;
  91.     m_suite = DefaultSuite;
  92.     m_invert = DefaultInvert;
  93.     m_cardalignment = DefaultCardAlignment;
  94.     BackBrush = NULL;
  95.  
  96.     SetControlSize( &size );
  97.  
  98. #if 0
  99. // for better performance when the cards are first displayed (such as
  100. // when a full deck is displayed to the user), un-ifdef this code.  
  101. // for better initial control creation time, keep this code ifdef'd.  
  102.  
  103.     // initialize the standard 52 cards (no jokers, no backs)
  104.     if( !cardcacheMem[0] )
  105.     {
  106.             EnterCriticalSection( &drawCritSec );
  107.         if( !cardcacheMem[0] )
  108.         {
  109.             CCardDraw cd( CCardDraw::DrawAll );
  110.             HDC drawDc;
  111.             HBITMAP drawDcMem;
  112.             int t;
  113.  
  114.             drawDc = CreateCompatibleDC( NULL );
  115.  
  116.             for( t = 0; t < 52; t++ )
  117.             {
  118.                 cardcacheMem[t] = cd.CreateDIBCard( drawDc );
  119.                 drawDcMem = SelectObject( drawDc, cardcacheMem[t] );    
  120.                 cd.DrawCard( drawDc, (t/14) + 1, (t%14) + 1 );
  121.                 SelectObject( drawDc, drawDcMem );
  122.             }
  123.             DeleteDC( drawDc );
  124.         }
  125.         LeaveCriticalSection( &drawCritSec );
  126.     }
  127. #endif
  128. }
  129. #pragma warning(default:4355)  // using 'this' in constructor
  130.  
  131. //=--------------------------------------------------------------------------=
  132. // CCardControl::~CCardControl
  133. //=--------------------------------------------------------------------------=
  134. // "We all labour against our own cure, for death is the cure of all diseases"
  135. //    - Sir Thomas Browne (1605 - 82)
  136. //
  137. // Notes:
  138. //
  139. CCardControl::~CCardControl ()
  140. {
  141.     if( BackBrush )
  142.         DeleteObject( BackBrush );
  143. }
  144.  
  145. //=--------------------------------------------------------------------------=
  146. // CCardControl:RegisterClassData
  147. //=--------------------------------------------------------------------------=
  148. // register the window class information for your control here.
  149. // this information will automatically get cleaned up for you on DLL shutdown.
  150. //
  151. // Output:
  152. //    BOOL            - FALSE means fatal error.
  153. //
  154. // Notes:
  155. //
  156. BOOL CCardControl::RegisterClassData()
  157. {
  158.     WNDCLASS wndclass;
  159.  
  160.     // TODO: register any additional information you find interesting here.
  161.     //       this method is only called once for each type of control
  162.     //
  163.     memset(&wndclass, 0, sizeof(WNDCLASS));
  164.     wndclass.style          = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
  165.     wndclass.lpfnWndProc    = COleControl::ControlWindowProc;
  166.     wndclass.hInstance      = g_hInstance;
  167.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  168.     wndclass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
  169.     wndclass.lpszClassName  = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLCARD);
  170.  
  171.     return RegisterClass(&wndclass);
  172. }
  173.  
  174. //=--------------------------------------------------------------------------=
  175. // CCardControl::InternalQueryInterface
  176. //=--------------------------------------------------------------------------=
  177. // qi for things only we support.
  178. //
  179. // Parameters:
  180. // Parameters:
  181. //    REFIID        - [in]  interface they want
  182. //    void **       - [out] where they want to put the resulting object ptr.
  183. //
  184. // Output:
  185. //    HRESULT       - S_OK, E_NOINTERFACE
  186. //
  187. // Notes:
  188. //
  189. HRESULT CCardControl::InternalQueryInterface
  190. (
  191.     REFIID  riid,
  192.     void  **ppvObjOut
  193. )
  194. {
  195.     IUnknown *pUnk;
  196.  
  197.     *ppvObjOut = NULL;
  198.  
  199.     // TODO: if you want to support any additional interrfaces, then you should
  200.     // indicate that here.  never forget to call COleControl's version in the
  201.     // case where you don't support the given interface.
  202.     //
  203.     if (DO_GUIDS_MATCH(riid, IID_ICard)) {
  204.         pUnk = (IUnknown *)(ICard *)this;
  205.     } else{
  206.         return COleControl::InternalQueryInterface(riid, ppvObjOut);
  207.     }
  208.  
  209.     pUnk->AddRef();
  210.     *ppvObjOut = (void *)pUnk;
  211.     return S_OK;
  212. }
  213.  
  214. //=--------------------------------------------------------------------------=
  215. // CCardControl::LoadTextState
  216. //=--------------------------------------------------------------------------=
  217. // load in our text state for this control.
  218. //
  219. // Parameters:
  220. //    IPropertyBag *        - [in] property bag to read from
  221. //    IErrorLog *           - [in] errorlog object to use with proeprty bag
  222. //
  223. // Output:
  224. //    HRESULT
  225. //
  226. // Notes:
  227. //    - NOTE: if you have a binary object, then you should pass an unknown
  228. //      pointer to the property bag, and it will QI it for IPersistStream, and
  229. //      get said object to do a Load()
  230. //
  231. STDMETHODIMP CCardControl::LoadTextState
  232. (
  233.     IPropertyBag *pPropertyBag,
  234.     IErrorLog    *pErrorLog
  235. )
  236. {
  237.     VARIANT v;
  238.     HRESULT hr;
  239.  
  240.     VariantInit(&v);    
  241.  
  242.     v.vt = VT_I2;
  243.     hr = pPropertyBag->Read(L"Number",&v,pErrorLog);
  244.     if (SUCCEEDED(hr))
  245.         m_number = (enumCardNumber) v.iVal;
  246.     ValidateNumber();
  247.     VariantClear(&v);
  248.  
  249.     v.vt = VT_I2;
  250.     hr = pPropertyBag->Read(L"Suite",&v,pErrorLog);
  251.     if (SUCCEEDED(hr))
  252.         m_suite = (enumCardSuite) v.iVal;
  253.     ValidateSuite();
  254.     VariantClear(&v);
  255.  
  256.     v.vt = VT_BOOL;
  257.     hr = pPropertyBag->Read(L"Invert",&v,pErrorLog);
  258.     if (SUCCEEDED(hr))
  259.         m_invert = v.boolVal;
  260.     VariantClear(&v);
  261.  
  262.     v.vt = VT_I2;
  263.     hr = pPropertyBag->Read(L"CardAlignment",&v,pErrorLog);
  264.     if (SUCCEEDED(hr))
  265.         m_cardalignment = (enumCardAlignment) v.iVal;
  266.     ValidateCardAlignment();
  267.     VariantClear(&v);
  268.  
  269.     return S_OK;
  270. }
  271.  
  272. #define        STREAMHDR_MAGIC        1296924267
  273.  
  274. //=--------------------------------------------------------------------------=
  275. // CCardControl::LoadBinaryState
  276. //=--------------------------------------------------------------------------=
  277. // loads in our binary state using streams.
  278. //
  279. // Parameters:
  280. //    IStream *            - [in] stream to write to.
  281. //
  282. // Output:
  283. //    HRESULT
  284. //
  285. // Notes:
  286. //
  287. STDMETHODIMP CCardControl::LoadBinaryState
  288. (
  289.     IStream *pStream
  290. )
  291. {
  292.     HRESULT hr;
  293.     DWORD sh;
  294.  
  295.     hr = pStream->Read(&sh, sizeof(sh), NULL);
  296.     RETURN_ON_FAILURE(hr);
  297.  
  298.     if (sh != STREAMHDR_MAGIC )
  299.         return E_UNEXPECTED;
  300.  
  301.     hr = pStream->Read(&(m_number),sizeof(m_number),NULL);
  302.     RETURN_ON_FAILURE(hr);
  303.     ValidateNumber();
  304.  
  305.     hr = pStream->Read(&(m_suite),sizeof(m_suite),NULL);
  306.     RETURN_ON_FAILURE(hr);
  307.     ValidateSuite();
  308.  
  309.     hr = pStream->Read(&(m_invert),sizeof(m_invert),NULL);
  310.     RETURN_ON_FAILURE(hr);
  311.  
  312.     hr = pStream->Read(&(m_cardalignment),sizeof(m_cardalignment),NULL);
  313.     RETURN_ON_FAILURE(hr);
  314.     ValidateCardAlignment();
  315.  
  316.     return S_OK;
  317. }
  318.  
  319. //=--------------------------------------------------------------------------=
  320. // CCardControl::SaveTextState
  321. //=--------------------------------------------------------------------------=
  322. // saves out the text state for this control using a property bag.
  323. //
  324. // Parameters:
  325. //    IPropertyBag *        - [in] the property bag with which to work.
  326. //    BOOL                  - [in] if TRUE, then write out ALL properties, even
  327. //                            if they're their the default value ...
  328. //
  329. // Output:
  330. //    HRESULT
  331. //
  332. // Notes:
  333. //
  334. STDMETHODIMP CCardControl::SaveTextState
  335. (
  336.     IPropertyBag *pPropertyBag,
  337.     BOOL          fWriteDefaults
  338. )
  339. {
  340.     VARIANT v;
  341.     HRESULT hr;
  342.  
  343.     if( m_number != DefaultNumber )
  344.     {
  345.         VariantInit(&v);
  346.         v.vt = VT_I2;
  347.         v.iVal = m_number;
  348.         hr = pPropertyBag->Write( L"Number", &v);
  349.     }
  350.  
  351.     if( m_suite != DefaultSuite )
  352.     {
  353.         VariantInit(&v);
  354.         v.vt = VT_I2;
  355.         v.iVal = m_suite;
  356.         hr = pPropertyBag->Write( L"Suite", &v);
  357.     }
  358.  
  359.     if( m_invert != DefaultInvert )
  360.     {
  361.         VariantInit(&v);
  362.         v.vt = VT_BOOL;
  363.         v.boolVal = m_invert;
  364.         hr = pPropertyBag->Write( L"Invert", &v);
  365.     }
  366.  
  367.     if( m_cardalignment != DefaultCardAlignment )
  368.     {
  369.         VariantInit(&v);
  370.         v.vt = VT_I2;
  371.         v.iVal = m_cardalignment;
  372.         hr = pPropertyBag->Write( L"CardAlignment", &v);
  373.     }
  374.  
  375.     return S_OK;
  376. }
  377.  
  378. //=--------------------------------------------------------------------------=
  379. // CCardControl::SaveBinaryState
  380. //=--------------------------------------------------------------------------=
  381. // save out the binary state for this control, using the given IStream object.
  382. //
  383. // Parameters:
  384. //    IStream  *             - [in] save to which you should save.
  385. //
  386. // Output:
  387. //    HRESULT
  388. //
  389. // Notes:
  390. //    - it is important that you seek to the end of where you saved your
  391. //      properties when you're done with the IStream.
  392. //
  393. STDMETHODIMP CCardControl::SaveBinaryState
  394. (
  395.     IStream *pStream
  396. )
  397. {
  398.     HRESULT hr;
  399.     DWORD sh = STREAMHDR_MAGIC;    
  400.  
  401.     // write out the stream hdr.
  402.     //
  403.     hr = pStream->Write(&sh, sizeof(sh), NULL);
  404.     RETURN_ON_FAILURE(hr);
  405.  
  406.     hr = pStream->Write(&(m_number),sizeof(m_number),NULL);
  407.     RETURN_ON_FAILURE(hr);
  408.  
  409.     hr = pStream->Write(&(m_suite),sizeof(m_suite),NULL);
  410.     RETURN_ON_FAILURE(hr);
  411.  
  412.     hr = pStream->Write(&(m_invert),sizeof(m_invert),NULL);
  413.     RETURN_ON_FAILURE(hr);
  414.  
  415.     hr = pStream->Write(&(m_cardalignment),sizeof(m_cardalignment),NULL);
  416.     RETURN_ON_FAILURE(hr);
  417.  
  418.     return S_OK;
  419. }
  420.  
  421.  
  422. //=--------------------------------------------------------------------------=
  423. // CCardControl::OnDraw
  424. //=--------------------------------------------------------------------------=
  425. // "I don't very much enjoy looking at paintings in general.  i know too
  426. //  much about them.  i take them apart."
  427. //    - georgia o'keeffe (1887-1986)
  428. //
  429. // Parameters:
  430. //    HDC                - [in]  HDC to draw to
  431. //    LPCRECTL           - [in]  rect we're drawing to
  432. //    LPCRECTL           - [in]  window extent and origin for meta-files
  433. //    HDC                - [in]  HIC for target device
  434. //
  435. // Output:
  436. //    HRESULT
  437. //
  438. // Notes:
  439. //
  440. HRESULT CCardControl::OnDraw
  441. (
  442.     DWORD    dvaspect,        
  443.     HDC      hdcDraw,
  444.     LPCRECTL prcBounds,
  445.     LPCRECTL prcWBounds,
  446.     HDC      hicTargetDevice,
  447.     BOOL     fOptimize
  448. )
  449. {
  450.     int OffsetX, OffsetY;
  451.     RECTL rcBoundsDP;
  452.     int width, height;
  453.     int savedDC;
  454.     HDC drawDc;
  455.     HBITMAP drawDcMem;
  456.     int c;
  457.  
  458.     if( !Windowless() && !BackBrush )
  459.     {
  460.         OLE_COLOR BackColor;
  461.         COLORREF BackColorCR;
  462.         if( !GetAmbientProperty( DISPID_AMBIENT_BACKCOLOR, VT_I4, &BackColor ) )
  463.             BackColor = 0;
  464.         OleTranslateColor( BackColor, NULL, &BackColorCR );
  465.         BackBrush = CreateSolidBrush( BackColorCR );
  466.     }
  467.         
  468.     rcBoundsDP = *prcBounds;
  469.     LPtoDP( hdcDraw, (POINT *) &rcBoundsDP, 2 );
  470.  
  471.     width = rcBoundsDP.right - rcBoundsDP.left;
  472.     height = rcBoundsDP.bottom - rcBoundsDP.top;
  473.  
  474.     switch( m_cardalignment )
  475.     {
  476.         case CardTopCenter: 
  477.         case CardCenter:
  478.         case CardBottomCenter:
  479.             OffsetX = (width - CCardDraw::CardSizeX) / 2;
  480.             break;
  481.         case CardTopRight: 
  482.         case CardCenterRight:
  483.         case CardBottomRight:
  484.             OffsetX = (width - CCardDraw::CardSizeX);
  485.             break;
  486.         default:
  487.             OffsetX = 0;
  488.             break;
  489.     }
  490.     switch( m_cardalignment )
  491.     {
  492.         case CardCenterRight:
  493.         case CardCenter:
  494.         case CardCenterLeft:
  495.             OffsetY = (height - CCardDraw::CardSizeY) / 2;
  496.             break;
  497.         case CardBottomRight: 
  498.         case CardBottomCenter: 
  499.         case CardBottomLeft:
  500.             OffsetY = (height - CCardDraw::CardSizeY);
  501.             break;
  502.         default:
  503.             OffsetY = 0;
  504.             break;
  505.     }
  506.  
  507.     if( BackBrush )
  508.         FillRect( hdcDraw, (RECT *) prcBounds, BackBrush );
  509.  
  510.     if( m_suite == CardBlank )
  511.         return S_OK;
  512.  
  513.     savedDC = SaveDC( hdcDraw );
  514.  
  515.     SetMapMode( hdcDraw, MM_TEXT );
  516.     SetWindowOrgEx( hdcDraw, -(OffsetX + rcBoundsDP.left), 
  517.                  -(OffsetY + rcBoundsDP.top), NULL );
  518.     SetViewportOrgEx( hdcDraw, 0, 0, NULL );
  519.  
  520.     if( width < CCardDraw::CardSizeX || height < CCardDraw::CardSizeY )
  521.     {
  522.         HRGN clipRgn;
  523.         clipRgn = CreateRectRgn( rcBoundsDP.left, 
  524.                      rcBoundsDP.top, 
  525.                      rcBoundsDP.left + width, 
  526.                      rcBoundsDP.top + height );
  527.         SelectClipRgn( hdcDraw, clipRgn );
  528.         DeleteObject( clipRgn );
  529.     }        
  530.  
  531.     SelectObject( hdcDraw, GetStockObject( m_invert ? WHITE_PEN : BLACK_PEN ) );
  532.  
  533.     drawDc = CreateCompatibleDC( NULL );
  534.  
  535.     if( m_suite > 0 )
  536.         c = (m_suite-1)*14 + (m_number-1);
  537.     else
  538.         c = (m_suite < -12) ? 56 : -m_suite + 56;
  539.  
  540.     if( !cardcacheMem[c] )
  541.     {
  542.         CCardDraw cd( (c > 55 ? CCardDraw::DrawBack : (int) m_number) );
  543.  
  544.             EnterCriticalSection( &drawCritSec );
  545.         if( !cardcacheMem[c] )
  546.         {
  547.             cardcacheMem[c] = cd.CreateDIBCard( hdcDraw );
  548.             drawDcMem = (HBITMAP) SelectObject( drawDc, cardcacheMem[c] );    
  549.             cd.DrawCard( drawDc, m_suite, m_number );
  550.         }
  551.         else
  552.             drawDcMem = (HBITMAP) SelectObject( drawDc, cardcacheMem[c] );    
  553.         LeaveCriticalSection( &drawCritSec );
  554.     }
  555.     else
  556.         drawDcMem = (HBITMAP) SelectObject( drawDc, cardcacheMem[c] );    
  557.  
  558.     if( m_cardalignment != CardStretch )
  559.     {
  560.           BitBlt( hdcDraw, 1, 1, CCardDraw::CardSizeX-2, CCardDraw::CardSizeY-2,
  561.                 drawDc, 1, 1, m_invert ? NOTSRCCOPY : SRCCOPY );
  562.         Polyline( hdcDraw, CCardDraw::CardBorder, 
  563.                 sizeof(CCardDraw::CardBorder)/sizeof(POINT) );
  564.     }
  565.     else
  566.     {
  567.         POINT border[9];
  568.         memcpy( border, CCardDraw::CardBorder, sizeof(border) );
  569.         border[2].x = border[5].x = width-3;
  570.         border[3].x = border[4].x = width-1;
  571.         border[4].y = border[7].y = height-3;
  572.         border[5].y = border[6].y = height-1;
  573.         StretchBlt( hdcDraw, 1, 1, width-2, height-2,
  574.                 drawDc, 1, 1, 
  575.                 CCardDraw::CardSizeX-2,
  576.                 CCardDraw::CardSizeY-2,
  577.                 m_invert ? NOTSRCCOPY : SRCCOPY );
  578.         Polyline( hdcDraw, border, sizeof(border)/sizeof(POINT) );
  579.     }
  580.  
  581.     RestoreDC( hdcDraw, savedDC );
  582.  
  583.     SelectObject( drawDc, drawDcMem );
  584.     DeleteDC( drawDc );
  585.     
  586.     return S_OK;
  587. }
  588.  
  589. //=--------------------------------------------------------------------------=
  590. // CCardControl::WindowProc
  591. //=--------------------------------------------------------------------------=
  592. // window procedure for this control.  nothing terribly exciting.
  593. //
  594. // Parameters:
  595. //     see win32sdk on window procs.
  596. //
  597. // Notes:
  598. //
  599. LRESULT CCardControl::WindowProc
  600. (
  601.     UINT   msg,
  602.     WPARAM wParam,
  603.     LPARAM lParam
  604. )
  605. {
  606.     POINTS pt;
  607.     RECT rect;
  608.     int b, s;
  609.     int ev = -1;
  610.  
  611.     switch( msg )
  612.     {
  613.     case WM_MOUSEMOVE:
  614.         ev = MouseMove;
  615.         // FALL THROUGH!
  616.     case WM_LBUTTONDOWN:
  617.     case WM_MBUTTONDOWN:
  618.     case WM_RBUTTONDOWN:
  619.         if( ev == -1 )    ev = MouseDown;
  620.         // FALL THROUGH!
  621.     case WM_LBUTTONUP:
  622.     case WM_MBUTTONUP:
  623.     case WM_RBUTTONUP:
  624.         if( ev == -1 )  ev = MouseUp;
  625.         pt = MAKEPOINTS( lParam );
  626.         OcxGetWindowRect( &rect );
  627.         b = (wParam & 3) == 3 ? 4 : wParam & 3;
  628.         s = (wParam >> 2) & 7;
  629.         FireEvent( &rgEvents[ev], b, s, pt.x-rect.left, pt.y-rect.top );
  630.         if( msg == WM_LBUTTONUP )
  631.             FireEvent( &rgEvents[Click] );
  632.         break;
  633.     case WM_LBUTTONDBLCLK:
  634.         FireEvent( &rgEvents[DblClick] );
  635.         break;
  636.     }
  637.  
  638.     return OcxDefWindowProc(msg, wParam, lParam);
  639. }
  640.  
  641. //=--------------------------------------------------------------------------=
  642. // CCardControl::AboutBox
  643. //=--------------------------------------------------------------------------=
  644. // prints up an about box.  fweeeee.
  645. //
  646. // Notes:
  647. //
  648. void CCardControl::AboutBox
  649. (
  650.     void
  651. )
  652. {
  653.     // TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
  654.     // they wanted a slightly more interesting About Box ...  you should
  655.     // still call ModalDialog first, however.
  656.     //
  657.     ModalDialog(TRUE);
  658.     MessageBox(NULL, "Microsoft ActiveX Card Control\n\n"
  659.              "Copyright ⌐ 1996 Microsoft Corp.",
  660.              "About Card", 
  661.              MB_OK | MB_TASKMODAL);
  662.     ModalDialog(FALSE);
  663. }
  664.  
  665. STDMETHODIMP  CCardControl::get_Number(enumCardNumber * number)
  666. {
  667.     CHECK_POINTER(number);
  668.  
  669.     *number = m_number;
  670.  
  671.     return( S_OK );
  672. }
  673.  
  674. STDMETHODIMP  CCardControl::put_Number(enumCardNumber number)
  675. {
  676.     if( m_number == number ) 
  677.         return S_OK;
  678.  
  679.     m_number = number;
  680.     ValidateNumber();
  681.     if( m_suite >= 1 )
  682.     {
  683.         if( Windowless() )
  684.         {
  685.             RECT rect;
  686.             OcxGetWindowRect( &rect );
  687.             OcxInvalidateRect( &rect, TRUE );
  688.         }
  689.         else
  690.             InvalidateControl( NULL );
  691.     }
  692.  
  693.     // update anybody who cares about property changes and mark ourselves
  694.     // as dirty
  695.     //
  696.     PropertyChanged(DISPID_NUMBER);
  697.     m_fDirty = TRUE;
  698.  
  699.     return S_OK;
  700. }
  701.  
  702. STDMETHODIMP  CCardControl::get_Invert( VARIANT_BOOL *invert )
  703. {
  704.     CHECK_POINTER(invert);
  705.  
  706.     *invert = m_invert;
  707.  
  708.     return( S_OK );
  709. }
  710.  
  711. STDMETHODIMP  CCardControl::put_Invert( VARIANT_BOOL invert )
  712. {
  713.     if( m_invert == invert )
  714.         return S_OK;
  715.  
  716.     m_invert = invert;
  717.  
  718.     {
  719.         if( Windowless() )
  720.         {
  721.             RECT rect;
  722.             OcxGetWindowRect( &rect );
  723.             OcxInvalidateRect( &rect, TRUE );
  724.         }
  725.         else
  726.             InvalidateControl( NULL );
  727.     }
  728.  
  729.     // update anybody who cares about property changes and mark ourselves
  730.     // as dirty
  731.     //
  732.     PropertyChanged(DISPID_INVERT);
  733.     m_fDirty = TRUE;
  734.  
  735.     return S_OK;
  736. }
  737.  
  738. STDMETHODIMP  CCardControl::get_CardAlignment( enumCardAlignment *cardalignment )
  739. {
  740.     CHECK_POINTER(cardalignment);
  741.  
  742.     *cardalignment = m_cardalignment;
  743.  
  744.     return( S_OK );
  745. }
  746.  
  747. STDMETHODIMP  CCardControl::put_CardAlignment( enumCardAlignment cardalignment )
  748. {
  749.     if( m_cardalignment == cardalignment )
  750.         return S_OK;
  751.  
  752.     m_cardalignment = cardalignment;    
  753.     ValidateCardAlignment();
  754.  
  755.     {
  756.         if( Windowless() )
  757.         {
  758.             RECT rect;
  759.             OcxGetWindowRect( &rect );
  760.             OcxInvalidateRect( &rect, TRUE );
  761.         }
  762.         else
  763.             InvalidateControl( NULL );
  764.     }
  765.  
  766.     // update anybody who cares about property changes and mark ourselves
  767.     // as dirty
  768.     //
  769.     PropertyChanged(DISPID_CARDALIGNMENT);
  770.     m_fDirty = TRUE;
  771.  
  772.     return S_OK;
  773. }
  774.  
  775. STDMETHODIMP  CCardControl::get_Suite(enumCardSuite * suite)
  776. {
  777.     CHECK_POINTER(suite);
  778.  
  779.     *suite = m_suite;
  780.  
  781.     return( S_OK );
  782. }
  783.  
  784. STDMETHODIMP  CCardControl::put_Suite(enumCardSuite suite)
  785. {
  786.     if( m_suite == suite ) 
  787.         return S_OK;
  788.  
  789.     m_suite = suite;
  790.     ValidateSuite();
  791.  
  792.     {
  793.         if( Windowless() )
  794.         {
  795.             RECT rect;
  796.             OcxGetWindowRect( &rect );
  797.             OcxInvalidateRect( &rect, TRUE );
  798.         }
  799.         else
  800.             InvalidateControl( NULL );
  801.     }
  802.  
  803.     // update anybody who cares about property changes and mark ourselves
  804.     // as dirty
  805.     //
  806.     PropertyChanged(DISPID_SUITE);
  807.     m_fDirty = TRUE;
  808.  
  809.     return S_OK;
  810. }
  811.  
  812. //=--------------------------------------------------------------------------=
  813. // CCardControl::Create
  814. //=--------------------------------------------------------------------------=
  815. // global static function that creates an instance of the control an returns
  816. // an IUnknown pointer for it.
  817. //
  818. // Parameters:
  819. //    IUnknown *        - [in] controlling unknown for aggregation
  820. //
  821. // Output:
  822. //    IUnknown *        - new object.
  823. //
  824. // Notes:
  825. //
  826. IUnknown *CCardControl::Create
  827. (
  828.     IUnknown *pUnkOuter
  829. )
  830. {
  831.     // make sure we return the private unknown so that we support aggegation
  832.     // correctly!
  833.     //
  834.     CCardControl *pNew = new CCardControl(pUnkOuter);
  835.     return pNew->PrivateUnknown();
  836. }
  837.  
  838.                                     
  839.                                     
  840.