MapHelper.cpp
上传用户:qinfarui
上传日期:2022-08-10
资源大小:362k
文件大小:22k
源码类别:

GIS编程

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////////
  2. // MapHelper.cpp - Utility routines for working with the MapObjects control
  3. // 
  4. #include "stdafx.h"
  5. #include <math.h>
  6. #include <afxctl.h>
  7. #include "maphelper.h"
  8. ///////////////////////////////////////////////////////////////////////////
  9. // Data Directory
  10. //
  11. CDataDir::CDataDir()
  12. : m_path("..\..\data")
  13. {
  14. }
  15. CString CDataDir::GetPath()
  16. {
  17. return m_path;
  18. }
  19. void CDataDir::SetPath(LPCTSTR newPath)
  20. {
  21. m_path = newPath;
  22. }
  23. ///////////////////////////////////////////////////////////////////////////
  24. // File name handling
  25. //
  26. CString GetFileDirectory(const CString& path)
  27. {
  28. ASSERT(path.GetLength());
  29. int pos = path.ReverseFind('\');
  30. if (pos >= 0)
  31. return path.Left(pos);
  32. return "";
  33. }
  34. CString GetFileName(const CString& path)
  35. {
  36. ASSERT(path.GetLength());
  37. int pos = path.ReverseFind('\');
  38. if (pos >= 0)
  39. return path.Right(path.GetLength() - pos - 1);
  40. return "";
  41. }
  42. CString GetFileExt(const CString& path)
  43. {
  44. ASSERT(path.GetLength());
  45. int pos = path.ReverseFind('.');
  46. if (pos >= 0)
  47. return path.Right(path.GetLength() - pos - 1);
  48. return "";
  49. }
  50. CString GetFileTitle(const CString& path)
  51. {
  52. ASSERT(path.GetLength());
  53. CString strResult = GetFileName(path);
  54. int pos = strResult.ReverseFind('.');
  55. if (pos >= 0)
  56. return strResult.Left(pos);
  57. return strResult;
  58. }
  59. ///////////////////////////////////////////////////////////////////////////
  60. // Layer Management
  61. //
  62. void AddLayer(CMap1& map)
  63. {
  64. CString filter(TEXT("ESRI Shapefiles (*.shp)|*.shp|"));
  65. CString allFormats = TEXT("All supported formats|*.shp");
  66. #if 0
  67. // add the image filters to the end of the string
  68. ImageFactory::FormatDescArray formats;
  69. ImageFactory::QueryFormats(formats);
  70. for (int i = 0; i < formats.GetSize(); i++)
  71. {
  72. if (formats[i].m_extensions.GetLength() == 0) continue;
  73. filter += formats[i].m_name + TEXT("|");
  74. filter += formats[i].m_extensions + TEXT("|");
  75. allFormats += TEXT(";") + formats[i].m_extensions;
  76. }
  77. filter = allFormats + TEXT("|") + filter + TEXT("|");
  78. #endif
  79. CFileDialog dlg(TRUE, TEXT(".shp"), 0, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, filter);
  80. if (dlg.DoModal() == IDOK)
  81. {
  82. CString ext = GetFileExt(dlg.GetPathName());
  83. if (ext.CompareNoCase(TEXT("shp")) == 0)
  84. AddLayer(map, dlg.GetPathName());
  85. else
  86. AddImageLayer(map, dlg.GetPathName());
  87. }
  88. }
  89. void AddLayer(CMap1& map, const CString& path, COLORREF color, LPDISPATCH renderer)
  90. {
  91. // Establish connection to data
  92. CMoDataConnection conn;
  93. if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
  94. throw "unable to create MapObjects2.DataConnection";
  95. conn.SetDatabase(GetFileDirectory(path));
  96. if (!conn.Connect())
  97. throw "unable to connect to database";
  98. // Add layer specified by path
  99. CMoLayers layers(map.GetLayers());
  100. CMoMapLayer layer;
  101.   if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
  102. throw "unable to create MapObjects2.MapLayer";
  103. CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)));
  104. layer.SetGeoDataset(geoDataset);
  105. if (color != -1) // Set color if specified
  106. {
  107. CMoSymbol layerSymbol(layer.GetSymbol());
  108. layerSymbol.SetColor(color);
  109. }
  110. if (renderer)
  111. layer.SetRenderer(renderer);
  112. layers.Add(layer);
  113. }
  114. void AddLabelLayer(CMap1& map, const CString& path, LPCTSTR labelField, COLORREF color)
  115. {
  116. // Establish connection to data
  117. CMoDataConnection conn;
  118. if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
  119. throw "unable to create MapObjects2.DataConnection";
  120. conn.SetDatabase(GetFileDirectory(path));
  121. if (!conn.Connect())
  122. throw "unable to connect to database";
  123. // Add layer specified by path
  124. CMoLayers layers(map.GetLayers());
  125. CMoMapLayer layer;
  126.   if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
  127. throw "unable to create MapObjects2.MapLayer";
  128. CMoGeoDataset geoDataset(conn.FindGeoDataset(GetFileTitle(path)));
  129. layer.SetGeoDataset(geoDataset);
  130. // Setup label renderer
  131. CMoLabelRenderer lr;
  132. lr.CreateDispatch("MapObjects2.LabelRenderer");
  133. lr.SetField(labelField);
  134. lr.SetDrawBackground(FALSE);
  135. CMoTextSymbol sym(lr.GetSymbol(0));
  136. CFontHolder font(0);
  137. const FONTDESC fd = { sizeof(FONTDESC), OLESTR("Arial"), FONTSIZE(12), FW_NORMAL, ANSI_CHARSET, FALSE, FALSE, FALSE };
  138. //font.InitializeFont(&fd, sym.GetFont());
  139. font.InitializeFont(&fd);
  140. sym.SetFont(font.GetFontDispatch());
  141. if (color != -1)
  142. sym.SetColor(color);
  143. sym.SetVerticalAlignment(moAlignBottom);
  144. sym.SetHorizontalAlignment(moAlignLeft);
  145. layer.SetRenderer(lr);
  146. layers.Add(layer);
  147. }
  148. void AddImageLayer(CMap1& map, const CString& path)
  149. {
  150. // Establish connection to data
  151. CMoDataConnection conn;
  152. if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
  153. throw "unable to create MapObjects2.DataConnection";
  154. conn.SetDatabase(GetFileDirectory(path));
  155. if (!conn.Connect())
  156. throw "unable to connect to database";
  157. // Add image layer
  158. CMoLayers layers(map.GetLayers());
  159. CMoImageLayer image;
  160.   if (!image.CreateDispatch(TEXT("MapObjects2.ImageLayer")))
  161. throw "unable to create MapObjects2.ImageLayer";
  162. image.SetFile(path);
  163. layers.Add(image);
  164. }
  165. void AddSDELayer(CMap1& map, LPCTSTR server, LPCTSTR user, 
  166.  LPCTSTR password, LPCTSTR db, COLORREF color)
  167. {
  168. // Establish connection to data
  169. CMoDataConnection conn;
  170. if (!conn.CreateDispatch(TEXT("MapObjects2.DataConnection")))
  171. throw "unable to create MapObjects2.DataConnection";
  172. conn.SetServer(server);
  173. conn.SetUser(user);
  174. conn.SetPassword(password);
  175. conn.SetDatabase(db);
  176. if (!conn.Connect())
  177. throw "unable to connect to database";
  178. // Add layer specified by path
  179. CMoLayers layers(map.GetLayers());
  180. CMoMapLayer layer;
  181.   if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
  182. throw "unable to create MapObjects2.MapLayer";
  183. CMoGeoDataset geoDataset(conn.FindGeoDataset(db));
  184. layer.SetGeoDataset(geoDataset);
  185. if (color != -1) // Set color if specified
  186. {
  187. CMoSymbol layerSymbol(layer.GetSymbol());
  188. layerSymbol.SetColor(color);
  189. }
  190. layers.Add(layer);
  191. }
  192. //
  193. // All layer objects support the GetLayerType method.
  194. // Each object's dispatch ID for the property is different 
  195. // though.  Given the object's dispatch pointer, lookup 
  196. // the dispatch ID for the LayerType property then call 
  197. // Invoke to get the layer type.
  198. //
  199. short GetLayerType(CMoLayers& layers, short layerNum)
  200. {
  201. USES_CONVERSION;
  202. short layerType = -1;
  203. LPCOLESTR lpOleStr = T2COLE(TEXT("LayerType"));
  204. DISPID dispID = -1;
  205. COleDispatchDriver dd(layers.Item(COleVariant(layerNum)));
  206. if (SUCCEEDED(LPDISPATCH(dd)->GetIDsOfNames(IID_NULL,
  207. (LPOLESTR*)&lpOleStr, 1, 0, &dispID)))
  208. {
  209. dd.GetProperty(dispID, VT_I2, &layerType);
  210. }
  211. return layerType;
  212. }
  213. //
  214. // Works with Redlands sample data
  215. //
  216. LPDISPATCH CreateStreetRenderer()
  217. {
  218. CMoSymbol sym;
  219. CMoValueMapRenderer vr;
  220. VERIFY(vr.CreateDispatch("MapObjects2.ValueMapRenderer"));
  221. vr.SetField(TEXT("CFCC"));
  222. vr.SetSymbolType(moLineSymbol);
  223. vr.SetValueCount(6);
  224. vr.SetValue(0, TEXT("A11"));
  225. sym.AttachDispatch(vr.GetSymbol(0));
  226. sym.SetColor(moBlue);
  227. sym.SetSize(9);
  228. vr.SetValue(1, TEXT("A15"));
  229. sym.AttachDispatch(vr.GetSymbol(1));
  230. sym.SetColor(moBlue);
  231. sym.SetSize(9);
  232. vr.SetValue(2, TEXT("A20"));
  233. sym.AttachDispatch(vr.GetSymbol(2));
  234. sym.SetColor(moNavy);
  235. sym.SetSize(5);
  236. vr.SetValue(3, TEXT("A21"));
  237. sym.AttachDispatch(vr.GetSymbol(3));
  238. sym.SetColor(moNavy);
  239. sym.SetSize(5);
  240. vr.SetValue(4, TEXT("A31"));
  241. sym.AttachDispatch(vr.GetSymbol(4));
  242. sym.SetColor(moBrown);
  243. sym.SetSize(2);
  244. vr.SetValue(5, TEXT("A63"));
  245. sym.AttachDispatch(vr.GetSymbol(5));
  246. sym.SetColor(moRed);
  247. sym.SetSize(5);
  248. sym.AttachDispatch(vr.GetDefaultSymbol());
  249. sym.SetColor(moGray);
  250. sym.SetSize(2);
  251. LPDISPATCH(vr)->AddRef();
  252. return LPDISPATCH(vr);
  253. }
  254. ///////////////////////////////////////////////////////////////////////////
  255. // Zoom and Pan
  256. //
  257. void ZoomIn(CMap1& map) 
  258. {
  259. CMoRectangle r(map.TrackRectangle());
  260. if (LPDISPATCH(r))
  261. map.SetExtent(r);
  262. }
  263. void ZoomOut(CMap1& map) 
  264. {
  265. CMoRectangle r(map.GetExtent());
  266. ASSERT(LPDISPATCH(r));
  267. r.ScaleRectangle(1.5);
  268. map.SetExtent(r);
  269. }
  270. void ZoomFull(CMap1& map) 
  271. {
  272. CMoRectangle r(map.GetFullExtent());
  273. ASSERT(LPDISPATCH(r));
  274. map.SetExtent(r);
  275. }
  276. void Pan(CMap1& map) 
  277. {
  278. map.Pan();
  279. }
  280. void Resize(CMap1& map, int cx, int cy, int border) 
  281. {
  282. if (map.m_hWnd)
  283. map.SetWindowPos(0, border, border, cx - border, cy - border, SWP_NOZORDER);
  284. }
  285. ///////////////////////////////////////////////////////////////////////////
  286. // Conversion
  287. //
  288. double DegreesToMiles(double x1, double y1, double x2, double y2)
  289. {
  290. // H. Andoyer: [Annuaire du Bureau des Longitudes, 1950, Paris, p. 145] 
  291. if (x1 == x2 && y1 == y2)
  292. return 0;
  293. double a = 6378137;      // Use GRS 80 spheroid 
  294. double f = 0.003352813;  // 1 / 298.257 
  295. double F = (DEG2RAD(y1) + DEG2RAD(y2)) / 2.0;
  296. double G = (DEG2RAD(y1) - DEG2RAD(y2)) / 2.0;
  297. double l = (DEG2RAD(x1) - DEG2RAD(x2)) / 2.0;
  298. double sF2 = pow(sin(F),2);
  299. double cF2 = pow(cos(F),2);
  300. double sG2 = pow(sin(G),2);
  301. double cG2 = pow(cos(G),2);
  302. double sL2 = pow(sin(l),2);
  303. double cL2 = pow(cos(l),2);
  304. double S = sG2*cL2 + cF2*sL2;
  305. double C = cG2*cL2 + sF2*sL2;
  306. double omega = atan(sqrt(S/C));
  307. double rho = sqrt(S*C) / omega;
  308. double D = 2*a*omega;
  309. double H1 = (3*rho - 1) / (2*C);
  310. double H2 = (3*rho + 1) / (2*S);
  311. double m = D*(1 + f*(H1*sF2*cG2 - H2*cF2*sG2));
  312. return m * 0.0006214;
  313. }
  314. ///////////////////////////////////////////////////////////////////////////
  315. // Miscellaneous
  316. //
  317. LPDISPATCH GetIDispatch(CMap1& map)
  318. {
  319. LPDISPATCH pDispatch = 0;
  320. LPUNKNOWN pUnknown = map.GetControlUnknown();
  321. if (pUnknown)
  322. pUnknown->QueryInterface(IID_IDispatch, (void**)&pDispatch);
  323. return pDispatch;
  324. }
  325. double GetAspectRatio(CMap1& map)
  326. {
  327. CMoRectangle r(map.GetExtent());
  328. return (double)r.GetWidth() / (double)r.GetHeight();
  329. }
  330. //
  331. // Use ratio of map to window to calculate map point
  332. //
  333. LPDISPATCH ToMapPoint(CMap1& map, long x, long y)
  334. {
  335. ASSERT(map.m_hWnd);
  336. CRect client;
  337. map.GetClientRect(&client);
  338. CMoRectangle bounds(map.GetExtent());
  339. double mapX = bounds.GetLeft() + (double)x * bounds.GetWidth() / (double)client.Width();
  340. double mapY = bounds.GetTop() - (double)y * bounds.GetHeight() / (double)client.Height();
  341. CMoPoint mapPoint;
  342. mapPoint.CreateDispatch(TEXT("MapObjects2.Point"));
  343. mapPoint.SetX(mapX);
  344. mapPoint.SetY(mapY);
  345. LPDISPATCH(mapPoint)->AddRef(); // Client is responsible for release
  346. return mapPoint;
  347. }
  348. void FromMapPoint(CMap1& map, CMoPoint& pt, long& x, long& y)
  349. {
  350. ASSERT(map.m_hWnd);
  351. CRect client;
  352. map.GetClientRect(&client);
  353. CMoRectangle bounds(map.GetExtent());
  354. x = (long)MULDIV((pt.GetX() - bounds.GetLeft()), client.Width(), bounds.GetWidth());
  355. y = (long)MULDIV((bounds.GetTop() - pt.GetY()),  client.Height(), bounds.GetHeight());
  356. }
  357. double ToMapDistance(CMap1& map, long x)
  358. ASSERT(map.m_hWnd); 
  359. CRect client; 
  360. map.GetClientRect(&client);
  361. CMoRectangle bounds(map.GetExtent());
  362. return (double)x * bounds.GetWidth() / (double)client.Width(); 
  363. }
  364. long FromMapDistance(CMap1& map, double& mapX)
  365. {
  366. ASSERT(map.m_hWnd);
  367. CRect client;
  368. map.GetClientRect(&client);
  369. CMoRectangle bounds(map.GetExtent());
  370. return (long)MULDIV(mapX, client.Width(), bounds.GetWidth());
  371. }
  372. ///////////////////////////////////////////////////////////////////////////
  373. // Geodatasets
  374. //
  375. void SetValue(CMoFields& fields, LPCTSTR name, VARIANT& value)
  376. {
  377. // Find the field
  378. CMoField field(fields.Item(COleVariant(name)));
  379. // Set the field value
  380. field.SetValue(value);
  381. }
  382. void SetValue(CMoFields& fields, LPCTSTR name, const LONG value)
  383. {
  384. VARIANT v;
  385. v.vt = VT_I4;
  386. v.lVal = value;
  387. SetValue(fields, name, v);
  388. }
  389. void SetValue(CMoFields& fields, LPCTSTR name, const double value)
  390. {
  391. VARIANT v;
  392. v.vt = VT_R8;
  393. v.dblVal = value;
  394. SetValue(fields, name, v);
  395. }
  396. void SetValue(CMoFields& fields, LPCTSTR name, const COleDateTime& value)
  397. {
  398. VARIANT v;
  399. v.vt = VT_DATE;
  400. v.date = value.m_dt;
  401. SetValue(fields, name, v);
  402. }
  403. void SetValue(CMoFields& fields, LPCTSTR name, const LPCTSTR value)
  404. {
  405. SetValue(fields, name, COleVariant(value));
  406. }
  407. void SetValue(CMoFields& fields, LPCTSTR name, const BOOL value)
  408. {
  409. VARIANT v;
  410. v.vt = VT_BOOL;
  411. v.bVal = value;
  412. SetValue(fields, name, v);
  413. }
  414. void SetValue(CMoFields& fields, LPCTSTR name, const LPDISPATCH value)
  415. {
  416. VARIANT v;
  417. v.vt = VT_DISPATCH;
  418. v.pdispVal = value;
  419. SetValue(fields, name, v);
  420. }
  421. ///////////////////////////////////////////////////////////////////////////
  422. // Printing and Export
  423. //
  424. static void S_AdjustWidthToRatio(CRect& r, const double ratio, const UINT align = DT_CENTER)
  425. {
  426. int newWidth = (int)MULT(r.Height(), ratio);
  427. int offset;
  428. if (align & DT_CENTER)
  429. offset = (int)DIV((double)r.Width() - newWidth, 2);
  430. else if (align & DT_RIGHT)
  431. offset = r.Width() - newWidth;
  432. else
  433. offset = 0;
  434. r.left += offset;
  435. r.right = r.left + newWidth;
  436. }
  437. static void S_AdjustHeightToRatio(CRect& r, const double ratio, const UINT align = DT_VCENTER)
  438. {
  439. int newHeight = (int)DIV(r.Width(), ratio);
  440. int offset;
  441. if (align & DT_VCENTER)
  442. offset = (int)DIV((double)r.Height() - newHeight, 2);
  443. else if (align & DT_BOTTOM)
  444. offset = r.Height() - newHeight;
  445. else 
  446. offset = 0;
  447. r.top += offset;
  448. r.bottom = r.top + newHeight;
  449. }
  450. //
  451. // Adjust the rectangle to match the aspect ratio specified
  452. // Use the following values or'd together for alignment:
  453. //
  454. // DT_TOP,  DT_VCENTER, DT_BOTTOM
  455. // DT_LEFT, DT_CENTER,  DT_RIGHT
  456. //
  457. CRect AdjustToRatio(const CRect& r, const double ratio, const UINT align)
  458. {
  459. CRect newRect = r;
  460. // First try simple adjustment
  461. if (ratio < 1.0)
  462. S_AdjustWidthToRatio(newRect, ratio, align);
  463. else
  464. S_AdjustHeightToRatio(newRect, ratio, align);
  465. // Didn't fit.  Adjust again.
  466. if (r.Width() < newRect.Width())
  467. {
  468. newRect.left = r.left;
  469. newRect.right = r.right;
  470. S_AdjustHeightToRatio(newRect, ratio, align);
  471. }
  472. if (r.Height() < newRect.Height())
  473. {
  474. newRect.top = r.top;
  475. newRect.bottom = r.bottom;
  476. S_AdjustWidthToRatio(newRect, ratio, align);
  477. }
  478. return newRect;
  479. }
  480. //
  481. // Calculate the size of the output device in pixels
  482. //
  483. CRect GetDeviceRect(CDC* pDC)
  484. {
  485. CRect devRect;
  486. // HDC hDC = pDC->m_hAttribDC;
  487. HDC hDC = pDC->GetSafeHdc();
  488. int type = ::GetObjectType(hDC);
  489. switch (type)
  490. {
  491. case OBJ_DC: // Printer or screen
  492. //
  493. // If there's a window associated with 
  494. // the DC, use the client area.  Otherwise
  495. // use the device width.
  496. //
  497. HWND hWnd;
  498. if (hWnd = ::WindowFromDC(hDC))
  499. ::GetClientRect(hWnd, &devRect);
  500. else
  501. devRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
  502. break;
  503. case OBJ_MEMDC: // Memory bitmap
  504. //
  505. // Use the bitmap size
  506. //
  507. HBITMAP hBitmap;
  508. hBitmap = (HBITMAP)::GetCurrentObject(pDC->GetSafeHdc(), OBJ_BITMAP);
  509. if (!hBitmap)
  510. throw "error with memory DC";
  511. BITMAP bm;
  512. VERIFY(::GetObject(hBitmap, sizeof(BITMAP), &bm));
  513. if (bm.bmWidth == 0 || bm.bmHeight == 0)
  514. throw "error with memory DC";;
  515. devRect.SetRect(0, 0, bm.bmWidth, bm.bmHeight);
  516. break;
  517. default: 
  518. devRect.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
  519. if (devRect.right == 0)
  520. {
  521. CClientDC dc(0);
  522. devRect.SetRect(0, 0, dc.GetDeviceCaps(HORZRES), dc.GetDeviceCaps(VERTRES));
  523. }
  524. break;
  525. }
  526. return devRect;
  527. }
  528. //
  529. // Work-around that allows you to draw maps on an old style windows
  530. // metafile.
  531. //
  532. void OutputMap(CMap1& map, CMetaFileDC* pDC)
  533. {
  534. map.ExportMap(moExportClipboardEMF, TEXT("TRUE"), 1.0); // system generates old-style metafile
  535. if (::OpenClipboard(::GetFocus()))
  536. {
  537. HANDLE hMFP = ::GetClipboardData(CF_METAFILEPICT);
  538. METAFILEPICT* pMFP = (METAFILEPICT*)::GlobalLock(hMFP);
  539. if (pMFP)
  540. {
  541. VERIFY(::PlayMetaFile(pDC->GetSafeHdc(), pMFP->hMF));
  542. ::GlobalUnlock(hMFP);
  543. }
  544. VERIFY(::CloseClipboard());
  545. }
  546. }
  547. //
  548. // Draw the map, scaling it to a frame on the surface of the 
  549. // device referenced by the DC.  If the frame doesn't match the
  550. // aspect ratio of the map, the map is position as specified 
  551. // by hAlign and vAlign within the frame.  Use the following
  552. // values or'd together for alignment:
  553. //
  554. // DT_TOP,  DT_VCENTER, DT_BOTTOM
  555. // DT_LEFT, DT_CENTER,  DT_RIGHT
  556. //
  557. void FrameMap(CMap1& map, CDC* pDC, const CRect& dstRect, const UINT align)
  558. {
  559. //
  560. // Create a frame of the same aspect ratio as the map and 
  561. // center or left justify it in dstRect.
  562. //
  563. double aspectRatio = GetAspectRatio(map);
  564. CRect frame = AdjustToRatio(dstRect, aspectRatio, align);
  565. //
  566. // Use GDI to position map on page
  567. //
  568. CRect devRect = AdjustToRatio(GetDeviceRect(pDC), aspectRatio);
  569. int saveID = pDC->SaveDC();
  570. pDC->SetMapMode(MM_ISOTROPIC); 
  571. pDC->SetWindowOrg(devRect.left, devRect.top); 
  572. pDC->SetWindowExt(devRect.Width(), devRect.Height()); 
  573. pDC->SetViewportOrg(frame.left, frame.top);
  574. pDC->SetViewportExt(frame.Width(), frame.Height());
  575. map.OutputMap((OLE_HANDLE)pDC->GetSafeHdc());
  576. pDC->RestoreDC(saveID);
  577. #if 0
  578. // Rectangles for testing
  579. HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
  580. HBRUSH hOldBrush = (HBRUSH)::SelectObject(pDC->GetSafeHdc(), hBrush);
  581. pDC->Rectangle(dstRect);
  582. HPEN   hPen = (HPEN)::CreatePen(PS_SOLID, 0, RGB(255, 0, 0));
  583. HPEN   hOldPen = (HPEN)::SelectObject(pDC->GetSafeHdc(), hPen);
  584. pDC->Rectangle(frame);
  585. ::SelectObject(pDC->GetSafeHdc(), hOldPen);
  586. ::SelectObject(pDC->GetSafeHdc(), hOldBrush);
  587. #endif
  588. }
  589. ///////////////////////////////////////////////////////////////////////////
  590. // OLE Fonts
  591. //
  592. CMoFont::CMoFont()
  593. : CFontHolder(0),
  594. m_pFontDisp(0),
  595. m_pDispatch(0)
  596. {
  597. CFontDesc fontDesc;
  598. InitializeFont(&fontDesc, 0);
  599. }
  600. CMoFont::CMoFont(LPFONTDISP pFontDisp)
  601. : CFontHolder(0)
  602. {
  603. InitializeFont(0, pFontDisp);
  604. // similar to COleDispatchDriver::CreateDispatch()
  605. }
  606. CMoFont::~CMoFont()
  607. {
  608. ReleaseDispatch();
  609. }
  610. void CMoFont::AttachDispatch(LPFONTDISP pFontDisp)
  611. {
  612. ReleaseDispatch();
  613. InitializeFont(0, pFontDisp);
  614. }
  615. void CMoFont::ReleaseDispatch()
  616. {
  617. if (m_pFontDisp)
  618. {
  619. m_pFontDisp->Release();
  620. m_pFontDisp = 0;
  621. }
  622. if (m_pDispatch)
  623. {
  624. m_pDispatch->Release();
  625. m_pDispatch = 0;
  626. }
  627. }
  628. CMoFont::operator LPFONTDISP() 
  629. if (m_pFontDisp == 0)
  630. m_pFontDisp = GetFontDispatch(); // must release;
  631. return m_pFontDisp; 
  632. }
  633. CMoFont::operator LPDISPATCH() 
  634. if (m_pDispatch == 0)
  635. {
  636. LPFONTDISP pFontDisp = this->operator LPFONTDISP();
  637. pFontDisp->QueryInterface(IID_IDispatch, (void**)&m_pDispatch); // must release;
  638. }
  639. return m_pDispatch; 
  640. }
  641. LPCTSTR CMoFont::GetName()
  642. {
  643. USES_CONVERSION;
  644. ASSERT(m_pFont);
  645. BSTR pName;   
  646. m_pFont->get_Name(&pName);
  647. return OLE2T(pName);
  648. }
  649. void CMoFont::SetName(LPCTSTR name)
  650. {
  651. USES_CONVERSION;
  652. ASSERT(m_pFont);
  653. m_pFont->put_Name(T2OLE(name));
  654. }
  655. long CMoFont::GetSize()
  656. {
  657. ASSERT(m_pFont);
  658. CY size;
  659. m_pFont->get_Size(&size);
  660. return (long)DIV(size.int64, 10000);
  661. }
  662. void CMoFont::SetSize(long size)
  663. {
  664. ASSERT(m_pFont);
  665. CY _size = { size * 10000, 0 };
  666. m_pFont->put_Size(_size);
  667. }
  668. short CMoFont::GetWeight()
  669. {
  670. ASSERT(m_pFont);
  671. short weight;
  672. m_pFont->get_Weight(&weight);
  673. return weight;
  674. }
  675. void CMoFont::SetWeight(short weight)
  676. {
  677. ASSERT(m_pFont);
  678. m_pFont->put_Weight(weight);
  679. }
  680. short CMoFont::GetCharSet()
  681. {
  682. ASSERT(m_pFont);
  683. short charSet;
  684. m_pFont->get_Charset(&charSet);
  685. return charSet;
  686. }
  687. void CMoFont::SetCharSet(short charset)
  688. {
  689. ASSERT(m_pFont);
  690. m_pFont->put_Charset(charset);
  691. }
  692. BOOL CMoFont::GetItalic()
  693. {
  694. ASSERT(m_pFont);
  695. BOOL flag;
  696. m_pFont->get_Italic(&flag);
  697. return flag;
  698. }
  699. void CMoFont::SetItalic(BOOL italic)
  700. {
  701. ASSERT(m_pFont);
  702. m_pFont->put_Italic(italic);
  703. }
  704. BOOL CMoFont::GetUnderline()
  705. {
  706. ASSERT(m_pFont);
  707. BOOL flag;
  708. m_pFont->get_Underline(&flag);
  709. return flag;
  710. }
  711. void CMoFont::SetUnderline(BOOL underline)
  712. {
  713. ASSERT(m_pFont);
  714. m_pFont->put_Underline(underline);
  715. }
  716. BOOL CMoFont::GetStrikeThrough()
  717. {
  718. ASSERT(m_pFont);
  719. BOOL flag;
  720. m_pFont->get_Strikethrough(&flag);
  721. return flag;
  722. }
  723. void CMoFont::SetStrikeThrough(BOOL strikeThrough)
  724. {
  725. ASSERT(m_pFont);
  726. m_pFont->put_Strikethrough(strikeThrough);
  727. }
  728. ///////////////////////////////////////////////////////////////////////////
  729. // Collection Iterator
  730. //
  731. CMoIterator::CMoIterator(COleDispatchDriver& collection)
  732. : m_pEnumVariant(0)
  733. {
  734. //
  735. // Find out if collection is really a collection
  736. // by querying for the _NewEnum property and 
  737. // assigning the m_pEnumVariant pointer to it.
  738. //
  739. USES_CONVERSION;
  740. LPCOLESTR pName = T2COLE(TEXT("_NewEnum"));
  741. DISPID dispID = -1;
  742. if (!SUCCEEDED(LPDISPATCH(collection)->GetIDsOfNames(IID_NULL, (OLECHAR**)&pName, 1, 0, &dispID)))
  743. throw "invalid collection object";
  744. LPUNKNOWN pUnknown = 0;
  745. collection.GetProperty(dispID, VT_UNKNOWN, &pUnknown);
  746. if (pUnknown == 0)
  747. throw "unable to get IUnknown for collection object";
  748. pUnknown->QueryInterface(IID_IEnumVARIANT, (void**)&m_pEnumVariant);
  749. pUnknown->Release();
  750. if (m_pEnumVariant == 0) 
  751. throw "unable to get IEnumVARIANT for collection object";
  752. Reset(); // might not need this.
  753. // success, collection has _NewEnum property!
  754. }
  755. //
  756. // Sets item to next element of collection
  757. // 
  758. BOOL CMoIterator::Next(COleDispatchDriver& item)
  759. {
  760. HRESULT result = S_FALSE;
  761. ASSERT(m_pEnumVariant);
  762. if (m_pEnumVariant)
  763. {
  764. ULONG c;
  765. VARIANT v;
  766. result = m_pEnumVariant->Next(1, &v, &c);
  767. if (result == S_OK && c == 1)
  768. {
  769. v.pdispVal->AddRef(); // Next should do this but doesn't
  770. item.AttachDispatch(v.pdispVal);
  771. }
  772. }
  773. return (result == S_OK);
  774. }
  775. void CMoIterator::Reset()
  776. {
  777. ASSERT(m_pEnumVariant);
  778. if (m_pEnumVariant)
  779. m_pEnumVariant->Reset();
  780. }
  781. void CMoIterator::Skip(unsigned long index)
  782. {
  783. ASSERT(m_pEnumVariant);
  784. if (m_pEnumVariant)
  785. m_pEnumVariant->Skip(index);
  786. }
  787. CMoIterator::~CMoIterator() 
  788. {
  789. if (m_pEnumVariant)
  790. m_pEnumVariant->Release();
  791. }
  792. IUnknown* CreateCOMObject(const GUID& clsid, IUnknown* pOuter)
  793. {
  794. USES_CONVERSION;
  795. IUnknown* pUnknown = 0;
  796. IClassFactory* pFactory = 0;
  797. HRESULT hr = CoGetClassObject(clsid, CLSCTX_ALL, 0, IID_IClassFactory, (void**)&pFactory);
  798. if (SUCCEEDED(hr))
  799. {
  800. hr = pFactory->CreateInstance(pOuter, IID_IUnknown, (void**)&pUnknown);
  801. pFactory->Release();
  802. }
  803. return pUnknown;
  804. }