MAINFRM.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

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