/*+/csubr/TOC---------------------------------------------------------------- * PlPrtClose - close a print job for a Windows printer * * Purpose: * Closes a print job for a Windows printer. "end page" and "end * document" commands are sent to the printer. * * After closing the print job, this routine wraps up operations * for the PL_CTX for the printout. * * Return Value: * PL_OK, or * PL_PRT_CANCEL if bAbort is 1 or if PlPrtStatusWindow has been * called and the operator clicks Cancel, or * other codes for other errors * * Notes: * 1. If bAbort is 1 (or if pPlot->bPrintCancel is 1), then the printout * is aborted, so that nothing is sent to the printer. * 2. This routine automatically calls PlotWrapup. * * See Also: * PlPrtOpenDefault, PlPrtOpenDialog, PlPrtStatusWindow * *-Date Author Revision * -------- ------------ -------- * 06-08-95 R. Cole created *--------------------------------------------------------------------------*/ int PASCAL PlPrtClose( PL_CTX *pPlot, // IO pointer to plot context struct for printing int bAbort) // I 1 to abort the printout { int retStat=PL_OK; int stat; PRINTDLG *pPd=NULL; if (pPlot->hDC != 0) { if (bAbort || pPlot->bPrintCancel) stat = AbortDoc(pPlot->hDC); else { stat = EndPage(pPlot->hDC); stat = EndDoc(pPlot->hDC); } } if (pPlot->pPd != NULL) { pPd = (PRINTDLG *)pPlot->pPd; if (pPd->hDevMode != 0) GlobalFree(pPd->hDevMode); if (pPd->hDevNames != 0) GlobalFree(pPd->hDevNames); GlobalUnlock(pPlot->hPD); } if (pPlot->hPD != 0) GlobalFree(pPlot->hPD); if (pPlot->hDC != 0) DeleteDC(pPlot->hDC); pPlot->hDC = 0; pPlot->hPD = 0; pPlot->pPd = NULL; retStat = PlPlotWrapup(pPlot); strcpy(pPlot->szPrintOpen, "cls"); return retStat; }
void endDoc(int hdc) { //rMessageBox(NULL, MB_APPLMODAL, "in endDoc", ""); if (bUserAbort) AbortDoc((HDC) hdc); else EndDoc((HDC) hdc); }
/* false=error, true=ok */ bool kGUIPrintJobMINGW::End(void) { if(m_error==true) /* some error occured previously, abort */ AbortDoc (m_printerHDC); else EndDoc (m_printerHDC); return(!m_error); }
Bool apc_prn_abort_doc( Handle self) { objCheck false; if ( AbortDoc( sys ps) < 0) apiPrnErr; hwnd_leave_paint( self); if ( sys pal) DeleteObject( sys pal); DeleteDC( sys ps); sys pal = nil; sys ps = nil; return apcError == errOk; }
VOID GdiSAPCallback(PLDC pldc) { DWORD Time, NewTime = GetTickCount(); Time = NewTime - pldc->CallBackTick; if ( Time < SAPCALLBACKDELAY) return; pldc->CallBackTick = NewTime; if ( !pldc->pAbortProc(pldc->hDC, 0) ) { CancelDC(pldc->hDC); AbortDoc(pldc->hDC); } }
/* Close the win_pr2 driver */ static int win_pr2_close(gx_device * dev) { int code; int aborted = FALSE; win_pr2_copy_check(wdev); /* Free resources */ if (!wdev->nocancel) { if (!wdev->hDlgModeless) aborted = TRUE; else DestroyWindow(wdev->hDlgModeless); wdev->hDlgModeless = 0; } if (aborted) AbortDoc(wdev->hdcprn); else EndDoc(wdev->hdcprn); DeleteDC(wdev->hdcprn); if (wdev->win32_hdevmode != NULL) { GlobalFree(wdev->win32_hdevmode); wdev->win32_hdevmode = NULL; } if (wdev->win32_hdevnames != NULL) { GlobalFree(wdev->win32_hdevnames); wdev->win32_hdevnames = NULL; } code = gdev_prn_close(dev); /* delete unwanted temporary file */ if (wdev->fname[0]) unlink(wdev->fname); return code; }
static int winprint_finish (struct winprint_data *wd, Tcl_Interp *interp, PRINTDLG *pd, int error) { int ret; ret = TCL_OK; if (error || wd->aborted) AbortDoc (pd->hDC); else { if (EndDoc (pd->hDC) <= 0) { windows_error (interp, "EndDoc"); ret = TCL_ERROR; } } DeleteDC (pd->hDC); return ret; }
/************************************************************************ * Escape [GDI32.@] */ INT WINAPI Escape( HDC hdc, INT escape, INT in_count, LPCSTR in_data, LPVOID out_data ) { INT ret; POINT *pt; switch (escape) { case ABORTDOC: return AbortDoc( hdc ); case ENDDOC: return EndDoc( hdc ); case GETPHYSPAGESIZE: pt = out_data; pt->x = GetDeviceCaps( hdc, PHYSICALWIDTH ); pt->y = GetDeviceCaps( hdc, PHYSICALHEIGHT ); return 1; case GETPRINTINGOFFSET: pt = out_data; pt->x = GetDeviceCaps( hdc, PHYSICALOFFSETX ); pt->y = GetDeviceCaps( hdc, PHYSICALOFFSETY ); return 1; case GETSCALINGFACTOR: pt = out_data; pt->x = GetDeviceCaps( hdc, SCALINGFACTORX ); pt->y = GetDeviceCaps( hdc, SCALINGFACTORY ); return 1; case NEWFRAME: return EndPage( hdc ); case SETABORTPROC: return SetAbortProc( hdc, (ABORTPROC)in_data ); case STARTDOC: { DOCINFOA doc; char *name = NULL; /* in_data may not be 0 terminated so we must copy it */ if (in_data) { name = HeapAlloc( GetProcessHeap(), 0, in_count+1 ); memcpy( name, in_data, in_count ); name[in_count] = 0; } /* out_data is actually a pointer to the DocInfo structure and used as * a second input parameter */ if (out_data) doc = *(DOCINFOA *)out_data; else { doc.cbSize = sizeof(doc); doc.lpszOutput = NULL; doc.lpszDatatype = NULL; doc.fwType = 0; } doc.lpszDocName = name; ret = StartDocA( hdc, &doc ); HeapFree( GetProcessHeap(), 0, name ); if (ret > 0) ret = StartPage( hdc ); return ret; } case QUERYESCSUPPORT: { const INT *ptr = (const INT *)in_data; if (in_count < sizeof(INT)) return 0; switch(*ptr) { case ABORTDOC: case ENDDOC: case GETPHYSPAGESIZE: case GETPRINTINGOFFSET: case GETSCALINGFACTOR: case NEWFRAME: case QUERYESCSUPPORT: case SETABORTPROC: case STARTDOC: return TRUE; } break; } } /* if not handled internally, pass it to the driver */ return ExtEscape( hdc, escape, in_count, in_data, 0, out_data ); }
int Print(HWND win) { BOOL rv = TRUE; int start, end; PRINTDLG pd; HWND hDlgCancel = 0; memset(&pd, 0, sizeof(pd)); pd.lStructSize = sizeof(pd); pd.hwndOwner = hwndFrame; pd.Flags = PD_NOPAGENUMS | PD_RETURNDC | PD_COLLATE ; pd.hInstance = hInstance; SendDlgItemMessage(win, ID_EDITCHILD, EM_GETSEL, (WPARAM) &start, (LPARAM) &end); tabSetting = PropGetInt(NULL, "TAB_INDENT"); leftmargin = PropGetInt(NULL, "PRINTER_LEFT"); rightmargin = PropGetInt(NULL, "PRINTER_RIGHT"); topmargin = PropGetInt(NULL, "PRINTER_TOP"); bottommargin = PropGetInt(NULL, "PRINTER_BOTTOM"); PropGetString(NULL, "PRINTER_HEADER", printHeader, sizeof(printHeader)); PropGetString(NULL, "PRINTER_FOOTER", printFooter, sizeof(printFooter)); if (tabSetting <= 0) tabSetting = 4; if (end != start) pd.Flags |= PD_SELECTION; if (PrintDlg(&pd)) { DOCINFO di; HWND child; char *buf, *pos, *savepos1; if (pd.Flags &PD_SELECTION) { if (end <= start) return TRUE ; } child = GetDlgItem(win, ID_EDITCHILD); buf = GetEditData(child); if (!buf) return TRUE ; if (pd.Flags &PD_SELECTION) { savepos1 = pos = buf + start; buf[end] = 0; } else savepos1 = pos = buf; printing = TRUE; memset(&di, 0, sizeof(di)); di.cbSize = sizeof(di); di.lpszDocName = (char*)SendMessage(win, WM_FILETITLE, 0, 0); if (pd.Flags &PD_PRINTTOFILE) di.lpszOutput = "FILE:"; SetAbortProc(pd.hDC, &AbortProc); if (StartDoc(pd.hDC, &di) > 0) { int pelsx, pelsy; int width, height, rows, cols; int done = FALSE; char headerLeft[256],headerRight[256],headerCenter[256]; char FooterLeft[256],FooterRight[256],FooterCenter[256]; SIZE strsize ; HFONT hFont, oldhFont; pelsx = GetDeviceCaps(pd.hDC, LOGPIXELSX); pelsy = GetDeviceCaps(pd.hDC, LOGPIXELSY); fontdata.lfHeight = - MulDiv(11, pelsx, 72); hFont = CreateFontIndirect(&fontdata); oldhFont = SelectObject(pd.hDC, hFont); GetTextExtentPoint32(pd.hDC, "A", 1, &strsize); width = GetDeviceCaps(pd.hDC, HORZRES); height = GetDeviceCaps(pd.hDC, VERTRES); // buf = GetEditData(win); rows = (height - (topmargin + bottommargin) *pelsy * 10 / 254) / strsize.cy ; cols = (width - (leftmargin + rightmargin) *pelsx * 10 / 254) / strsize.cx; if (rows <= 0 || cols <= 0) { AbortDoc(pd.hDC); free(buf); DeleteObject(hFont); if (pd.hDC != NULL) DeleteDC(pd.hDC); if (pd.hDevMode != NULL) GlobalFree(pd.hDevMode); if (pd.hDevNames != NULL) GlobalFree(pd.hDevNames); return FALSE; } SelectObject(pd.hDC, oldhFont); if (printHeader[0]) rows -= 2; if (printFooter[0]) rows -= 2; total_pages = countPages(savepos1, rows, cols); setTimeFormats(); split(printHeader, headerLeft, headerRight, headerCenter); split(printFooter, FooterLeft, FooterRight, FooterCenter); hDlgCancel = CreateDialog(hInstance, "PRINTABORTDLG", 0, (DLGPROC) CancelProc); EnableWindow(hwndFrame, FALSE); do { int colcount = pd.nCopies; int pagenum = 1; pos = savepos1; while (printing && *pos && StartPage(pd.hDC) > 0) { int i, j, k; int hdrlines = 0; char line[512]; char *savepos2 = pos; oldhFont = SelectObject(pd.hDC, hFont); if (printHeader[0]) { char buf[256]; int cx ; int cy = topmargin * pelsy * 10/ 254; cx = subs(pd.hDC, buf, headerLeft, di.lpszDocName, pagenum); cx = leftmargin * pelsx * 10 / 254; TextOut(pd.hDC, cx, cy, buf, strlen(buf)); cx = subs(pd.hDC, buf, headerCenter, di.lpszDocName, pagenum); cx = (width - cx)/2 ; TextOut(pd.hDC, cx, cy, buf, strlen(buf)); cx = subs(pd.hDC, buf, headerRight, di.lpszDocName, pagenum); cx = width - cx - rightmargin * pelsx * 10 / 254; TextOut(pd.hDC, cx, cy, buf, strlen(buf)); hdrlines = 2; } for (i = 0; i < rows; i++) { int count = 0; if (*pos == '\n') { pos++; } else if (*pos == '\f') { pos += 2; break; } else { for (j = 0; j < cols; j++) { if (*pos == '\t') { int n = tabSetting - j % tabSetting; pos++; for (k = 0; k < n; k++) line[count++] = ' '; j += n - 1; } else { if (*pos < 32 || *pos > 126) { if (*pos == '\n') pos++; break; } line[count++] = *pos++; } } TextOut(pd.hDC, leftmargin *pelsx * 10 / 254, (i + hdrlines) *strsize.cy + topmargin * pelsy * 10 / 254, line, count); } if (! *pos) break; } if (printFooter[0]) { char buf[256]; int cx ; int cy = height - strsize.cy - bottommargin * pelsy * 10 / 254; cx = subs(pd.hDC, buf, FooterLeft, di.lpszDocName, pagenum); cx = leftmargin * pelsx * 10 / 254; TextOut(pd.hDC, cx, cy, buf, strlen(buf)); cx = subs(pd.hDC, buf, FooterCenter, di.lpszDocName, pagenum); cx = (width - cx) / 2; TextOut(pd.hDC, cx, cy, buf, strlen(buf)); cx = subs(pd.hDC, buf, FooterRight, di.lpszDocName, pagenum); cx = width - cx - rightmargin * pelsx * 10 / 254; TextOut(pd.hDC, cx, cy, buf, strlen(buf)); } SelectObject(pd.hDC, oldhFont); if (printing) if (EndPage(pd.hDC) <= 0) goto doneprinting; if (!(pd.Flags &PD_COLLATE)) { if (--colcount) { pos = savepos2; } else { colcount = pd.nCopies; pagenum++; } } else { pagenum++; } } } while (printing && (pd.Flags &PD_COLLATE) && --pd.nCopies) ; if (!printing) AbortDoc(pd.hDC); doneprinting: if (printing) EndDoc(pd.hDC); EnableWindow(hwndFrame, TRUE); if (hDlgCancel) DestroyWindow(hDlgCancel); DeleteObject(hFont); } FreeEditData(buf); } if (pd.hDC != NULL) DeleteDC(pd.hDC); if (pd.hDevMode != NULL) GlobalFree(pd.hDevMode); if (pd.hDevNames != NULL) GlobalFree(pd.hDevNames); return rv; }
void CPrinterDC::Abort(void) { ASSERT(m_hDC); AbortDoc(m_hDC); }
/****************************************************************************** * AbortDoc [GDI.382] */ INT16 WINAPI AbortDoc16(HDC16 hdc) { return AbortDoc(hdc); }
static void PrintPiecesThread(void* pv) { CFrameWndEx* pFrame = (CFrameWndEx*)pv; CView* pView = pFrame->GetActiveView(); CPrintDialog PD(FALSE, PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOPAGENUMS|PD_NOSELECTION, pFrame); if (theApp.DoPrintDialog(&PD) != IDOK) return; if (PD.m_pd.hDC == NULL) return; Project* project = lcGetActiveProject(); ObjArray<lcPiecesUsedEntry> PiecesUsed; project->GetPiecesUsed(PiecesUsed); PiecesUsed.Sort(PiecesUsedSortFunc, NULL); // gather file to print to if print-to-file selected CString strOutput; if (PD.m_pd.Flags & PD_PRINTTOFILE) { CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT)); CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT)); CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER)); CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION)); CFileDialog dlg(FALSE, strDef, strPrintDef,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter); dlg.m_ofn.lpstrTitle = strCaption; if (dlg.DoModal() != IDOK) return; strOutput = dlg.GetPathName(); } CString DocName; char* Ext = strrchr(project->m_strTitle, '.'); DocName.Format("LeoCAD - %.*s BOM", Ext ? Ext - project->m_strTitle : strlen(project->m_strTitle), project->m_strTitle); DOCINFO docInfo; memset(&docInfo, 0, sizeof(DOCINFO)); docInfo.cbSize = sizeof(DOCINFO); docInfo.lpszDocName = DocName; CString strPortName; int nFormatID; if (strOutput.IsEmpty()) { docInfo.lpszOutput = NULL; strPortName = PD.GetPortName(); nFormatID = AFX_IDS_PRINTONPORT; } else { docInfo.lpszOutput = strOutput; AfxGetFileTitle(strOutput, strPortName.GetBuffer(_MAX_PATH), _MAX_PATH); nFormatID = AFX_IDS_PRINTTOFILE; } SetAbortProc(PD.m_pd.hDC, _AfxAbortProc); pFrame->EnableWindow(FALSE); CPrintingDialog dlgPrintStatus(NULL); CString strTemp; dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, DocName); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME, PD.GetDeviceName()); AfxFormatString1(strTemp, nFormatID, strPortName); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp); dlgPrintStatus.ShowWindow(SW_SHOW); dlgPrintStatus.UpdateWindow(); if (StartDoc(PD.m_pd.hDC, &docInfo) == SP_ERROR) { pFrame->EnableWindow(TRUE); dlgPrintStatus.DestroyWindow(); AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT); return; } int ResX = GetDeviceCaps(PD.m_pd.hDC, LOGPIXELSX); int ResY = GetDeviceCaps(PD.m_pd.hDC, LOGPIXELSY); CRect RectDraw(0, 0, GetDeviceCaps(PD.m_pd.hDC, HORZRES), GetDeviceCaps(PD.m_pd.hDC, VERTRES)); DPtoLP(PD.m_pd.hDC, (LPPOINT)(RECT*)&RectDraw, 2); RectDraw.DeflateRect((int)(ResX*(float)theApp.GetProfileInt("Default","Margin Left", 50)/100.0f), (int)(ResY*(float)theApp.GetProfileInt("Default","Margin Top", 50)/100.0f), (int)(ResX*(float)theApp.GetProfileInt("Default","Margin Right", 50)/100.0f), (int)(ResY*(float)theApp.GetProfileInt("Default","Margin Bottom", 50)/100.0f)); CRect HeaderRect = RectDraw; HeaderRect.top -= (int)(ResY*theApp.GetProfileInt("Default", "Margin Top", 50) / 200.0f); HeaderRect.bottom += (int)(ResY*theApp.GetProfileInt("Default", "Margin Bottom", 50) / 200.0f); int RowsPerPage = AfxGetApp()->GetProfileInt("Default", "Catalog Rows", 10); int ColsPerPage = AfxGetApp()->GetProfileInt("Default", "Catalog Columns", 3); int PicHeight = RectDraw.Height() / RowsPerPage; int PicWidth = RectDraw.Width() / ColsPerPage; int TotalRows = (PiecesUsed.GetSize() + ColsPerPage - 1) / ColsPerPage; int TotalPages = (TotalRows + RowsPerPage - 1) / RowsPerPage; int RowHeight = RectDraw.Height() / RowsPerPage; int ColWidth = RectDraw.Width() / ColsPerPage; PD.m_pd.nMinPage = 1; PD.m_pd.nMaxPage = TotalPages + 1; UINT EndPage = PD.m_pd.nToPage; UINT StartPage = PD.m_pd.nFromPage; if (PD.PrintAll()) { EndPage = PD.m_pd.nMaxPage; StartPage = PD.m_pd.nMinPage; } lcClamp(EndPage, PD.m_pd.nMinPage, PD.m_pd.nMaxPage); lcClamp(StartPage, PD.m_pd.nMinPage, PD.m_pd.nMaxPage); int StepPage = (EndPage >= StartPage) ? 1 : -1; VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM)); // begin page printing loop BOOL bError = FALSE; // Creating Compatible Memory Device Context CDC *pMemDC = new CDC; if (!pMemDC->CreateCompatibleDC(pView->GetDC())) return; BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = PicWidth; bi.bmiHeader.biHeight = PicHeight; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = PicWidth * PicHeight * 3; bi.bmiHeader.biXPelsPerMeter = 2925; bi.bmiHeader.biYPelsPerMeter = 2925; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; LPBITMAPINFOHEADER lpbi[1]; HBITMAP hBm, hBmOld; hBm = CreateDIBSection(pView->GetDC()->GetSafeHdc(), &bi, DIB_RGB_COLORS, (void **)&lpbi, NULL, (DWORD)0); if (!hBm) return; hBmOld = (HBITMAP)::SelectObject(pMemDC->GetSafeHdc(), hBm); PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int pixelformat = ChoosePixelFormat(pMemDC->m_hDC, &pfd); DescribePixelFormat(pMemDC->m_hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); SetPixelFormat(pMemDC->m_hDC, pixelformat, &pfd); HGLRC hmemrc = wglCreateContext(pMemDC->GetSafeHdc()); wglMakeCurrent(pMemDC->GetSafeHdc(), hmemrc); GL_DisableVertexBufferObject(); float Aspect = (float)PicWidth/(float)PicHeight; glViewport(0, 0, PicWidth, PicHeight); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(0.5f, 0.1f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(1, 1, 1, 1); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); lf.lfHeight = -MulDiv(12, ResY, 72); lf.lfWeight = FW_REGULAR; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = PROOF_QUALITY; strcpy (lf.lfFaceName , "Arial"); HFONT HeaderFont = CreateFontIndirect(&lf); HFONT OldFont = (HFONT)SelectObject(PD.m_pd.hDC, HeaderFont); SetBkMode(PD.m_pd.hDC, TRANSPARENT); SetTextColor(PD.m_pd.hDC, 0x000000); SetTextAlign(PD.m_pd.hDC, TA_CENTER|TA_NOUPDATECP); DWORD PrintOptions = AfxGetApp()->GetProfileInt("Settings", "Print", PRINT_NUMBERS | PRINT_BORDER/*|PRINT_NAMES*/); bool DrawNames = 1;//(PrintOptions & PRINT_NAMES) != 0; bool Horizontal = 1;//(PrintOptions & PRINT_HORIZONTAL) != 0; pMemDC->SetTextColor(0x000000); pMemDC->SetBkMode(TRANSPARENT); // lf.lfHeight = -MulDiv(40, GetDeviceCaps(pMemDC->m_hDC, LOGPIXELSY), 72); // lf.lfWeight = FW_BOLD; HFONT CatalogFont = CreateFontIndirect(&lf); lf.lfHeight = -MulDiv(80, GetDeviceCaps(pMemDC->m_hDC, LOGPIXELSY), 72); HFONT CountFont = CreateFontIndirect(&lf); HFONT OldMemFont = (HFONT)SelectObject(pMemDC->m_hDC, CatalogFont); HPEN hpOld = (HPEN)SelectObject(pMemDC->m_hDC, GetStockObject(BLACK_PEN)); for (UINT CurPage = StartPage; CurPage != EndPage; CurPage += StepPage) { TCHAR szBuf[80]; wsprintf(szBuf, strTemp, CurPage); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf); if (::StartPage(PD.m_pd.hDC) < 0) { bError = TRUE; break; } // Draw header and footer. SelectObject(PD.m_pd.hDC, HeaderFont); CString Header; UINT Align; FormatHeader(Header, Align, AfxGetApp()->GetProfileString("Default", "Catalog Header", ""), project->m_strTitle, project->m_strAuthor, project->m_strDescription, CurPage, TotalPages); Align |= DT_TOP|DT_SINGLELINE; DrawText(PD.m_pd.hDC, (LPCTSTR)Header, Header.GetLength(), HeaderRect, Align); FormatHeader(Header, Align, AfxGetApp()->GetProfileString("Default", "Catalog Footer", "Page &P"), project->m_strTitle, project->m_strAuthor, project->m_strDescription, CurPage, TotalPages); Align |= DT_BOTTOM|DT_SINGLELINE; DrawText(PD.m_pd.hDC, (LPCTSTR)Header, Header.GetLength(), HeaderRect, Align); int StartPiece = (CurPage - 1) * RowsPerPage * ColsPerPage; int EndPiece = lcMin(StartPiece + RowsPerPage * ColsPerPage, PiecesUsed.GetSize()); for (int CurPiece = StartPiece; CurPiece < EndPiece; CurPiece++) { FillRect(pMemDC->m_hDC, CRect(0, PicHeight, PicWidth, 0), (HBRUSH)GetStockObject(WHITE_BRUSH)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); PieceInfo* pInfo = PiecesUsed[CurPiece].Info; pInfo->ZoomExtents(30.0f, Aspect); pInfo->RenderPiece(PiecesUsed[CurPiece].ColorIndex); glFinish(); // Draw description text at the bottom. CRect TextRect(0, 0, PicWidth, PicHeight); if (DrawNames) { SelectObject(pMemDC->m_hDC, CatalogFont); pMemDC->DrawText(pInfo->m_strDescription, strlen(pInfo->m_strDescription), TextRect, DT_CALCRECT | DT_WORDBREAK); TextRect.OffsetRect(0, PicHeight - TextRect.Height() - 5); pMemDC->DrawText(pInfo->m_strDescription, strlen(pInfo->m_strDescription), TextRect, DT_WORDBREAK); } // Draw count. SelectObject(pMemDC->m_hDC, CountFont); TextRect = CRect(0, 0, PicWidth, TextRect.top); TextRect.DeflateRect(5, 5); char CountStr[16]; sprintf(CountStr, "%dx", PiecesUsed[CurPiece].Count); pMemDC->DrawText(CountStr, strlen(CountStr), TextRect, DT_BOTTOM | DT_LEFT | DT_SINGLELINE); LPBITMAPINFOHEADER lpbi[1]; lpbi[0] = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hBm, 24)); BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); memcpy (&bi.bmiHeader, lpbi[0], sizeof(BITMAPINFOHEADER)); SetStretchBltMode(PD.m_pd.hDC, COLORONCOLOR); int CurRow, CurCol; if (Horizontal) { CurRow = (CurPiece - StartPiece) / ColsPerPage; CurCol = (CurPiece - StartPiece) % ColsPerPage; } else { CurRow = (CurPiece - StartPiece) % RowsPerPage; CurCol = (CurPiece - StartPiece) / RowsPerPage; } int Left = RectDraw.left + ColWidth * CurCol + (ColWidth - PicWidth) / 2; int Top = RectDraw.top + RowHeight * CurRow + (RowHeight - PicHeight) / 2; StretchDIBits(PD.m_pd.hDC, Left, Top, PicWidth, PicHeight, 0, 0, PicWidth, PicHeight, (LPBYTE)lpbi[0] + lpbi[0]->biSize + lpbi[0]->biClrUsed * sizeof(RGBQUAD), &bi, DIB_RGB_COLORS, SRCCOPY); if (lpbi[0]) GlobalFreePtr(lpbi[0]); } if (::EndPage(PD.m_pd.hDC) < 0 || !_AfxAbortProc(PD.m_pd.hDC, 0)) { bError = TRUE; break; } } SelectObject(pMemDC->m_hDC, hpOld); SelectObject(PD.m_pd.hDC, OldFont); DeleteObject(HeaderFont); SelectObject(pMemDC->m_hDC, OldMemFont); DeleteObject(CatalogFont); DeleteObject(CountFont); GL_EnableVertexBufferObject(); wglMakeCurrent(NULL, NULL); wglDeleteContext(hmemrc); SelectObject(pMemDC->GetSafeHdc(), hBmOld); DeleteObject(hBm); delete pMemDC; if (!bError) EndDoc(PD.m_pd.hDC); else AbortDoc(PD.m_pd.hDC); pFrame->EnableWindow(); dlgPrintStatus.DestroyWindow(); if (PD.m_pd.hDC != NULL) { ::DeleteDC(PD.m_pd.hDC); PD.m_pd.hDC = NULL; } }
/*++ ******************************************************************* P r i n t T e x t J o b Routine Description: Prints a text data job. Arguments: pData => Data structure for this job pDocumentName => Name of this document Return Value: TRUE if successful FALSE if failed - GetLastError() will return reason. ******************************************************************* --*/ BOOL PrintTextJob( IN PPRINTPROCESSORDATA pData, __in IN LPWSTR pDocumentName) { DOCINFO DocInfo; LOGFONT LogFont; CHARSETINFO CharSetInfo; HFONT hOldFont, hFont = NULL; DWORD Copies; BOOL rc; DWORD NoRead; DWORD CurrentLine; DWORD CurrentCol; HANDLE hPrinter = NULL; BYTE *ReadBufferStart = NULL; PBYTE pLineBuffer = NULL; PBYTE pReadBuffer = NULL; PBYTE pReadBufferEnd = NULL; ULONG CharHeight, CharWidth, CharsPerLine, LinesPerPage; ULONG PageWidth, PageHeight; ULONG Length, TabBase; BOOL ReadAll; TEXTMETRIC tm; DWORD fdwFlags; DWORD Encoding; DWORD SplitSize; BOOL ReturnValue = FALSE; BOOL bAbortDoc = FALSE; DWORD dwNeeded; DWORD dwNoTranslate = 0; DWORD dwNoTranslateCR = 0; DWORD dwTransparent = 0; INT iBkMode = OPAQUE; DocInfo.lpszDocName = pData->pDocument; /* Document name */ DocInfo.lpszOutput = NULL; /* Output file */ DocInfo.lpszDatatype = NULL; /* Datatype */ DocInfo.cbSize = sizeof(DOCINFO); /* Size of the structure */ // // Go figure out the size of the form on the printer. We do this // by calling GetTextMetrics, which gives us the font size of the // printer font, then getting the form size and calculating the // number of characters that will fit. In other cases we treat it as ANSI text. // Currently the codepage context is fixed to the system default codepage. // Encoding = GetACP(); // // Create FIXED PITCH font and select // hOldFont = 0; ZeroMemory(&CharSetInfo, sizeof(CHARSETINFO)); if (TranslateCharsetInfo((PDWORD)UIntToPtr(Encoding), &CharSetInfo, TCI_SRCCODEPAGE)) { ZeroMemory(&LogFont, sizeof(LOGFONT)); LogFont.lfWeight = 400; LogFont.lfCharSet = (BYTE)CharSetInfo.ciCharset; LogFont.lfPitchAndFamily = FIXED_PITCH; hFont = CreateFontIndirect(&LogFont); hOldFont = (HFONT) SelectObject(pData->hDC, hFont); } if (!GetTextMetrics(pData->hDC, &tm)) { // Essential text processing computation failed goto Done; } CharHeight = tm.tmHeight + tm.tmExternalLeading; CharWidth = tm.tmAveCharWidth; if (!CharWidth || !CharHeight) { // Essential text processing computation failed goto Done; } // // Calculate most fittable characters' number to one line. // PageWidth = GetDeviceCaps(pData->hDC, DESKTOPHORZRES); PageHeight = GetDeviceCaps(pData->hDC, DESKTOPVERTRES); CharsPerLine = PageWidth / CharWidth; LinesPerPage = PageHeight / CharHeight; if (!CharsPerLine || !LinesPerPage) { // Essential text processing computation failed goto Done; } /** Allocate a buffer for one line of text **/ pLineBuffer = (PBYTE)AllocSplMem(CharsPerLine + 5); if (!pLineBuffer) { goto Done; } /** Let the printer know we are starting a new document **/ if (!StartDoc(pData->hDC, (LPDOCINFO)&DocInfo)) { goto Done; } ReadBufferStart = (BYTE *)AllocSplMem(READ_BUFFER_SIZE); if (!ReadBufferStart) { goto Done; } /** Print the data pData->Copies times **/ Copies = pData->Copies; while (Copies--) { /** Loop, getting data and sending it to the printer. This also takes care of pausing and cancelling print jobs by checking the processor's status flags while printing. The way we do this is to read in some data from the printer. We will then pull data, one tabbed line at a time from there and print it. If the last bit of data in the buffer does not make up a whole line, we call GetTabbedLineFromBuffer() with a non- zero Length, which indicates that there are chars left from the previous read. **/ TabBase = 0; Length = 0; fdwFlags = FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF; CurrentLine = 0; CurrentCol = 0; /** Open the printer. If it fails, return. This also sets up the pointer for the ReadPrinter calls. **/ if (!OpenPrinter(pDocumentName, &hPrinter, NULL)) { hPrinter = NULL; bAbortDoc = TRUE; goto Done; } // // Call GetPrinterData to see if the queue wants no LF/CR processing. // if( GetPrinterData( hPrinter, (LPWSTR)gszNoTranslateCRLF, NULL, (PBYTE)&dwNoTranslate, sizeof( dwNoTranslate ), &dwNeeded ) == ERROR_SUCCESS ){ if( dwNoTranslate ){ fdwFlags &= ~( FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF ); } } // // Call GetPrinterData to see if the queue wants no CR processing. // if( GetPrinterData( hPrinter, (LPWSTR)gszNoTranslateCR, NULL, (PBYTE)&dwNoTranslateCR, sizeof( dwNoTranslateCR ), &dwNeeded ) == ERROR_SUCCESS ){ if( dwNoTranslateCR ){ fdwFlags &= ~FLAG_TRANSLATE_CR; if( GetPrinterData( hPrinter, (LPWSTR)gszTransparency, NULL, (PBYTE)&dwTransparent, sizeof( dwTransparent ), &dwNeeded ) == ERROR_SUCCESS ){ if( dwTransparent ){ iBkMode = SetBkMode( pData->hDC, TRANSPARENT ); } } } } if (StartPage(pData->hDC) == SP_ERROR) { bAbortDoc = TRUE; goto Done; } /** ReadAll indicates if we are on the last line of the file **/ ReadAll = FALSE; /** This next do loop continues until we have read all of the data for the print job. **/ do { if (fdwFlags & FLAG_DBCS_SPLIT) { SplitSize = (DWORD)(pReadBufferEnd - pReadBuffer); memcpy(ReadBufferStart, pReadBuffer, SplitSize); fdwFlags &= ~FLAG_DBCS_SPLIT; } else { SplitSize = 0; } rc = ReadPrinter(hPrinter, (ReadBufferStart + SplitSize), (READ_BUFFER_SIZE - SplitSize), &NoRead); if (!rc || !NoRead) { ReadAll = TRUE; } else { /** Pick up a pointer to the end of the data **/ pReadBuffer = ReadBufferStart; pReadBufferEnd = ReadBufferStart + SplitSize + NoRead; } /** This loop will process all the data that we have just read from the printer. **/ do { if (!ReadAll) { /** Length on entry holds the length of any residual chars from the last line that we couldn't print out because we ran out of characters on the ReadPrinter buffer. **/ pReadBuffer = GetTabbedLineFromBuffer( pReadBuffer, pReadBufferEnd, pLineBuffer, CharsPerLine - CurrentCol, pData->TabSize, Encoding, &Length, &TabBase, &fdwFlags ); /** If pReadBuffer == NULL, then we have exhausted the read buffer and we need to ReadPrinter again and save the last line chars. Length holds the number of characters on this partial line, so the next time we call ReadPrinter we will pickup where we left off. The only time we'll get residual chars is if: 1. The last line ends w/o ff/lf/cr ("Hello\EOF") In this case we should TextOutA the last line and then quit. (In this case, don't break here; go ahead and print, then we'll break out below in the do..while.) 2. The ReadPrinter last byte is in the middle of a line. Here we should read the next chunk and add the new characters at the end of the chars we just read. (In this case, we should break and leave Length as it is so we will read again and append to the buffer, beginning at Length.) **/ if (!pReadBuffer || (fdwFlags & FLAG_DBCS_SPLIT)) break; } /** If the print processor is paused, wait for it to be resumed **/ if (pData->fsStatus & PRINTPROCESSOR_PAUSED) { WaitForSingleObject(pData->semPaused, INFINITE); } /** If the job has been aborted, clean up and leave **/ if (pData->fsStatus & PRINTPROCESSOR_ABORTED) { ReturnValue = TRUE; bAbortDoc = TRUE; goto Done; } /** Write the data to the printer **/ /** Make sure Length is not zero **/ /** TextOut will fail if Length == 0 **/ if (Length) { /** We may have a number of newlines pending, that may push us to the next page (or even next-next page). **/ while (CurrentLine >= LinesPerPage) { /** We need a new page; always defer this to the last second to prevent extra pages from coming out. **/ if (EndPage(pData->hDC) == SP_ERROR || StartPage(pData->hDC) == SP_ERROR) { bAbortDoc = TRUE; goto Done; } CurrentLine -= LinesPerPage; } #pragma prefast(suppress:__WARNING_ANSI_APICALL, "By design. This function is inherently handling only ANSI text print jobs.") if (TextOutA(pData->hDC, CurrentCol * CharWidth, CurrentLine * CharHeight, (LPCSTR)pLineBuffer, Length) == FALSE) { ODS(("TextOut() failed\n")); bAbortDoc = TRUE; goto Done; } CurrentCol += Length; } /** Even if the length is zero, increment the line. Should happen when the character is only 0x0D or 0x0A. **/ if (fdwFlags & FLAG_CR) { CurrentCol=0; fdwFlags &= ~FLAG_CR; } if (fdwFlags & FLAG_LF) { CurrentLine++; fdwFlags &= ~FLAG_LF; } /** We need a new page. Set the current line to the end of the page. We could do a End/StartPage sequence, but this may cause a blank page to get ejected. Note: this code will avoid printing out pages that consist of formfeeds only (if you have a page with a space in it, that counts as text). **/ if (fdwFlags & FLAG_FF) { CurrentLine = LinesPerPage; CurrentCol = 0; fdwFlags &= ~FLAG_FF; } /** We have done the text out, so these characters have been successfully printed. Zero out Length so these characters won't be printed again **/ Length = 0; /** We only terminate this loop if we run out of chars or we run out of read buffer. **/ } while (pReadBuffer && pReadBuffer != pReadBufferEnd); /** Keep going until we get the last line **/ } while (!ReadAll); if (EndPage(pData->hDC) == SP_ERROR) { bAbortDoc = TRUE; goto Done; } /** Close the printer - we open/close the printer for each copy so the data pointer will rewind. **/ ClosePrinter(hPrinter); hPrinter = NULL; } /* While copies to print */ /** Let the printer know that we are done printing **/ EndDoc(pData->hDC); ReturnValue = TRUE; Done: if (dwTransparent) SetBkMode( pData->hDC, iBkMode ); if (hPrinter) ClosePrinter(hPrinter); if (bAbortDoc) AbortDoc(pData->hDC); if (pLineBuffer) FreeSplMem(pLineBuffer); if (hOldFont) { SelectObject(pData->hDC, hOldFont); DeleteObject(hFont); } if (ReadBufferStart) { FreeSplMem(ReadBufferStart); } return ReturnValue; }
static bool PrintToDevice(const PrintData &pd, ProgressUpdateUI *progressUI = nullptr, AbortCookieManager *abortCookie = nullptr) { AssertCrash(pd.engine); if (!pd.engine) return false; AssertCrash(pd.printerName); if (!pd.printerName) return false; BaseEngine &engine = *pd.engine; ScopedMem<WCHAR> fileName; DOCINFO di = { 0 }; di.cbSize = sizeof(DOCINFO); if (gPluginMode) { fileName.Set(url::GetFileName(gPluginURL)); // fall back to a generic "filename" instead of the more confusing temporary filename di.lpszDocName = fileName ? fileName : L"filename"; } else di.lpszDocName = engine.FileName(); int current = 1, total = 0; if (pd.sel.Count() == 0) { for (size_t i = 0; i < pd.ranges.Count(); i++) { if (pd.ranges.At(i).nToPage < pd.ranges.At(i).nFromPage) total += pd.ranges.At(i).nFromPage - pd.ranges.At(i).nToPage + 1; else total += pd.ranges.At(i).nToPage - pd.ranges.At(i).nFromPage + 1; } } else { for (int pageNo = 1; pageNo <= engine.PageCount(); pageNo++) { if (!BoundSelectionOnPage(pd.sel, pageNo).IsEmpty()) total++; } } AssertCrash(total > 0); if (0 == total) return false; if (progressUI) progressUI->UpdateProgress(current, total); // cf. http://blogs.msdn.com/b/oldnewthing/archive/2012/11/09/10367057.aspx ScopeHDC hdc(CreateDC(nullptr, pd.printerName, nullptr, pd.devMode)); if (!hdc) return false; if (StartDoc(hdc, &di) <= 0) return false; // MM_TEXT: Each logical unit is mapped to one device pixel. // Positive x is to the right; positive y is down. SetMapMode(hdc, MM_TEXT); const SizeI paperSize(GetDeviceCaps(hdc, PHYSICALWIDTH), GetDeviceCaps(hdc, PHYSICALHEIGHT)); const RectI printable(GetDeviceCaps(hdc, PHYSICALOFFSETX), GetDeviceCaps(hdc, PHYSICALOFFSETY), GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES)); const float dpiFactor = std::min(GetDeviceCaps(hdc, LOGPIXELSX) / engine.GetFileDPI(), GetDeviceCaps(hdc, LOGPIXELSY) / engine.GetFileDPI()); bool bPrintPortrait = paperSize.dx < paperSize.dy; if (pd.devMode && (pd.devMode.Get()->dmFields & DM_ORIENTATION)) bPrintPortrait = DMORIENT_PORTRAIT == pd.devMode.Get()->dmOrientation; if (pd.sel.Count() > 0) { for (int pageNo = 1; pageNo <= engine.PageCount(); pageNo++) { RectD bounds = BoundSelectionOnPage(pd.sel, pageNo); if (bounds.IsEmpty()) continue; if (progressUI) progressUI->UpdateProgress(current, total); StartPage(hdc); geomutil::SizeT<float> bSize = bounds.Size().Convert<float>(); float zoom = std::min((float)printable.dx / bSize.dx, (float)printable.dy / bSize.dy); // use the correct zoom values, if the page fits otherwise // and the user didn't ask for anything else (default setting) if (PrintScaleShrink == pd.advData.scale) zoom = std::min(dpiFactor, zoom); else if (PrintScaleNone == pd.advData.scale) zoom = dpiFactor; for (size_t i = 0; i < pd.sel.Count(); i++) { if (pd.sel.At(i).pageNo != pageNo) continue; RectD *clipRegion = &pd.sel.At(i).rect; PointI offset((int)((clipRegion->x - bounds.x) * zoom), (int)((clipRegion->y - bounds.y) * zoom)); if (pd.advData.scale != PrintScaleNone) { // center the selection on the physical paper offset.x += (int)(printable.dx - bSize.dx * zoom) / 2; offset.y += (int)(printable.dy - bSize.dy * zoom) / 2; } bool ok = false; short shrink = 1; do { RenderedBitmap *bmp = engine.RenderBitmap( pd.sel.At(i).pageNo, zoom / shrink, pd.rotation, clipRegion, Target_Print, abortCookie ? &abortCookie->cookie : nullptr); if (abortCookie) abortCookie->Clear(); if (bmp && bmp->GetBitmap()) { RectI rc(offset.x, offset.y, bmp->Size().dx * shrink, bmp->Size().dy * shrink); ok = bmp->StretchDIBits(hdc, rc); } delete bmp; shrink *= 2; } while (!ok && shrink < 32 && !(progressUI && progressUI->WasCanceled())); } // TODO: abort if !ok? if (EndPage(hdc) <= 0 || progressUI && progressUI->WasCanceled()) { AbortDoc(hdc); return false; } current++; } EndDoc(hdc); return false; } // print all the pages the user requested for (size_t i = 0; i < pd.ranges.Count(); i++) { int dir = pd.ranges.At(i).nFromPage > pd.ranges.At(i).nToPage ? -1 : 1; for (DWORD pageNo = pd.ranges.At(i).nFromPage; pageNo != pd.ranges.At(i).nToPage + dir; pageNo += dir) { if ((PrintRangeEven == pd.advData.range && pageNo % 2 != 0) || (PrintRangeOdd == pd.advData.range && pageNo % 2 == 0)) continue; if (progressUI) progressUI->UpdateProgress(current, total); StartPage(hdc); geomutil::SizeT<float> pSize = engine.PageMediabox(pageNo).Size().Convert<float>(); int rotation = 0; // Turn the document by 90 deg if it isn't in portrait mode if (pSize.dx > pSize.dy) { rotation += 90; std::swap(pSize.dx, pSize.dy); } // make sure not to print upside-down rotation = (rotation % 180) == 0 ? 0 : 270; // finally turn the page by (another) 90 deg in landscape mode if (!bPrintPortrait) { rotation = (rotation + 90) % 360; std::swap(pSize.dx, pSize.dy); } // dpiFactor means no physical zoom float zoom = dpiFactor; // offset of the top-left corner of the page from the printable area // (negative values move the page into the left/top margins, etc.); // offset adjustments are needed because the GDI coordinate system // starts at the corner of the printable area and we rather want to // center the page on the physical paper (except for PrintScaleNone // where the page starts at the very top left of the physical paper so // that printing forms/labels of varying size remains reliably possible) PointI offset(printable.x, printable.y); if (pd.advData.scale != PrintScaleNone) { // make sure to fit all content into the printable area when scaling // and the whole document page on the physical paper RectD rect = engine.PageContentBox(pageNo, Target_Print); geomutil::RectT<float> cbox = engine.Transform(rect, pageNo, 1.0, rotation).Convert<float>(); zoom = std::min((float)printable.dx / cbox.dx, std::min((float)printable.dy / cbox.dy, std::min((float)paperSize.dx / pSize.dx, (float)paperSize.dy / pSize.dy))); // use the correct zoom values, if the page fits otherwise // and the user didn't ask for anything else (default setting) if (PrintScaleShrink == pd.advData.scale && dpiFactor < zoom) zoom = dpiFactor; // center the page on the physical paper offset.x += (int)(paperSize.dx - pSize.dx * zoom) / 2; offset.y += (int)(paperSize.dy - pSize.dy * zoom) / 2; // make sure that no content lies in the non-printable paper margins geomutil::RectT<float> onPaper(printable.x + offset.x + cbox.x * zoom, printable.y + offset.y + cbox.y * zoom, cbox.dx * zoom, cbox.dy * zoom); if (onPaper.x < printable.x) offset.x += (int)(printable.x - onPaper.x); else if (onPaper.BR().x > printable.BR().x) offset.x -= (int)(onPaper.BR().x - printable.BR().x); if (onPaper.y < printable.y) offset.y += (int)(printable.y - onPaper.y); else if (onPaper.BR().y > printable.BR().y) offset.y -= (int)(onPaper.BR().y - printable.BR().y); } bool ok = false; short shrink = 1; do { RenderedBitmap *bmp = engine.RenderBitmap(pageNo, zoom / shrink, rotation, nullptr, Target_Print, abortCookie ? &abortCookie->cookie : nullptr); if (abortCookie) abortCookie->Clear(); if (bmp && bmp->GetBitmap()) { RectI rc(offset.x, offset.y, bmp->Size().dx * shrink, bmp->Size().dy * shrink); ok = bmp->StretchDIBits(hdc, rc); } delete bmp; shrink *= 2; } while (!ok && shrink < 32 && !(progressUI && progressUI->WasCanceled())); // TODO: abort if !ok? if (EndPage(hdc) <= 0 || progressUI && progressUI->WasCanceled()) { AbortDoc(hdc); return false; } current++; } } EndDoc(hdc); return true; }
/* GetWindowLong(hwnd, 4) must be available for use */ void WDPROC DumpPrinter(HWND hwnd, LPSTR szAppName, LPSTR szFileName) { HDC printer; PRINTDLG pd; GP_PRINT pr; DOCINFO di; char *buf; WORD *bufcount; int count; FILE *f; long lsize; long ldone; char pcdone[10]; memset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.hwndOwner = hwnd; pd.Flags = PD_PRINTSETUP | PD_RETURNDC; if ((f = fopen(szFileName, "rb")) == (FILE *)NULL) return; fseek(f, 0L, SEEK_END); lsize = ftell(f); if (lsize <= 0) lsize = 1; fseek(f, 0L, SEEK_SET); ldone = 0; if (PrintDlg(&pd)) { printer = pd.hDC; if (printer != (HDC)NULL) { pr.hdcPrn = printer; SetWindowLong(hwnd, 4, (LONG)((GP_LPPRINT)&pr)); PrintRegister((GP_LPPRINT)&pr); if ( (buf = malloc(4096+2)) != (char *)NULL ) { bufcount = (WORD *)buf; EnableWindow(hwnd,FALSE); pr.bUserAbort = FALSE; /* is parent set correctly */ pr.hDlgPrint = CreateDialogParam(hdllInstance, "CancelDlgBox", hwnd, PrintDlgProc, (LPARAM) szAppName); SetAbortProc(printer, PrintAbortProc); di.cbSize = sizeof(DOCINFO); di.lpszDocName = szAppName; di.lpszOutput = NULL; if (StartDoc(printer, &di) > 0) { while ( pr.hDlgPrint && !pr.bUserAbort && (count = fread(buf+2, 1, 4096, f)) != 0 ) { *bufcount = count; Escape(printer, PASSTHROUGH, count+2, (LPSTR)buf, NULL); ldone += count; sprintf(pcdone, "%d%% done", (int) (ldone * 100 / lsize)); SetWindowText(GetDlgItem(pr.hDlgPrint, CANCEL_PCDONE), pcdone); if (pr.bUserAbort) AbortDoc(printer); else EndDoc(printer); } if (!pr.bUserAbort) { EnableWindow(hwnd,TRUE); DestroyWindow(pr.hDlgPrint); } free(buf); } } DeleteDC(printer); SetWindowLong(hwnd, 4, (LONG)(0L)); PrintUnregister((GP_LPPRINT)&pr); } } fclose(f); }
BOOL PrintReport( IN HWND hWnd, IN HDC PrinterDC, IN LPREPORT_LINE lpReportHead ) /*++ Routine Description: PrintReport - Do page formatting and printing. Arguments: hWnd - PrinterDC - lpReportHead - Report head pointer. Return Value: BOOL - TRUE if we got a valid Printer DC, FALSE otherwise. --*/ { TCHAR Buffer [ MAX_PATH ]; BOOL Success; int nError; SIZE szMetric; int cHeightPels; DOCINFO DocInfo; // // Validate the printer DC // DbgHandleAssert( PrinterDC ); // // Initialize the members of a DOCINFO structure. // DocInfo.cbSize = sizeof(DOCINFO); DocInfo.lpszDocName = GetString( IDS_DOC_TITLE ); DocInfo.lpszOutput = (LPTSTR) NULL; DocInfo.lpszDatatype = NULL; DocInfo.fwType = 0; // // Begin a print job by calling the StartDoc function. // nError = StartDoc( PrinterDC, &DocInfo ); if (nError == SP_ERROR) { PrinterError( hWnd, PrinterDC, (LPTSTR) GetString( IDS_START_DOC ) ); return FALSE; } // // Get the vertical resolution of printer. // cHeightPels = GetDeviceCaps( PrinterDC, VERTRES ); // // Use a string to get he max height of chars // lstrcpy( Buffer, L"Ay" ); // // Retrieve the character size: // szMetric.cx = Width of string in Buffer // szMetric.cy = Height of string in Buffer // GetTextExtentPoint32( PrinterDC, Buffer, lstrlen ( Buffer ), &szMetric ); // // To Find the true char width, divide cCharWidth by 2 // because there are two chars in the test string // CharWidth = szMetric.cx / 2; CharHt = szMetric.cy; // // Calculate the max lines for the page. // MaxLines = cHeightPels / szMetric.cy; // // Set the current line number to the top of the page. // LineNumber = 1; // // Inform the driver that the application is // about to begin sending data. // nError = StartPage( PrinterDC ); if (nError <= 0) { PrinterError( hWnd, PrinterDC, (LPTSTR) GetString( IDS_START_PAGE ) ); return FALSE; } // // Output the report lines to file or printer. // Success = OutputReportLines( hWnd, PrinterDC, IDC_SEND_TO_PRINTER, lpReportHead ); // // Determine whether the user has pressed the Cancel button in the AbortPrintJob // dialog box; if the button has been pressed, call the AbortDoc function. Otherwise, inform // the spooler that the page is complete. // if (bAbortReport) { AbortDoc( PrinterDC ); return(FALSE); // cancel print job } else { nError = EndPage( PrinterDC ); if (nError <= 0) { PrinterError( hWnd, PrinterDC, (LPTSTR) GetString( IDS_END_PAGE ) ); return FALSE; } // // Inform the driver that the document has ended. // nError = EndDoc( PrinterDC ); if (nError <= 0) { PrinterError( hWnd, PrinterDC, (LPTSTR) GetString( IDS_END_DOC ) ); return FALSE; } } return(TRUE); }
static bool PrintToDevice(PrintData& pd, ProgressUpdateUI *progressUI=NULL, AbortCookieManager *abortCookie=NULL) { AssertCrash(pd.engine); if (!pd.engine) return false; AssertCrash(pd.printerName); if (!pd.printerName) return false; BaseEngine& engine = *pd.engine; ScopedMem<WCHAR> fileName; DOCINFO di = { 0 }; di.cbSize = sizeof (DOCINFO); if (gPluginMode) { fileName.Set(ExtractFilenameFromURL(gPluginURL)); // fall back to a generic "filename" instead of the more confusing temporary filename di.lpszDocName = fileName ? fileName : L"filename"; } else di.lpszDocName = engine.FileName(); int current = 1, total = 0; if (pd.sel.Count() == 0) { for (size_t i = 0; i < pd.ranges.Count(); i++) { if (pd.ranges.At(i).nToPage < pd.ranges.At(i).nFromPage) total += pd.ranges.At(i).nFromPage - pd.ranges.At(i).nToPage + 1; else total += pd.ranges.At(i).nToPage - pd.ranges.At(i).nFromPage + 1; } } else { for (int pageNo = 1; pageNo <= engine.PageCount(); pageNo++) { if (!BoundSelectionOnPage(pd.sel, pageNo).IsEmpty()) total++; } } AssertCrash(total > 0); if (0 == total) return false; if (progressUI) progressUI->UpdateProgress(current, total); // cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1882 // According to our crash dumps, Cannon printer drivers (caprenn.dll etc.) // are buggy and like to crash during printing with DEP violation // We disable dep during printing to hopefully not crash // TODO: even better would be to print in a separate process so that // crashes during printing wouldn't affect the main process. It's also // much more complicated to implement ScopeDisableDEP scopeNoDEP; // cf. http://blogs.msdn.com/b/oldnewthing/archive/2012/11/09/10367057.aspx ScopeHDC hdc(CreateDC(pd.driverName, pd.printerName, pd.portName, pd.devMode)); if (!hdc) return false; if (StartDoc(hdc, &di) <= 0) return false; // MM_TEXT: Each logical unit is mapped to one device pixel. // Positive x is to the right; positive y is down. SetMapMode(hdc, MM_TEXT); const SizeI paperSize(GetDeviceCaps(hdc, PHYSICALWIDTH), GetDeviceCaps(hdc, PHYSICALHEIGHT)); const RectI printable(GetDeviceCaps(hdc, PHYSICALOFFSETX), GetDeviceCaps(hdc, PHYSICALOFFSETY), GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES)); const float dpiFactor = min(GetDeviceCaps(hdc, LOGPIXELSX) / engine.GetFileDPI(), GetDeviceCaps(hdc, LOGPIXELSY) / engine.GetFileDPI()); bool bPrintPortrait = paperSize.dx < paperSize.dy; if (pd.devMode && (pd.devMode.Get()->dmFields & DM_ORIENTATION)) bPrintPortrait = DMORIENT_PORTRAIT == pd.devMode.Get()->dmOrientation; if (pd.sel.Count() > 0) { for (int pageNo = 1; pageNo <= engine.PageCount(); pageNo++) { RectD bounds = BoundSelectionOnPage(pd.sel, pageNo); if (bounds.IsEmpty()) continue; if (progressUI) progressUI->UpdateProgress(current, total); StartPage(hdc); SizeT<float> bSize = bounds.Size().Convert<float>(); float zoom = min((float)printable.dx / bSize.dx, (float)printable.dy / bSize.dy); // use the correct zoom values, if the page fits otherwise // and the user didn't ask for anything else (default setting) if (PrintScaleShrink == pd.advData.scale) zoom = min(dpiFactor, zoom); else if (PrintScaleNone == pd.advData.scale) zoom = dpiFactor; for (size_t i = 0; i < pd.sel.Count(); i++) { if (pd.sel.At(i).pageNo != pageNo) continue; RectD *clipRegion = &pd.sel.At(i).rect; PointI offset((int)((clipRegion->x - bounds.x) * zoom), (int)((clipRegion->y - bounds.y) * zoom)); if (!pd.advData.asImage) { RectI rc((int)(printable.dx - bSize.dx * zoom) / 2 + offset.x, (int)(printable.dy - bSize.dy * zoom) / 2 + offset.y, (int)(clipRegion->dx * zoom), (int)(clipRegion->dy * zoom)); engine.RenderPage(hdc, rc, pd.sel.At(i).pageNo, zoom, pd.rotation, clipRegion, Target_Print, abortCookie ? &abortCookie->cookie : NULL); if (abortCookie) abortCookie->Clear(); } else { RenderedBitmap *bmp = NULL; short shrink = 1; do { bmp = engine.RenderBitmap(pd.sel.At(i).pageNo, zoom / shrink, pd.rotation, clipRegion, Target_Print, abortCookie ? &abortCookie->cookie : NULL); if (abortCookie) abortCookie->Clear(); if (!bmp || !bmp->GetBitmap()) { shrink *= 2; delete bmp; bmp = NULL; } } while (!bmp && shrink < 32 && !(progressUI && progressUI->WasCanceled())); if (bmp) { RectI rc((int)(paperSize.dx - bSize.dx * zoom) / 2 + offset.x, (int)(paperSize.dy - bSize.dy * zoom) / 2 + offset.y, bmp->Size().dx * shrink, bmp->Size().dy * shrink); bmp->StretchDIBits(hdc, rc); delete bmp; } } } if (EndPage(hdc) <= 0 || progressUI && progressUI->WasCanceled()) { AbortDoc(hdc); return false; } current++; } EndDoc(hdc); return false; } // print all the pages the user requested for (size_t i = 0; i < pd.ranges.Count(); i++) { int dir = pd.ranges.At(i).nFromPage > pd.ranges.At(i).nToPage ? -1 : 1; for (DWORD pageNo = pd.ranges.At(i).nFromPage; pageNo != pd.ranges.At(i).nToPage + dir; pageNo += dir) { if ((PrintRangeEven == pd.advData.range && pageNo % 2 != 0) || (PrintRangeOdd == pd.advData.range && pageNo % 2 == 0)) continue; if (progressUI) progressUI->UpdateProgress(current, total); StartPage(hdc); SizeT<float> pSize = engine.PageMediabox(pageNo).Size().Convert<float>(); int rotation = 0; // Turn the document by 90 deg if it isn't in portrait mode if (pSize.dx > pSize.dy) { rotation += 90; swap(pSize.dx, pSize.dy); } // make sure not to print upside-down rotation = (rotation % 180) == 0 ? 0 : 270; // finally turn the page by (another) 90 deg in landscape mode if (!bPrintPortrait) { rotation = (rotation + 90) % 360; swap(pSize.dx, pSize.dy); } // dpiFactor means no physical zoom float zoom = dpiFactor; // offset of the top-left corner of the page from the printable area // (negative values move the page into the left/top margins, etc.); // offset adjustments are needed because the GDI coordinate system // starts at the corner of the printable area and we rather want to // center the page on the physical paper (default behavior) PointI offset(-printable.x, -printable.y); if (pd.advData.scale != PrintScaleNone) { // make sure to fit all content into the printable area when scaling // and the whole document page on the physical paper RectD rect = engine.PageContentBox(pageNo, Target_Print); RectT<float> cbox = engine.Transform(rect, pageNo, 1.0, rotation).Convert<float>(); zoom = min((float)printable.dx / cbox.dx, min((float)printable.dy / cbox.dy, min((float)paperSize.dx / pSize.dx, (float)paperSize.dy / pSize.dy))); // use the correct zoom values, if the page fits otherwise // and the user didn't ask for anything else (default setting) if (PrintScaleShrink == pd.advData.scale && dpiFactor < zoom) zoom = dpiFactor; // make sure that no content lies in the non-printable paper margins RectT<float> onPaper((paperSize.dx - pSize.dx * zoom) / 2 + cbox.x * zoom, (paperSize.dy - pSize.dy * zoom) / 2 + cbox.y * zoom, cbox.dx * zoom, cbox.dy * zoom); if (onPaper.x < printable.x) offset.x += (int)(printable.x - onPaper.x); else if (onPaper.BR().x > printable.BR().x) offset.x -= (int)(onPaper.BR().x - printable.BR().x); if (onPaper.y < printable.y) offset.y += (int)(printable.y - onPaper.y); else if (onPaper.BR().y > printable.BR().y) offset.y -= (int)(onPaper.BR().y - printable.BR().y); } if (!pd.advData.asImage) { RectI rc = RectI::FromXY((int)(paperSize.dx - pSize.dx * zoom) / 2 + offset.x, (int)(paperSize.dy - pSize.dy * zoom) / 2 + offset.y, paperSize.dx, paperSize.dy); engine.RenderPage(hdc, rc, pageNo, zoom, rotation, NULL, Target_Print, abortCookie ? &abortCookie->cookie : NULL); if (abortCookie) abortCookie->Clear(); } else { RenderedBitmap *bmp = NULL; short shrink = 1; do { bmp = engine.RenderBitmap(pageNo, zoom / shrink, rotation, NULL, Target_Print, abortCookie ? &abortCookie->cookie : NULL); if (abortCookie) abortCookie->Clear(); if (!bmp || !bmp->GetBitmap()) { shrink *= 2; delete bmp; bmp = NULL; } } while (!bmp && shrink < 32 && !(progressUI && progressUI->WasCanceled())); if (bmp) { RectI rc((paperSize.dx - bmp->Size().dx * shrink) / 2 + offset.x, (paperSize.dy - bmp->Size().dy * shrink) / 2 + offset.y, bmp->Size().dx * shrink, bmp->Size().dy * shrink); bmp->StretchDIBits(hdc, rc); delete bmp; } } if (EndPage(hdc) <= 0 || progressUI && progressUI->WasCanceled()) { AbortDoc(hdc); return false; } current++; } } EndDoc(hdc); return true; }
/* * @unimplemented */ INT WINAPI Escape( _In_ HDC hdc, _In_ INT nEscape, _In_ INT cbInput, _In_ LPCSTR lpvInData, _Out_ LPVOID lpvOutData) { INT retValue = SP_ERROR; ULONG ulObjType; ulObjType = GDI_HANDLE_GET_TYPE(hdc); if (ulObjType == GDILoObjType_LO_METADC16_TYPE) { return METADC16_Escape(hdc, nEscape, cbInput, lpvInData, lpvOutData); } switch (nEscape) { case ABORTDOC: /* Note: Windows checks if the handle has any user data for the ABORTDOC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } else { retValue = AbortDoc(hdc); } break; case DRAFTMODE: case FLUSHOUTPUT: case SETCOLORTABLE: /* Note 1: DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE are outdated */ /* Note 2: Windows checks if the handle has any user data for the DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE commands * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); } retValue = FALSE; break; case SETABORTPROC: /* Note: Windows checks if the handle has any user data for the SETABORTPROC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } retValue = SetAbortProc(hdc, (ABORTPROC)lpvInData); break; case GETCOLORTABLE: retValue = GetSystemPaletteEntries(hdc, (UINT)*lpvInData, 1, (LPPALETTEENTRY)lpvOutData); if (!retValue) { retValue = SP_ERROR; } break; case ENDDOC: /* Note: Windows checks if the handle has any user data for the ENDDOC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } retValue = EndDoc(hdc); break; case GETSCALINGFACTOR: /* Note GETSCALINGFACTOR is outdated have been replace by GetDeviceCaps */ if (ulObjType == GDI_OBJECT_TYPE_DC) { if (lpvOutData) { PPOINT ptr = (PPOINT)lpvOutData; ptr->x = 0; ptr->y = 0; } } retValue = FALSE; break; case GETEXTENDEDTEXTMETRICS: retValue = GetETM(hdc, (EXTTEXTMETRIC *)lpvOutData) != 0; break; case STARTDOC: { DOCINFOA di; /* Note: Windows checks if the handle has any user data for the STARTDOC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } di.cbSize = sizeof(DOCINFOA); di.lpszOutput = 0; di.lpszDatatype = 0; di.fwType = 0; di.lpszDocName = lpvInData; /* NOTE : doc for StartDocA/W at msdn http://msdn2.microsoft.com/en-us/library/ms535793(VS.85).aspx */ retValue = StartDocA(hdc, &di); /* Check if StartDocA failed */ if (retValue < 0) { { retValue = GetLastError(); /* Translate StartDocA error code to STARTDOC error code * see msdn http://msdn2.microsoft.com/en-us/library/ms535472.aspx */ switch(retValue) { case ERROR_NOT_ENOUGH_MEMORY: retValue = SP_OUTOFMEMORY; break; case ERROR_PRINT_CANCELLED: retValue = SP_USERABORT; break; case ERROR_DISK_FULL: retValue = SP_OUTOFDISK; break; default: retValue = SP_ERROR; break; } } } } break; default: UNIMPLEMENTED; SetLastError(ERROR_CALL_NOT_IMPLEMENTED); } return retValue; }
/* GetWindowLong(hwnd, 4) must be available for use */ void WDPROC DumpPrinter(HWND hwnd, LPSTR szAppName, LPSTR szFileName) { HDC printer; PRINTDLG pd; /* FIXME: share these with CopyPrint */ static DEVNAMES * pDevNames = NULL; static DEVMODE * pDevMode = NULL; LPCTSTR szDriver, szDevice, szOutput; GP_PRINT pr; DOCINFO di; char *buf; WORD *bufcount; int count; FILE *f; long lsize; long ldone; char pcdone[10]; if ((f = fopen(szFileName, "rb")) == NULL) return; fseek(f, 0L, SEEK_END); lsize = ftell(f); if (lsize <= 0) lsize = 1; fseek(f, 0L, SEEK_SET); ldone = 0; /* Print Setup Dialog */ /* See http://support.microsoft.com/kb/240082 */ memset(&pd, 0, sizeof(pd)); pd.lStructSize = sizeof(pd); pd.hwndOwner = hwnd; pd.Flags = PD_PRINTSETUP; pd.hDevNames = pDevNames; pd.hDevMode = pDevMode; if (PrintDlg(&pd)) { pDevNames = (DEVNAMES *) GlobalLock(pd.hDevNames); pDevMode = (DEVMODE *) GlobalLock(pd.hDevMode); szDriver = (LPCTSTR)pDevNames + pDevNames->wDriverOffset; szDevice = (LPCTSTR)pDevNames + pDevNames->wDeviceOffset; szOutput = (LPCTSTR)pDevNames + pDevNames->wOutputOffset; printer = CreateDC(szDriver, szDevice, szOutput, pDevMode); GlobalUnlock(pd.hDevMode); GlobalUnlock(pd.hDevNames); /* We no longer free these structures, but preserve them for the next time GlobalFree(pd.hDevMode); GlobalFree(pd.hDevNames); */ if (printer == NULL) return; /* abort */ pr.hdcPrn = printer; SetWindowLongPtr(hwnd, 4, (LONG_PTR)((GP_LPPRINT)&pr)); PrintRegister((GP_LPPRINT)&pr); if ((buf = malloc(4096 + 2)) != NULL) { bufcount = (WORD *)buf; EnableWindow(hwnd,FALSE); pr.bUserAbort = FALSE; pr.hDlgPrint = CreateDialogParam(hdllInstance, "CancelDlgBox", hwnd, PrintDlgProc, (LPARAM)szAppName); SetAbortProc(printer, PrintAbortProc); memset(&di, 0, sizeof(DOCINFO)); di.cbSize = sizeof(DOCINFO); di.lpszDocName = szAppName; if (StartDoc(printer, &di) > 0) { while (pr.hDlgPrint && !pr.bUserAbort && (count = fread(buf + 2, 1, 4096, f)) != 0 ) { int ret; *bufcount = count; ret = Escape(printer, PASSTHROUGH, count + 2, (LPSTR)buf, NULL); ldone += count; if (ret != SP_ERROR) { sprintf(pcdone, "%d%% done", (int)(ldone * 100 / lsize)); SetWindowText(GetDlgItem(pr.hDlgPrint, CANCEL_PCDONE), pcdone); } else { SetWindowText(GetDlgItem(pr.hDlgPrint, CANCEL_PCDONE), "Passthrough Error!"); } if (pr.bUserAbort) AbortDoc(printer); else EndDoc(printer); } if (!pr.bUserAbort) { EnableWindow(hwnd, TRUE); DestroyWindow(pr.hDlgPrint); } free(buf); } } DeleteDC(printer); SetWindowLong(hwnd, 4, 0L); PrintUnregister((GP_LPPRINT)&pr); } fclose(f); }
static void PrintCatalogThread (CWnd* pParent, CFrameWndEx* pMainFrame) { CCADView* pView = (CCADView*)pMainFrame->GetActiveView(); CPrintDialog* PD = new CPrintDialog(FALSE, PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOSELECTION|PD_ENABLEPRINTHOOK, pParent); lcPiecesLibrary *pLib = lcGetPiecesLibrary(); int bricks = 0; for (int j = 0; j < pLib->mPieces.GetSize(); j++) if (pLib->mPieces[j]->m_strDescription[0] != '~') bricks++; int rows = theApp.GetProfileInt("Default", "Catalog Rows", 10); int cols = theApp.GetProfileInt("Default", "Catalog Columns", 3); PD->m_pd.lpfnPrintHook = PrintHookProc; PD->m_pd.nFromPage = PD->m_pd.nMinPage = 1; PD->m_pd.nMaxPage = bricks/(rows*cols); if (bricks%(rows*cols) != 0) PD->m_pd.nMaxPage++; PD->m_pd.nToPage = PD->m_pd.nMaxPage; PD->m_pd.lCustData= (LONG)pMainFrame; // bring up the print dialog and allow user to change things if (theApp.DoPrintDialog(PD) != IDOK) return; if (PD->m_pd.hDC == NULL) return; // update page range rows = theApp.GetProfileInt("Default","Catalog Rows", 10); cols = theApp.GetProfileInt("Default","Catalog Columns", 3); PD->m_pd.nMaxPage = bricks/(rows*cols); if (bricks%(rows*cols) != 0) PD->m_pd.nMaxPage++; // gather file to print to if print-to-file selected CString strOutput; if (PD->m_pd.Flags & PD_PRINTTOFILE) { // construct CFileDialog for browsing CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT)); CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT)); CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER)); CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION)); CFileDialog dlg(FALSE, strDef, strPrintDef, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter); dlg.m_ofn.lpstrTitle = strCaption; if (dlg.DoModal() != IDOK) return; // set output device to resulting path name strOutput = dlg.GetPathName(); } DOCINFO docInfo; memset(&docInfo, 0, sizeof(DOCINFO)); docInfo.cbSize = sizeof(DOCINFO); docInfo.lpszDocName = "LeoCAD pieces catalog"; CString strPortName; int nFormatID; if (strOutput.IsEmpty()) { docInfo.lpszOutput = NULL; strPortName = PD->GetPortName(); nFormatID = AFX_IDS_PRINTONPORT; } else { docInfo.lpszOutput = strOutput; AfxGetFileTitle(strOutput, strPortName.GetBuffer(_MAX_PATH), _MAX_PATH); nFormatID = AFX_IDS_PRINTTOFILE; } // setup the printing DC SetAbortProc(PD->m_pd.hDC, _AfxAbortProc); // disable main window while printing & init printing status dialog pParent->EnableWindow(FALSE); CPrintingDialog dlgPrintStatus(NULL); CString strTemp; dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, "LeoCAD parts catalog"); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME, PD->GetDeviceName()); AfxFormatString1(strTemp, nFormatID, strPortName); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strTemp); dlgPrintStatus.ShowWindow(SW_SHOW); dlgPrintStatus.UpdateWindow(); // start document printing process if (StartDoc(PD->m_pd.hDC, &docInfo) == SP_ERROR) { pParent->EnableWindow(TRUE); dlgPrintStatus.DestroyWindow(); AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT); return; } // Guarantee values are in the valid range UINT nEndPage = PD->m_pd.nToPage; UINT nStartPage = PD->m_pd.nFromPage; if (PD->PrintAll()) { nEndPage = PD->m_pd.nMaxPage; nStartPage = PD->m_pd.nMinPage; } if (nEndPage < PD->m_pd.nMinPage) nEndPage = PD->m_pd.nMinPage; if (nEndPage > PD->m_pd.nMaxPage) nEndPage = PD->m_pd.nMaxPage; if (nStartPage < PD->m_pd.nMinPage) nStartPage = PD->m_pd.nMinPage; if (nStartPage > PD->m_pd.nMaxPage) nStartPage = PD->m_pd.nMaxPage; int nStep = (nEndPage >= nStartPage) ? 1 : -1; nEndPage = nEndPage + nStep; VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM)); // begin page printing loop BOOL bError = FALSE; // set up drawing rect to entire page (in logical coordinates) CRect rectDraw (0, 0, GetDeviceCaps(PD->m_pd.hDC, HORZRES), GetDeviceCaps(PD->m_pd.hDC, VERTRES)); DPtoLP(PD->m_pd.hDC, (LPPOINT)(RECT*)&rectDraw, 2); rectDraw.DeflateRect( GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSX)*theApp.GetProfileInt("Default","Margin Left", 50)/100, GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSY)*theApp.GetProfileInt("Default","Margin Top", 50)/100, GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSX)*theApp.GetProfileInt("Default","Margin Right", 50)/100, GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSY)*theApp.GetProfileInt("Default","Margin Bottom", 50)/100); int w = rectDraw.Width()/cols; int h = rectDraw.Height()/rows; // Creating Compatible Memory Device Context CDC *pMemDC = new CDC; if (!pMemDC->CreateCompatibleDC(pView->GetDC())) return; // Preparing bitmap header for DIB section BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = w; bi.bmiHeader.biHeight = h; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = w * h * (24/8); bi.bmiHeader.biXPelsPerMeter = 2925; bi.bmiHeader.biYPelsPerMeter = 2925; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; LPBITMAPINFOHEADER lpbi[1]; // Creating a DIB surface HBITMAP hBm, hBmOld; hBm = CreateDIBSection(pView->GetDC()->GetSafeHdc(), &bi, DIB_RGB_COLORS, (void **)&lpbi, NULL, (DWORD)0); if (!hBm) return; // Selecting the DIB Surface hBmOld = (HBITMAP)::SelectObject(pMemDC->GetSafeHdc(), hBm); if (!hBmOld) return; // Setting up a Pixel format for the DIB surface PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1,PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int pixelformat = ChoosePixelFormat(pMemDC->m_hDC, &pfd); DescribePixelFormat(pMemDC->m_hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); SetPixelFormat(pMemDC->m_hDC, pixelformat, &pfd); // Creating a OpenGL context HGLRC hmemrc = wglCreateContext(pMemDC->GetSafeHdc()); // Setting up the current OpenGL context GL_DisableVertexBufferObject(); wglMakeCurrent(pMemDC->GetSafeHdc(), hmemrc); double aspect = (float)w/(float)h; glMatrixMode(GL_MODELVIEW); glViewport(0, 0, w, h); // Sort pieces by description struct BRICKSORT { char name[64]; int actual; struct BRICKSORT *next; } start, *node, *previous, *news; start.next = NULL; for (int j = 0; j < pLib->mPieces.GetSize(); j++) { char* desc = pLib->mPieces[j]->m_strDescription; if (desc[0] != '~') continue; // Find the correct location previous = &start; node = start.next; while ((node) && (strcmp(desc, node->name) > 0)) { node = node->next; previous = previous->next; } news = (struct BRICKSORT*) malloc(sizeof(struct BRICKSORT)); news->next = node; previous->next = news; strcpy(news->name, desc); news->actual = j; } node = start.next; if (PD->PrintRange()) { for (int j = 0; j < (int)(nStartPage - 1)*rows*cols; j++) if (node) node = node->next; } LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); lf.lfHeight = -MulDiv(12, GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSY), 72); lf.lfWeight = FW_REGULAR; lf.lfCharSet = DEFAULT_CHARSET; lf.lfQuality = PROOF_QUALITY; strcpy (lf.lfFaceName , "Arial"); HFONT HeaderFont = CreateFontIndirect(&lf); HFONT OldFont = (HFONT)SelectObject(PD->m_pd.hDC, HeaderFont); SetBkMode(PD->m_pd.hDC, TRANSPARENT); SetTextColor(PD->m_pd.hDC, 0x000000); SetTextAlign (PD->m_pd.hDC, TA_TOP|TA_LEFT|TA_NOUPDATECP); SetTextColor (pMemDC->m_hDC, 0x000000); lf.lfHeight = -MulDiv(10, GetDeviceCaps(pMemDC->m_hDC, LOGPIXELSY), 72); lf.lfWeight = FW_BOLD; HFONT CatalogFont = CreateFontIndirect(&lf); HFONT OldMemFont = (HFONT)SelectObject(pMemDC->m_hDC, CatalogFont); HPEN hpOld = (HPEN)SelectObject(pMemDC->m_hDC,(HPEN)GetStockObject(BLACK_PEN)); for (UINT nCurPage = nStartPage; nCurPage != nEndPage; nCurPage += nStep) { // write current page TCHAR szBuf[80]; wsprintf(szBuf, strTemp, nCurPage); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf); // attempt to start the current page if (StartPage(PD->m_pd.hDC) < 0) { bError = TRUE; break; } int printed = 0; // page successfully started, so now render the page for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) { if (node == NULL) continue; printed++; glDepthFunc(GL_LEQUAL); glClearColor(1,1,1,1); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glDisable(GL_DITHER); glShadeModel(GL_FLAT); lcSetColor(lcGetActiveProject()->GetCurrentColor()); // dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, node->name); node = node->next; PieceInfo* pInfo = pLib->mPieces[node->actual]; pInfo->ZoomExtents(30.0f, (float)aspect); float pos[4] = { 0, 0, 10, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, pos); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); FillRect(pMemDC->m_hDC, CRect(0,h,w,0), (HBRUSH)GetStockObject(WHITE_BRUSH)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); pInfo->RenderPiece(lcGetActiveProject()->GetCurrentColor()); glFlush(); TextOut (pMemDC->m_hDC, 5, 5, pInfo->m_strDescription, strlen(pInfo->m_strDescription)); // BitBlt(PD->m_pd.hDC, rectDraw.left+(w*c), rectDraw.top+(h*r), w, h, pMemDC->m_hDC, 0, 0, SRCCOPY); LPBITMAPINFOHEADER lpbi[1]; lpbi[0] = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hBm, 24)); BITMAPINFO bi; ZeroMemory(&bi, sizeof(BITMAPINFO)); memcpy (&bi.bmiHeader, lpbi[0], sizeof(BITMAPINFOHEADER)); SetStretchBltMode(PD->m_pd.hDC, COLORONCOLOR); StretchDIBits(PD->m_pd.hDC, rectDraw.left+(w*c), rectDraw.top+(h*r), w, h, 0, 0, w, h, (LPBYTE) lpbi[0] + lpbi[0]->biSize + lpbi[0]->biClrUsed * sizeof(RGBQUAD), &bi, DIB_RGB_COLORS, SRCCOPY); if (lpbi[0]) GlobalFreePtr(lpbi[0]); } DWORD dwPrint = theApp.GetProfileInt("Settings","Print", PRINT_NUMBERS|PRINT_BORDER); if (dwPrint & PRINT_BORDER) for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) { if (printed == 0) continue; printed--; if (r == 0) { MoveToEx(PD->m_pd.hDC, rectDraw.left+(w*c), rectDraw.top+(h*r), NULL); LineTo(PD->m_pd.hDC, rectDraw.left+(w*(c+1)), rectDraw.top+(h*r)); } if (c == 0) { MoveToEx(PD->m_pd.hDC, rectDraw.left+(w*c), rectDraw.top+(h*r), NULL); LineTo(PD->m_pd.hDC, rectDraw.left+(w*c), rectDraw.top+(h*(r+1))); } MoveToEx(PD->m_pd.hDC, rectDraw.left+(w*(c+1)), rectDraw.top+(h*r), NULL); LineTo(PD->m_pd.hDC, rectDraw.left+(w*(c+1)), rectDraw.top+(h*(r+1))); MoveToEx(PD->m_pd.hDC, rectDraw.left+(w*c), rectDraw.top+(h*(r+1)), NULL); LineTo(PD->m_pd.hDC, rectDraw.left+(w*(c+1)), rectDraw.top+(h*(r+1))); } CRect r2 = rectDraw; r2.top -= GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSY)*theApp.GetProfileInt("Default","Margin Top", 50)/200; r2.bottom += GetDeviceCaps(PD->m_pd.hDC, LOGPIXELSY)*theApp.GetProfileInt("Default","Margin Bottom", 50)/200; pView->PrintHeader(FALSE, PD->m_pd.hDC, r2, nCurPage, nEndPage, TRUE); pView->PrintHeader(TRUE, PD->m_pd.hDC, r2, nCurPage, nEndPage, TRUE); if (EndPage(PD->m_pd.hDC) < 0 || !_AfxAbortProc(PD->m_pd.hDC, 0)) { bError = TRUE; break; } } SelectObject(pMemDC->m_hDC, hpOld); SelectObject(PD->m_pd.hDC, OldFont); DeleteObject(HeaderFont); SelectObject(pMemDC->m_hDC, OldMemFont); DeleteObject(CatalogFont); node = start.next; while (node) { previous = node; node = node->next; free(previous); } GL_EnableVertexBufferObject(); wglMakeCurrent(NULL, NULL); wglDeleteContext(hmemrc); SelectObject(pMemDC->GetSafeHdc(), hBmOld); DeleteObject(hBm); delete pMemDC; // cleanup document printing process if (!bError) EndDoc(PD->m_pd.hDC); else AbortDoc(PD->m_pd.hDC); pParent->EnableWindow(); dlgPrintStatus.DestroyWindow(); if (PD != NULL && PD->m_pd.hDC != NULL) { ::DeleteDC(PD->m_pd.hDC); PD->m_pd.hDC = NULL; } delete PD; }