Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
14 KiB

  1. // printres.cpp : implementation of the CPrintResObj class
  2. //
  3. // #define PAGESETUP
  4. #include "stdafx.h"
  5. #include "pbrush.h"
  6. #include "pbrusfrm.h"
  7. #include "pbrusvw.h"
  8. #include "pbrusdoc.h"
  9. #include "imgwnd.h"
  10. #include "bmobject.h"
  11. #include "imgsuprt.h"
  12. #include "printres.h"
  13. #include "cmpmsg.h"
  14. #include "imageatt.h"
  15. #include "pgsetup.h"
  16. #ifdef _DEBUG
  17. #undef THIS_FILE
  18. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  19. #endif
  20. IMPLEMENT_DYNAMIC( CPrintResObj, CObject )
  21. #include "memtrace.h"
  22. void MulDivRect(LPRECT r1, LPRECT r2, int num, int div)
  23. {
  24. r1->left = MulDiv(r2->left, num, div);
  25. r1->top = MulDiv(r2->top, num, div);
  26. r1->right = MulDiv(r2->right, num, div);
  27. r1->bottom = MulDiv(r2->bottom, num, div);
  28. }
  29. /***************************************************************************/
  30. // CPrintResObj implementation
  31. CPrintResObj::CPrintResObj( CPBView* pView, CPrintInfo* pInfo )
  32. {
  33. m_pDIB = NULL;
  34. m_pDIBpalette = NULL;
  35. if (pInfo == NULL
  36. || pView == NULL
  37. || pView->m_pImgWnd == NULL
  38. || pView->m_pImgWnd->m_pImg == NULL
  39. || pView->m_pImgWnd->m_pImg->m_pBitmapObj == NULL)
  40. return;
  41. m_pView = pView;
  42. m_iPicWidth = m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_nWidth;
  43. m_iPicHeight = m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_nHeight;
  44. // force the resource to save itself then use the dib to print
  45. BOOL bOldFlag = m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_bDirty;
  46. m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_bDirty = TRUE;
  47. m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->SaveResource( TRUE );
  48. m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_bDirty = bOldFlag;
  49. m_pDIB = GlobalLock(m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_hThing);
  50. if (m_pDIB == NULL)
  51. return;
  52. m_pDIBpalette = CreateDIBPalette( (LPSTR)m_pDIB );
  53. m_pDIBits = FindDIBBits ( (LPSTR)m_pDIB );
  54. // save the scroll value off, then set to 0,0
  55. m_cSizeScroll = m_pView->m_pImgWnd->GetScrollPos();
  56. // save the zoom value off, then set to 100%
  57. m_iZoom = m_pView->m_pImgWnd->GetZoom();
  58. m_rtMargins.SetRectEmpty();
  59. pInfo->m_nNumPreviewPages = 1;
  60. pInfo->m_lpUserData = this;
  61. }
  62. /***************************************************************************/
  63. CPrintResObj::~CPrintResObj()
  64. {
  65. GlobalUnlock(m_pView->m_pImgWnd->m_pImg->m_pBitmapObj->m_hThing);
  66. }
  67. /***************************************************************************/
  68. void CPrintResObj::BeginPrinting( CDC* pDC, CPrintInfo* pInfo )
  69. {
  70. if (pDC == NULL
  71. || pDC->GetSafeHdc() == NULL)
  72. return;
  73. m_pView->m_pImgWnd->SetScroll( 0, 0 );
  74. m_pView->m_pImgWnd->SetZoom ( 1 );
  75. // get device sizes
  76. int nHorzRes = pDC->GetDeviceCaps(HORZRES);
  77. int nVertRes = pDC->GetDeviceCaps(VERTRES);
  78. int nHorzSize = pDC->GetDeviceCaps(HORZSIZE);
  79. int nVertSize = pDC->GetDeviceCaps(VERTSIZE);
  80. int nPhysicalWidth = pDC->GetDeviceCaps(PHYSICALWIDTH);
  81. int nPhysicalHeight = pDC->GetDeviceCaps(PHYSICALHEIGHT);
  82. int nPhysicalOffsetX = pDC->GetDeviceCaps(PHYSICALOFFSETX);
  83. int nPhysicalOffsetY = pDC->GetDeviceCaps(PHYSICALOFFSETY);
  84. // calculate min margins in pixels
  85. double cOutputXPelsPerMeter = (double) nHorzRes * 1000 / nHorzSize;
  86. double cOutputYPelsPerMeter = (double) nVertRes * 1000 / nVertSize;
  87. CRect rcMinMargins;
  88. rcMinMargins.left = nPhysicalOffsetX;
  89. rcMinMargins.top = nPhysicalOffsetY;
  90. rcMinMargins.right = nPhysicalWidth - nHorzRes - nPhysicalOffsetX;
  91. rcMinMargins.bottom = nPhysicalHeight - nVertRes - nPhysicalOffsetY;
  92. m_rtMargins.left = max(0, (LONG) (theApp.m_rectMargins.left * cOutputXPelsPerMeter / 100000) - rcMinMargins.left );
  93. m_rtMargins.top = max(0, (LONG) (theApp.m_rectMargins.top * cOutputYPelsPerMeter / 100000) - rcMinMargins.top );
  94. m_rtMargins.right = max(0, (LONG) (theApp.m_rectMargins.right * cOutputXPelsPerMeter / 100000) - rcMinMargins.right );
  95. m_rtMargins.bottom = max(0, (LONG) (theApp.m_rectMargins.bottom * cOutputYPelsPerMeter / 100000) - rcMinMargins.bottom);
  96. // Quick sanity check
  97. if (m_rtMargins.left + m_rtMargins.right >= nHorzRes)
  98. {
  99. m_rtMargins.left = m_rtMargins.right = 0;
  100. }
  101. if (m_rtMargins.top + m_rtMargins.bottom >= nVertRes)
  102. {
  103. m_rtMargins.top = m_rtMargins.bottom = 0;
  104. }
  105. CPageSetupData PageSetupData;
  106. PageSetupData.bCenterHorizontally = theApp.m_bCenterHorizontally;
  107. PageSetupData.bCenterVertically = theApp.m_bCenterVertically;
  108. PageSetupData.bScaleFitTo = theApp.m_bScaleFitTo;
  109. PageSetupData.nAdjustToPercent = theApp.m_nAdjustToPercent;
  110. PageSetupData.nFitToPagesWide = theApp.m_nFitToPagesWide;
  111. PageSetupData.nFitToPagesTall = theApp.m_nFitToPagesTall;
  112. double cInputXPelsPerMeter = m_pView->m_pImgWnd->m_pImg->cXPelsPerMeter ?
  113. m_pView->m_pImgWnd->m_pImg->cXPelsPerMeter : theApp.ScreenDeviceInfo.ixPelsPerDM * 10;
  114. double cInputYPelsPerMeter = m_pView->m_pImgWnd->m_pImg->cYPelsPerMeter ?
  115. m_pView->m_pImgWnd->m_pImg->cYPelsPerMeter : theApp.ScreenDeviceInfo.iyPelsPerDM * 10;
  116. PageSetupData.fPhysicalImageWidth = (double) m_iPicWidth * cOutputXPelsPerMeter / cInputXPelsPerMeter;
  117. PageSetupData.fPhysicalImageHeight = (double) m_iPicHeight * cOutputYPelsPerMeter / cInputYPelsPerMeter;
  118. m_PhysicalPageSize.cx = pDC->GetDeviceCaps(HORZRES) - m_rtMargins.left - m_rtMargins.right;
  119. m_PhysicalPageSize.cy = pDC->GetDeviceCaps(VERTRES) - m_rtMargins.top - m_rtMargins.bottom;
  120. PageSetupData.CalculateImageRect(m_PhysicalPageSize, m_PhysicalOrigin, m_PhysicalScaledImageSize);
  121. m_nPagesWide = PageSetupData.nFitToPagesWide;
  122. int nPages = PageSetupData.nFitToPagesWide * PageSetupData.nFitToPagesTall;
  123. pInfo->SetMaxPage(nPages);
  124. // If only printing 1 page, should not be in 2 page mode
  125. if (nPages == 1)
  126. {
  127. pInfo->m_nNumPreviewPages = 1;
  128. }
  129. }
  130. /******************************************************************************/
  131. /* We not only move the window origin to allow us to print multiple pages */
  132. /* wide but we also scale both the viewport and window extents to make them */
  133. /* proportional (i.e. a line on the screen is the same size as on */
  134. /* the printer). The pages to print are numbered across. For +---+---+ */
  135. /* example, if there were 4 pages to print, then the first row | 1 | 2 | */
  136. /* would have pages 1,2 and the second row would have pages 3,4. +---+---+ */
  137. /* | 3 | 4 | */
  138. /* +---+---+ */
  139. /* */
  140. /******************************************************************************/
  141. void CPrintResObj::PrepareDC( CDC* pDC, CPrintInfo* pInfo )
  142. {
  143. if (pDC == NULL || pInfo == NULL)
  144. return;
  145. pDC->SetMapMode( MM_TEXT );
  146. pDC->SetStretchBltMode( HALFTONE );
  147. }
  148. /***************************************************************************/
  149. BOOL CPrintResObj::PrintPage( CDC* pDC, CPrintInfo* pInfo )
  150. {
  151. if (m_pDIB == NULL)
  152. return FALSE;
  153. int nPageCol = (pInfo->m_nCurPage - 1) % m_nPagesWide;
  154. int nPageRow = (pInfo->m_nCurPage - 1) / m_nPagesWide;
  155. int nX0 = m_PhysicalOrigin.x - nPageCol * m_PhysicalPageSize.cx;
  156. int nY0 = m_PhysicalOrigin.y - nPageRow * m_PhysicalPageSize.cy;
  157. CRect OutputImageRect;
  158. OutputImageRect.left = max(nX0, 0);
  159. OutputImageRect.top = max(nY0, 0);
  160. OutputImageRect.right = min(nX0 + m_PhysicalScaledImageSize.cx, m_PhysicalPageSize.cx);
  161. OutputImageRect.bottom = min(nY0 + m_PhysicalScaledImageSize.cy, m_PhysicalPageSize.cy);
  162. if (OutputImageRect.right < 0 || OutputImageRect.bottom < 0)
  163. {
  164. return TRUE;
  165. }
  166. CRect InputImageRect;
  167. InputImageRect.left = MulDiv(OutputImageRect.left - nX0, m_iPicWidth, m_PhysicalScaledImageSize.cx);
  168. InputImageRect.top = MulDiv(OutputImageRect.top - nY0, m_iPicHeight, m_PhysicalScaledImageSize.cy);
  169. InputImageRect.right = MulDiv(OutputImageRect.right - nX0, m_iPicWidth, m_PhysicalScaledImageSize.cx);
  170. InputImageRect.bottom = MulDiv(OutputImageRect.bottom - nY0, m_iPicHeight, m_PhysicalScaledImageSize.cy);
  171. if (InputImageRect.right < 0 || InputImageRect.bottom < 0)
  172. {
  173. return TRUE;
  174. }
  175. CPalette* ppalOld = NULL;
  176. if (m_pDIBpalette != NULL)
  177. {
  178. ppalOld = pDC->SelectPalette( m_pDIBpalette, FALSE );
  179. pDC->RealizePalette();
  180. }
  181. int nResult = StretchDIBits(
  182. pDC->m_hDC,
  183. m_rtMargins.left + OutputImageRect.left,
  184. m_rtMargins.top + OutputImageRect.top,
  185. OutputImageRect.Width(),
  186. OutputImageRect.Height(),
  187. InputImageRect.left,
  188. m_iPicHeight - InputImageRect.bottom, // DIB's are upside down
  189. InputImageRect.Width(),
  190. InputImageRect.Height(),
  191. m_pDIBits, (LPBITMAPINFO)m_pDIB,
  192. DIB_RGB_COLORS, SRCCOPY
  193. );
  194. if (nResult == GDI_ERROR)
  195. {
  196. CmpMessageBox( IDS_ERROR_PRINTING, AFX_IDS_APP_TITLE, MB_OK | MB_ICONEXCLAMATION );
  197. }
  198. if (ppalOld != NULL)
  199. {
  200. pDC->SelectPalette( ppalOld, FALSE );
  201. }
  202. return TRUE;
  203. }
  204. /***************************************************************************/
  205. void CPrintResObj::EndPrinting( CDC* pDC, CPrintInfo* pInfo )
  206. {
  207. if (pDC != NULL)
  208. {
  209. m_pView->m_pImgWnd->SetScroll( m_cSizeScroll.cx, m_cSizeScroll.cy );
  210. // restore the zoom value
  211. m_pView->m_pImgWnd->SetZoom( m_iZoom );
  212. }
  213. if (m_pDIBpalette != NULL)
  214. delete m_pDIBpalette;
  215. delete this;
  216. }
  217. /***************************************************************************/
  218. inline int roundleast(int n)
  219. {
  220. int mod = n%10;
  221. n -= mod;
  222. if (mod >= 5)
  223. n += 10;
  224. else if (mod <= -5)
  225. n -= 10;
  226. return n;
  227. }
  228. static void RoundRect(LPRECT r1)
  229. {
  230. r1->left = roundleast(r1->left);
  231. r1->right = roundleast(r1->right);
  232. r1->top = roundleast(r1->top);
  233. r1->bottom = roundleast(r1->bottom);
  234. }
  235. void CPBView::OnFilePageSetup()
  236. {
  237. CPageSetupDialog dlg;
  238. PAGESETUPDLG& psd = dlg.m_psd;
  239. TCHAR szMetric[2];
  240. BOOL bMetric;
  241. LCID lcidThread;
  242. //
  243. // We should use metric if the user has chosen CM in the
  244. // Image Attributes dialog, OR if using Pels and the NLS
  245. // setting is for metric
  246. //
  247. if (theApp.m_iCurrentUnits == ePIXELS)
  248. {
  249. lcidThread = GetThreadLocale();
  250. GetLocaleInfo (lcidThread, LOCALE_IMEASURE, szMetric, 2);
  251. bMetric = (szMetric[0] == TEXT('0'));
  252. }
  253. else
  254. {
  255. bMetric = ((eUNITS)theApp.m_iCurrentUnits == eCM); //centimeters
  256. }
  257. CPageSetupData PageSetupData;
  258. PageSetupData.bCenterHorizontally = theApp.m_bCenterHorizontally;
  259. PageSetupData.bCenterVertically = theApp.m_bCenterVertically;
  260. PageSetupData.bScaleFitTo = theApp.m_bScaleFitTo;
  261. PageSetupData.nAdjustToPercent = theApp.m_nAdjustToPercent;
  262. PageSetupData.nFitToPagesWide = theApp.m_nFitToPagesWide;
  263. PageSetupData.nFitToPagesTall = theApp.m_nFitToPagesTall;
  264. double cXPelsPerMeter = m_pImgWnd->m_pImg->cXPelsPerMeter ?
  265. m_pImgWnd->m_pImg->cXPelsPerMeter : theApp.ScreenDeviceInfo.ixPelsPerDM * 10;
  266. double cYPelsPerMeter = m_pImgWnd->m_pImg->cYPelsPerMeter ?
  267. m_pImgWnd->m_pImg->cYPelsPerMeter : theApp.ScreenDeviceInfo.iyPelsPerDM * 10;
  268. PageSetupData.fPhysicalImageWidth = (double)m_pImgWnd->m_pImg->cxWidth * 100000 / cXPelsPerMeter;
  269. PageSetupData.fPhysicalImageHeight = (double)m_pImgWnd->m_pImg->cyHeight * 100000 / cYPelsPerMeter;
  270. if (!bMetric)
  271. {
  272. PageSetupData.fPhysicalImageWidth /= 2.54;
  273. PageSetupData.fPhysicalImageHeight /= 2.54;
  274. }
  275. psd.Flags |= PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGEPAINTHOOK | PSD_ENABLEPAGESETUPTEMPLATE |
  276. PSD_MARGINS | (bMetric ? PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES);
  277. int nUnitsPerInch = bMetric ? 2540 : 1000;
  278. MulDivRect(&psd.rtMargin, theApp.m_rectMargins, nUnitsPerInch, MARGINS_UNITS);
  279. RoundRect(&psd.rtMargin);
  280. // get the current device from the app
  281. PRINTDLG pd;
  282. pd.hDevNames = NULL;
  283. pd.hDevMode = NULL;
  284. theApp.GetPrinterDeviceDefaults(&pd);
  285. psd.hDevNames = pd.hDevNames;
  286. psd.hDevMode = pd.hDevMode;
  287. psd.hInstance = AfxGetInstanceHandle();
  288. psd.lCustData = (LPARAM) &PageSetupData;
  289. psd.lpfnPagePaintHook = CPageSetupData::PagePaintHook;
  290. psd.lpfnPageSetupHook = CPageSetupData::PageSetupHook;
  291. psd.lpPageSetupTemplateName = MAKEINTRESOURCE(IDD_PAGESETUPDLG);
  292. if (dlg.DoModal() == IDOK)
  293. {
  294. RoundRect(&psd.rtMargin);
  295. MulDivRect(theApp.m_rectMargins, &psd.rtMargin, MARGINS_UNITS, nUnitsPerInch);
  296. //theApp.m_rectPageMargin = m_rectMargin;
  297. theApp.SelectPrinter(psd.hDevNames, psd.hDevMode);
  298. theApp.m_bCenterHorizontally = PageSetupData.bCenterHorizontally;
  299. theApp.m_bCenterVertically = PageSetupData.bCenterVertically;
  300. theApp.m_bScaleFitTo = PageSetupData.bScaleFitTo;
  301. theApp.m_nAdjustToPercent = PageSetupData.nAdjustToPercent;
  302. theApp.m_nFitToPagesWide = PageSetupData.nFitToPagesWide;
  303. theApp.m_nFitToPagesTall = PageSetupData.nFitToPagesTall;
  304. }
  305. // PageSetupDlg failed
  306. // if (CommDlgExtendedError() != 0)
  307. // {
  308. //
  309. // nothing to handle this failure
  310. //
  311. // }
  312. }