// Print catalog and pieces list // // TODO: rewrite everything #include "stdafx.h" #include "leocad.h" #include "Print.h" #include "project.h" #include "pieceinf.h" #include "globals.h" #include "CADView.h" #include "Tools.h" #include "Piece.h" #include "library.h" #include "lc_application.h" static void PrintCatalogThread (CWnd* pParent, CFrameWnd* pMainFrame) { CCADView* pView = (CCADView*)pMainFrame->GetActiveView(); CPrintDialog* PD = new CPrintDialog(FALSE, PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOSELECTION|PD_ENABLEPRINTHOOK, pParent); PiecesLibrary *pLib = lcGetPiecesLibrary(); int bricks = 0; for (int j = 0; j < pLib->GetPieceCount (); j++) if (pLib->GetPieceInfo(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 = OpenGLChoosePixelFormat(pMemDC->m_hDC, &pfd); OpenGLDescribePixelFormat(pMemDC->m_hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); OpenGLSetPixelFormat(pMemDC->m_hDC, pixelformat, &pfd); // Creating a OpenGL context HGLRC hmemrc = pfnwglCreateContext(pMemDC->GetSafeHdc()); // Setting up the current OpenGL context pfnwglMakeCurrent(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->GetPieceCount (); j++) { char* desc = pLib->GetPieceInfo(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++; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0f, aspect, 1.0f, 200.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); 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); glColor3ubv(FlatColorArray[lcGetActiveProject()->GetCurrentColor()]); // dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, node->name); node = node->next; PieceInfo* pInfo = pLib->GetPieceInfo(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); } pfnwglMakeCurrent(NULL, NULL); pfnwglDeleteContext(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; } UINT PrintCatalogFunction (LPVOID pv) { PRINT_PARAMS* param = (PRINT_PARAMS*)pv; PrintCatalogThread (param->pParent, param->pMainFrame); param->pParent->EnableWindow (TRUE); free(param); return 0; } static void PrintPiecesThread(void* pv) { CFrameWnd* pFrame = (CFrameWnd*)pv; CView* pView = pFrame->GetActiveView(); CPrintDialog* PD = new CPrintDialog(FALSE, PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOPAGENUMS|PD_NOSELECTION, pFrame); PiecesLibrary *pLib = lcGetPiecesLibrary(); Project* project = lcGetActiveProject(); UINT *pieces = (UINT*)malloc(pLib->GetPieceCount ()*28*sizeof(UINT)); int col[28]; memset (pieces, 0, pLib->GetPieceCount ()*28*sizeof(UINT)); memset (&col, 0, sizeof (col)); for (Piece* tmp = project->m_pPieces; tmp; tmp = tmp->m_pNext) { int idx = pLib->GetPieceIndex (tmp->GetPieceInfo ()); pieces[(idx*28)+tmp->GetColor()]++; col[tmp->GetColor()]++; } int rows = 0, cols = 1, i, j; for (i = 0; i < pLib->GetPieceCount (); i++) for (j = 0; j < 28; j++) if (pieces[(i*28)+j] > 0) { rows++; j = 28; } int ID = 1; for (i = 0; i < 28; i++) if (col[i]) { col[i] = ID; ID++; cols++; } if (theApp.DoPrintDialog(PD) != IDOK) return; if (PD->m_pd.hDC == NULL) return; // 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 strDocName = "LeoCAD - Pieces used in "; strDocName += project->m_strTitle; DOCINFO docInfo; memset(&docInfo, 0, sizeof(DOCINFO)); docInfo.cbSize = sizeof(DOCINFO); docInfo.lpszDocName = strDocName; 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, strDocName); 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(resx*theApp.GetProfileInt("Default","Margin Left", 50)/100, resy*theApp.GetProfileInt("Default","Margin Top", 50)/100, resx*theApp.GetProfileInt("Default","Margin Right", 50)/100, resy*theApp.GetProfileInt("Default","Margin Bottom", 50)/100); int rowspp = rectDraw.Height()/(int)(resy*0.75); PD->m_pd.nMaxPage = rows/(rowspp+1); if (rows%(rowspp+1) > 0) PD->m_pd.nMaxPage++; 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; int picw = resx; int w = (rectDraw.Width()-picw)/cols; int h = rectDraw.Height()/(rowspp+1); // 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 = picw; bi.bmiHeader.biHeight = h; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = picw * h * 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); if (!hBmOld) return; 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 = OpenGLChoosePixelFormat(pMemDC->m_hDC, &pfd); OpenGLDescribePixelFormat(pMemDC->m_hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); OpenGLSetPixelFormat(pMemDC->m_hDC, pixelformat, &pfd); HGLRC hmemrc = pfnwglCreateContext(pMemDC->GetSafeHdc()); pfnwglMakeCurrent(pMemDC->GetSafeHdc(), hmemrc); double aspect = (float)picw/(float)h; glMatrixMode(GL_MODELVIEW); glViewport(0, 0, picw, h); // Sort pieces by description struct BRICKSORT { char name[64]; int actual; struct BRICKSORT *next; } start, *node, *previous, *news; start.next = NULL; for (j = 0; j < pLib->GetPieceCount (); j++) { char* desc = pLib->GetPieceInfo(j)->m_strDescription; if (desc[0] == '~') continue; BOOL bAdd = FALSE; for (i = 0; i < 28; i++) if (pieces[(j*28)+i]) bAdd = TRUE; if (!bAdd) 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 (j = 0; j < (int)(nStartPage - 1)*rows*cols; j++) if (node) node = node->next; } LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); lf.lfHeight = -MulDiv(10, resy, 72); lf.lfWeight = FW_BOLD; 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); 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) { TCHAR szBuf[80]; wsprintf(szBuf, strTemp, nCurPage); dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf); if (StartPage(PD->m_pd.hDC) < 0) { bError = TRUE; break; } int printed = 0; CString str; CRect rc(rectDraw.left+picw, rectDraw.top, rectDraw.left+picw+w, rectDraw.top+h); for (i = 0; i < 28; i++) if (col[i]) { str.LoadString(IDS_COLOR01 + i); DrawText(PD->m_pd.hDC, (LPCTSTR)str, str.GetLength(), rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); rc.OffsetRect (w, 0); } str = "Total"; DrawText(PD->m_pd.hDC, (LPCTSTR)str, str.GetLength(), rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); for (int r = 1; r < rowspp+1; r++) { if (node == NULL) continue; printed++; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0f, aspect, 1.0f, 200.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); 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); glColor3ubv(FlatColorArray[project->m_nCurColor]); PieceInfo* pInfo = pLib->GetPieceInfo(node->actual); node = node->next; 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,picw,0), (HBRUSH)GetStockObject(WHITE_BRUSH)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); pInfo->RenderPiece(project->m_nCurColor); glFlush(); TextOut (pMemDC->m_hDC, 5, 5, pInfo->m_strDescription, strlen(pInfo->m_strDescription)); int rowtotal = 0; char tmp[5]; int idx = (pLib->GetPieceIndex (pInfo)); for (i = 0; i < 28; i++) if (pieces[(idx*28)+i]) { CRect rc(rectDraw.left+picw+w*(col[i]-1), rectDraw.top+h*r, rectDraw.left+picw+w*col[i], rectDraw.top+h*(r+1)); sprintf (tmp, "%d", pieces[(idx*28)+i]); DrawText(PD->m_pd.hDC, tmp, strlen(tmp), rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE); rowtotal += pieces[(idx*28)+i]; } sprintf (tmp, "%d", rowtotal); CRect rc(rectDraw.right-w, rectDraw.top+h*r, rectDraw.right, rectDraw.top+h*(r+1)); DrawText(PD->m_pd.hDC, tmp, strlen(tmp), rc, DT_CENTER|DT_VCENTER|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); StretchDIBits(PD->m_pd.hDC, rectDraw.left, rectDraw.top+(h*r), picw, h, 0, 0, picw, h, (LPBYTE) lpbi[0] + lpbi[0]->biSize + lpbi[0]->biClrUsed * sizeof(RGBQUAD), &bi, DIB_RGB_COLORS, SRCCOPY); if (lpbi[0]) GlobalFreePtr(lpbi[0]); } /* if (pFrame->m_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))); } */ 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); } pfnwglMakeCurrent(NULL, NULL); pfnwglDeleteContext(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 != NULL && PD->m_pd.hDC != NULL) { ::DeleteDC(PD->m_pd.hDC); PD->m_pd.hDC = NULL; } free (pieces); delete PD; } UINT PrintPiecesFunction (LPVOID pv) { PrintPiecesThread(pv); CFrameWnd* pFrame = (CFrameWnd*)pv; pFrame->EnableWindow(TRUE); return 0; }