home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / atl / atltangram / mfctangram / mainfrm.cpp next >
C/C++ Source or Header  |  1998-03-26  |  14KB  |  577 lines

  1. // MainFrm.cpp : implementation of the CMFCMainFrame class
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12.  
  13. #include "stdafx.h"
  14. #include "MFCTangram.h"
  15. #include "MainFrm.h"
  16. #include "MFCTangramConfigDlg.h"
  17. #include "objbase.h"
  18. #include <oleauto.h>
  19. #include <stdlib.h> //for rand()
  20. #include <time.h>
  21.  
  22. // Interface definitions.
  23. #include "ATLModel.h"
  24. #include "ATLModel_i.c"
  25. #include "AtlTangramCanvas.h"
  26. #include "AtlTangramCanvas_i.c"
  27. #include "AtlGdiWorld_i.c"
  28. #include "AtlGdiWorld.h"
  29. #include "AtlGLWorld.h"
  30. #include "AtlGLWorld_i.c"
  31.  
  32. // Others
  33. #include "util.h"
  34. #include "util.cpp"
  35.  
  36.  
  37. #ifdef _DEBUG
  38. #define new DEBUG_NEW
  39. #undef THIS_FILE
  40. static char THIS_FILE[] = __FILE__;
  41. #endif
  42.  
  43. const int POLYGONS = 7;
  44.  
  45. ///////////////////////////////////////////////////////////
  46. //
  47. // Statics
  48. //
  49. CString CMFCMainFrame::s_strClassName = "" ;
  50.  
  51. /////////////////////////////////////////////////////////////////////////////
  52. // CMFCMainFrame
  53.  
  54. BEGIN_MESSAGE_MAP(CMFCMainFrame, CFrameWnd)
  55.     //{{AFX_MSG_MAP(CMFCMainFrame)
  56.     ON_WM_CREATE()
  57.     ON_WM_PAINT()
  58.     ON_WM_MOUSEMOVE()
  59.     ON_WM_LBUTTONDOWN()
  60.     ON_WM_LBUTTONUP()
  61.     ON_WM_RBUTTONDOWN()
  62.     ON_WM_RBUTTONUP()
  63.     ON_WM_PALETTECHANGED()
  64.     ON_WM_QUERYNEWPALETTE()
  65.     ON_WM_DESTROY()
  66.     //}}AFX_MSG_MAP
  67. END_MESSAGE_MAP()
  68.  
  69. static UINT indicators[] =
  70. {
  71.     ID_SEPARATOR,           // status line indicator
  72.     ID_INDICATOR_CAPS,
  73.     ID_INDICATOR_NUM,
  74.     ID_INDICATOR_SCRL,
  75. };
  76.  
  77. /////////////////////////////////////////////////////////////////////////////
  78. // CMFCMainFrame construction/destruction
  79.  
  80. ///////////////////////////////////////////////////////////
  81. //
  82. // Constructor
  83. //
  84. CMFCMainFrame::CMFCMainFrame()
  85. :   m_pWorld(NULL),
  86.     m_pSelectedVisual(NULL)
  87. {
  88.     m_sizedDiff.cx = 0.0 ;
  89.     m_sizedDiff.cy = 0.0 ;
  90. }
  91.  
  92. ///////////////////////////////////////////////////////////
  93. //
  94. // Destructor
  95. //
  96. CMFCMainFrame::~CMFCMainFrame()
  97. {
  98.     if (m_pWorld != NULL)
  99.     {
  100.         m_pWorld->Release() ;
  101.     }
  102.     POSITION pos = m_ModelList.GetHeadPosition();
  103.     while( pos != NULL )
  104.     {
  105.         IATLTangramModel* pITangramModel = m_ModelList.GetNext( pos ) ;
  106.         pITangramModel->Release();
  107.         m_ModelList.RemoveHead();
  108.     }
  109.     m_ModelList.RemoveAll();
  110.  
  111. /**/
  112. }
  113.  
  114.  
  115. int CMFCMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  116. {
  117.     if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  118.     {
  119.         TRACE0("Could not create main window.\r\n") ;
  120.         return -1;
  121.     }
  122.  
  123.     // Initialize
  124.     CRect aRect ;
  125.     GetClientRect(&aRect) ;
  126.     if (!Initialize(aRect.Width(), aRect.Height()))
  127.     {
  128.         TRACE0("Cannot initialize main window.\r\n") ;
  129.         return -1 ;
  130.     }
  131.  
  132.     return 0;
  133. }
  134.  
  135. BOOL CMFCMainFrame::PreCreateWindow(CREATESTRUCT& cs)
  136. {
  137.     // TODO: Modify the Window class or styles here by modifying
  138.     //  the CREATESTRUCT cs
  139.  
  140.     return CFrameWnd::PreCreateWindow(cs);
  141. }
  142.  
  143. /////////////////////////////////////////////////////////////////////////////
  144. // CMFCMainFrame diagnostics
  145.  
  146. #ifdef _DEBUG
  147. void CMFCMainFrame::AssertValid() const
  148. {
  149.     CFrameWnd::AssertValid();
  150. }
  151.  
  152. void CMFCMainFrame::Dump(CDumpContext& dc) const
  153. {
  154.     CFrameWnd::Dump(dc);
  155. }
  156.  
  157. #endif //_DEBUG
  158.  
  159. ///////////////////////////////////////////////////////////
  160. //
  161. // Initialize
  162. //
  163. BOOL CMFCMainFrame::Initialize(int cx, int cy)
  164. {
  165.     ASSERT( (cx != 0) && (cy != 0)) ;
  166.  
  167.     // Which components are in the IWorldComponent Category.
  168.     CMFCTangramConfigDlg dlg;
  169.     if (dlg.DoModal() != IDOK)
  170.     {
  171.         TRACE0("User canceled the dialog box. Fail initialization.\r\n") ;
  172.         return FALSE ;
  173.     }
  174.  
  175.     // Did the user want to use local or inproc?
  176.     DWORD clsctx = (dlg.m_bLocalModel) ? CLSCTX_LOCAL_SERVER : CLSCTX_INPROC_SERVER ;
  177.  
  178.     // Create the desired world selected component.
  179.     HRESULT hr = ::CoCreateInstance(    dlg.m_clsid,           // either Gdi or GL
  180.                                         NULL,
  181.                                         CLSCTX_INPROC_SERVER,
  182.                                         IID_IAtlTangramWorld,
  183.                                         reinterpret_cast<void**>(&m_pWorld)) ;
  184.     if (FAILED(hr))
  185.     {
  186.         ErrorMessage("Failed to create the world component.", hr) ;
  187.         return FALSE ;
  188.     }
  189.  
  190.     // Initialize the world.
  191.     hr = m_pWorld->Initialize(m_hWnd, 20.0, 20.0) ;
  192.     if (FAILED(hr))
  193.     {
  194.         ErrorMessage("Cannot initialize World.\r\n", hr) ;
  195.         m_pWorld->Release() ;
  196.         m_pWorld = NULL ;
  197.         return FALSE ;
  198.     }
  199.  
  200.     // Create and initialize the tangrams pieces.
  201.     struct PolygonInit{
  202.         int iSides ;
  203.         TangramPoint2d points[4] ;
  204.     };
  205.  
  206.     PolygonInit polygons[7] = {
  207.         // Sides   Vertex 0     1            2            3
  208.         { 4,  {{0.0, 0.0 }, {1.0, 0.0 }, {1.0, 1.0 }, {0.0, 1.0 }} }, // Square
  209.         { 3,  {{0.0, 0.0 }, {1.0, 0.0 }, {0.0, 1.0 }, {9.9, 9.9 }} }, // Small Triangle
  210.         { 3,  {{0.0, 0.0 }, {1.0, 0.0 }, {0.0, 1.0 }, {9.9, 9.9 }} }, // Small Triangle
  211.         { 3,  {{0.0, 0.0 }, {2.0, 0.0 }, {1.0, 1.0 }, {9.9, 9.9 }} }, // Medium Triangle
  212.         { 3,  {{0.0, 0.0 }, {2.0, 0.0 }, {0.0, 2.0 }, {9.9, 9.9 }} }, // Big Triangle
  213.         { 3,  {{0.0, 0.0 }, {2.0, 0.0 }, {0.0, 2.0 }, {9.9, 9.9 }} }, // Big Triangle
  214.         { 4,  {{0.0, 0.0 }, {1.0, 0.0 }, {2.0, 1.0 }, {1.0, 1.0 }} }, // Paralelagram
  215.     };
  216.  
  217.     double x = 0.0 ;
  218.     IATLTangramModel* pITangramModel = NULL ;
  219.  
  220.     for (int i = 0 ; i < POLYGONS ; i ++)
  221.     {
  222.         hr = ::CoCreateInstance(CLSID_ATLTangramModel,
  223.                                 NULL,
  224.                                 clsctx ,
  225.                                 IID_IATLTangramModel,
  226.                                 (void**)&pITangramModel);
  227.         if (FAILED(hr))
  228.         {
  229.             ErrorMessage("Failed to create Tangram piece.", hr) ;
  230.             return FALSE ;
  231.         }
  232.  
  233.         // Set the vertices for this model.
  234.         hr = pITangramModel->SetVertices(polygons[i].iSides, polygons[i].points) ;
  235.         ASSERT_HRESULT(hr) ;
  236.  
  237.         // Add the interface to the array.
  238.         // This makes a copy of the pointer without
  239.         // an AddRef(), so we don't have to Release() the
  240.         // model
  241.         m_ModelList.AddTail(pITangramModel) ;
  242.  
  243.         hr = m_pWorld->CreateVisualForModel(pITangramModel) ;
  244.         ASSERT_HRESULT(hr) ;
  245.  
  246.         // Get the IATLTangramTransform interface.
  247.         IATLTangramTransform* pITangramTransform = NULL ;
  248.         HRESULT hr = pITangramModel->QueryInterface(IID_IATLTangramTransform, (void**)&pITangramTransform ) ;
  249.         ASSERT_HRESULT(hr) ;
  250.  
  251.         // Place the tangram piece.
  252.         pITangramTransform->Translate(x, 1.0) ;
  253.         x += 2.0  ;
  254.  
  255.         // We are done with IATLTangramTransform.
  256.         pITangramTransform->Release() ;
  257.  
  258.     }
  259.  
  260.     return TRUE ;
  261. }
  262.  
  263. ///////////////////////////////////////////////////////////
  264. //
  265. // Create - Helper function for creating  the window class
  266. //              and window.
  267. //
  268. BOOL CMFCMainFrame::Create()
  269. {
  270.     if (s_strClassName.IsEmpty())
  271.     {
  272.         s_strClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
  273.                                             AfxGetApp()->LoadStandardCursor(IDC_ARROW),
  274.                                             0,
  275.                                             AfxGetApp()->LoadIcon(IDR_MAINFRAME));
  276.     }
  277.  
  278.     // Set screen size.
  279.     CClientDC dc(NULL) ;
  280.     int cx = 640 ;
  281.     int cy = 480 ;
  282.  
  283.     return CWnd::CreateEx(  0, s_strClassName, AfxGetAppName(),
  284.                             WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|
  285.                             WS_BORDER|WS_MINIMIZEBOX|WS_VISIBLE,
  286.                             0,0, cx, cy,
  287.                             NULL, NULL);
  288. }
  289.  
  290. ///////////////////////////////////////////////////////////
  291. //
  292. // OnPaint
  293. //
  294. void CMFCMainFrame::OnPaint()
  295. {
  296.     CPaintDC dc(this);
  297.  
  298.     // Get ICanvas interface pointer.
  299.     IAtlTangramCanvas* pCanvas = NULL ;
  300.     HRESULT hr = m_pWorld->QueryInterface(IID_IAtlTangramCanvas, (void**)&pCanvas) ;
  301.     ASSERT_HRESULT(hr) ;
  302.  
  303.     // Use it.
  304.     hr = pCanvas->Paint(dc.m_hDC, dc.m_ps.rcPaint) ;
  305.     ASSERT_HRESULT(hr) ;
  306.  
  307.     // Lose it.
  308.     pCanvas->Release() ;
  309. }
  310.  
  311. ///////////////////////////////////////////////////////////
  312. //
  313. // Handle both left and right button down messages.
  314. //
  315. void CMFCMainFrame::DoButtonDown(UINT nWhichButton, CPoint point)
  316. {
  317.     if (m_pSelectedVisual != NULL)
  318.     {
  319.         // User may have pressed right button then left button.
  320.         TRACE0("OnLButtonDown: Visual already selected.\r\n") ;
  321.         return ;
  322.     }
  323.  
  324.     HRESULT hr = m_pWorld->VisualFromPoint(point, IID_IAtlTangramVisual, (IUnknown**)&m_pSelectedVisual) ; //@
  325.     ASSERT(SUCCEEDED(hr)) ;
  326.     if (hr == S_OK)
  327.     {
  328.         ASSERT(m_pSelectedVisual != NULL) ;
  329.         //
  330.         // Get mouse pointer offset from model's origin.
  331.         //
  332.  
  333.         // Convert to Model Coordinates.
  334.         TangramPoint2d ptModel ;
  335.         hr = m_pWorld->DeviceToModel(point, &ptModel);
  336.         ASSERT_HRESULT(hr) ;
  337.  
  338.         // Get the Model's ITrangramTransform interface.
  339.         IATLTangramTransform* pITangramTransform = NULL ;
  340.         hr = m_pSelectedVisual->GetModel(IID_IATLTangramTransform, (IUnknown**)&pITangramTransform) ;
  341.         ASSERT_HRESULT(hr) ;
  342.  
  343.         // Where does the model reside.
  344.         TangramPoint2d ptOrigin ;
  345.         hr = pITangramTransform->GetTranslation(&ptOrigin) ;
  346.         ASSERT_HRESULT(hr) ;
  347.  
  348.         // Release ITangramTransfrom.
  349.         pITangramTransform->Release() ;
  350.         pITangramTransform = NULL ;
  351.  
  352.         // Get difference between where the mouse clicked and the origin of the piece.
  353.         m_sizedDiff.cx = ptModel.x - ptOrigin.x ;
  354.         m_sizedDiff.cy = ptModel.y - ptOrigin.y ;
  355.  
  356.         // Select the visual.
  357.         hr = m_pWorld->SelectVisual(m_pSelectedVisual, TRUE) ;
  358.         ASSERT_HRESULT(hr) ;
  359.  
  360.         // Update the display
  361.         hr = m_pWorld->Animate() ;
  362.         ASSERT_HRESULT(hr) ;
  363.  
  364.         // Capture the mouse.
  365.         SetCapture() ;
  366.         }
  367.     else
  368.     {
  369.         TRACE0("DoButtonDown: PtInVisual returned Null.\r\n") ;
  370.     }
  371. }
  372.  
  373. void CMFCMainFrame::PostNcDestroy()
  374. {
  375.     delete this;
  376. }
  377.  
  378. ///////////////////////////////////////////////////////////
  379. //
  380. // OnLButtonDown Message Handler
  381. //
  382. void CMFCMainFrame::OnLButtonDown(UINT nWhichButton, CPoint point)
  383. {
  384.     DoButtonDown(nWhichButton, point) ;
  385. }
  386.  
  387. ///////////////////////////////////////////////////////////
  388. //
  389. // OnLButtonUp Message Handler
  390. //
  391. void CMFCMainFrame::OnLButtonUp(UINT nWhichButton, CPoint point)
  392. {
  393.     if (::GetCapture() != m_hWnd)
  394.     {
  395.         return ;
  396.     }
  397.  
  398.     if (m_pSelectedVisual != NULL)
  399.     {
  400.         // De-select the currently selected model.
  401.         HRESULT hr = m_pWorld->SelectVisual(m_pSelectedVisual, FALSE) ;
  402.         ASSERT_HRESULT(hr) ;
  403.  
  404.         // Cleanup
  405.         m_pSelectedVisual->Release() ;
  406.         m_pSelectedVisual = NULL ;
  407.     }
  408.  
  409.     // We don't need the mouse capture any more.
  410.     ::ReleaseCapture() ;
  411. }
  412.  
  413. ///////////////////////////////////////////////////////////
  414. //
  415. // OnMouseMove Message Handler
  416. //
  417. void CMFCMainFrame::OnMouseMove(UINT nWhichButton, CPoint point)
  418. {
  419.     if ((::GetCapture() != m_hWnd) ||
  420.         (nWhichButton & (MK_SHIFT | MK_CONTROL)))
  421.     {
  422.         // Return if another window has captured the mouse or
  423.         // if the SHIFT or CTRL key is pressed, signaling rotation.
  424.         return ;
  425.     }
  426.  
  427.     // Make sure that mouse is not outside of our client area.
  428.     CRect rectClient ;
  429.     GetClientRect(&rectClient) ;
  430.     if (!rectClient.PtInRect(point))
  431.     {
  432.         return ;
  433.     }
  434.  
  435.     ASSERT(m_pSelectedVisual != NULL) ;
  436.  
  437.     // Convert to Model Coordinates.
  438.     TangramPoint2d ptModel ;
  439.     HRESULT hr = m_pWorld->DeviceToModel(point, &ptModel);
  440.     ASSERT_HRESULT(hr) ;
  441.  
  442.     //Get the Model's ITangramTransfrom interface.
  443.     IATLTangramTransform* pITangramTransform = NULL ;
  444.     hr = m_pSelectedVisual->GetModel(IID_IATLTangramTransform, (IUnknown**)&pITangramTransform) ;
  445.     ASSERT_HRESULT(hr) ;
  446.  
  447.     // Move the model.
  448.     hr = pITangramTransform->Translate(ptModel.x - m_sizedDiff.cx, ptModel.y - m_sizedDiff.cy);
  449.     ASSERT_HRESULT(hr) ;
  450.  
  451.     // Release the interface.
  452.     pITangramTransform->Release() ;
  453. }
  454.  
  455. ///////////////////////////////////////////////////////////
  456. //
  457. // Rotate using the right mouse button.
  458. //
  459. void CMFCMainFrame::OnRButtonDown(UINT nWhichButton, CPoint point)
  460. {
  461.     DoButtonDown(nWhichButton, point) ;
  462. }
  463.  
  464. ///////////////////////////////////////////////////////////
  465. //
  466. // Rotate the model. Shift key determines direction.
  467. //
  468. void CMFCMainFrame::OnRButtonUp(UINT nWhichButton, CPoint point)
  469. {
  470.     if (::GetCapture() != m_hWnd)
  471.     {
  472.         return ;
  473.     }
  474.  
  475.     if (m_pSelectedVisual != NULL)
  476.     {
  477.         //----- Rotate the shape. -----
  478.  
  479.         // Check to see of the mouse pointer is still over the same visual.
  480.         IAtlTangramVisual* pSameVisual = NULL ;
  481.         HRESULT hr = m_pWorld->VisualFromPoint(point, IID_IAtlTangramVisual, (IUnknown**)&pSameVisual) ;
  482.         ASSERT_HRESULT(hr) ;
  483.         ASSERT(pSameVisual != NULL) ;
  484.  
  485.         if (::InterfacesAreOnSameComponent(m_pSelectedVisual, pSameVisual))
  486.         {
  487.             //Get the Model's IATLTangramTransform interface.
  488.             IATLTangramTransform* pITangramTransform = NULL ;
  489.             hr = m_pSelectedVisual->GetModel(IID_IATLTangramTransform, (IUnknown**)&pITangramTransform);
  490.             ASSERT_HRESULT(hr) ;
  491.  
  492.             // Rotate the model.
  493.             int iRotationDirection = (nWhichButton & MK_SHIFT) ? -1 : 1 ;
  494.             double dDegrees  ;
  495.             pITangramTransform->GetRotation(&dDegrees) ;
  496.             pITangramTransform->Rotate(dDegrees + 45.0*iRotationDirection);
  497.  
  498.             // Release IATLTangramTransform
  499.             pITangramTransform->Release() ;
  500.             pITangramTransform = NULL ;
  501.         }
  502.  
  503.         // Cleanup
  504.         pSameVisual->Release() ;
  505.         pSameVisual = NULL ;
  506.  
  507.         // De-select the currently selected model.
  508.         hr = m_pWorld->SelectVisual(m_pSelectedVisual, FALSE) ;
  509.         ASSERT_HRESULT(hr) ;
  510.  
  511.         // Cleanup
  512.         m_pSelectedVisual->Release() ;
  513.         m_pSelectedVisual = NULL ;
  514.     }
  515.  
  516.     // We don't need the mouse capture any more.
  517.     ::ReleaseCapture() ;
  518. }
  519.  
  520. ///////////////////////////////////////////////////////////
  521. //
  522. // OnPaletteChanged Message Handler
  523. //
  524. void CMFCMainFrame::OnPaletteChanged(CWnd* pFocusWnd)
  525. {
  526.     if (pFocusWnd != this)
  527.     {
  528.         OnQueryNewPalette() ;
  529.     }
  530. }
  531.  
  532. ///////////////////////////////////////////////////////////
  533. //
  534. // QueryNewPalette Message Handler
  535. //
  536. BOOL CMFCMainFrame::OnQueryNewPalette()
  537. {
  538.     if (m_hWnd == NULL)
  539.     {
  540.         return FALSE ;
  541.     }
  542.  
  543.     // Get ICanvas interface pointer.
  544.     IAtlTangramCanvas* pCanvas = NULL ;
  545.     HRESULT hr = m_pWorld->QueryInterface(IID_IAtlTangramCanvas, (void**)&pCanvas) ;
  546.     if (SUCCEEDED(hr))
  547.     {
  548.         // Use it.
  549.         hr = pCanvas->OnQueryNewPalette(m_hWnd);
  550.  
  551.         // Lose it.
  552.         pCanvas->Release() ;
  553.     }
  554.     return SUCCEEDED(hr);
  555. }
  556.  
  557.  
  558.  
  559. void CMFCMainFrame::OnDestroy()
  560. {
  561.     CFrameWnd::OnDestroy();
  562. /*
  563.     POSITION pos = m_ModelList.GetHeadPosition();
  564.     while( pos != NULL )
  565.     {
  566.         IATLTangramModel* pITangramModel = m_ModelList.GetNext( pos ) ;
  567.         pITangramModel->Release();
  568.         m_ModelList.RemoveHead();
  569.     }
  570.     m_ModelList.RemoveAll();
  571.     if (m_pWorld != NULL)
  572.     {
  573.         m_pWorld->Release() ;
  574.     }
  575.     */
  576. }
  577.