Beispiel #1
0
BOOL CMainMDIFrame::OnFilePrint()
{
	// Bring up a dialog to choose the printer
	CPrintDialog Printdlg;

	try
	{
		INT_PTR Res = Printdlg.DoModal(*this);

		// Retrieve the printer DC
		// CDC dcPrinter = Printdlg.GetPrinterDC();

		// TODO:
		// Add your own code here. Refer to the tutorial for additional information

		return (Res == IDOK);	// boolean expression
	}

	catch (const CWinException& /* e */)
	{
		// No default printer
		MessageBox(_T("Unable to display print dialog"), _T("Print Failed"), MB_OK);
		return FALSE;
	}
}
Beispiel #2
0
void PagePrint::PrintPage(){
	CPrintDialog* printDlg = NULL;

	printDlg = new CPrintDialog(FALSE, PD_ALLPAGES);
	if (printDlg->DoModal() == IDOK){
		//출력에 대한 알고리즘이 나오면 된다.
	}

	if (printDlg != NULL){
		delete printDlg;
	}
}
Beispiel #3
0
//*************************************************************************************
void CBCGPKeyMapDlg::PrintKeyMap ()
{
	CWaitCursor WaitCursor;
	
	int nItem = -1;
	int nFlag = (m_KeymapList.GetSelectedCount () > 0)  ?  LVNI_SELECTED : LVNI_ALL;
	
	CPrintDialog dlgPrint (FALSE, PD_ALLPAGES | PD_RETURNDC | PD_NOSELECTION, NULL);
	if (dlgPrint.DoModal() != IDOK)
	{
		return;
	}
	
	// Obtain a handle to the device context.
	HDC hdcPrn = dlgPrint.GetPrinterDC ();
	if (hdcPrn == NULL)
	{
		ASSERT (FALSE);
		return;
	}

	CDC dc;
	dc.Attach (hdcPrn);

	CSize szPage (dc.GetDeviceCaps (HORZRES), dc.GetDeviceCaps (VERTRES));

	dc.StartDoc(_T("BCGKeyMapDlg"));  // begin a new print job
	dc.StartPage ();
	
	int nPage = 1;
	int y = OnPrintHeader (dc, nPage, szPage.cx);

	while ((nItem = m_KeymapList.GetNextItem (nItem, nFlag)) >= 0)
	{
		int nItemHeight = OnPrintItem (dc, nItem, y, szPage.cx, TRUE /* Calc height */);
		if (y + nItemHeight > szPage.cy)
		{
			dc.EndPage();

			dc.StartPage ();
			y = OnPrintHeader (dc, ++nPage, szPage.cx);
		}

		y += OnPrintItem (dc, nItem, y, szPage.cx, FALSE /* Draw */);
	}
	
	dc.EndPage();
	dc.EndDoc();
}
Beispiel #4
0
int  CLitePrint::Dialog(LPTSTR PrinterName, int Pages)
{
	CPrintDialog* printDlg = NULL;
    bool    bNewDlg = true;
    // if no special printer-dialog is given, we take the standard printer-dialog
    if (printDlg == NULL)
    {
		printDlg = new CPrintDialog(FALSE,PD_DISABLEPRINTTOFILE);
		bNewDlg = false;
    }
    ASSERT(printDlg != NULL);
	if (PrinterName == NULL) 
	{
		// which printer ist desired, and how much copies?
		if (printDlg->DoModal() == IDCANCEL) 
			return (-1);
		m_hprinter = printDlg->GetPrinterDC();
		m_info.m_numCopies = printDlg->GetCopies ();
	} 
	else 
	{
		// a printer is given...
		if (m_PrinterDC.CreateDC(NULL, PrinterName, NULL, NULL) == 0) 
		{
			m_LastErrNo = PRERR_CANTCREATEPRINTERDC;
            if (!bNewDlg && printDlg != NULL) 
				delete (printDlg);
			return (-1);
		}
		m_hprinter = m_PrinterDC;
		m_info.m_numCopies = Pages;
	}
	
	if (m_DC.Attach(m_hprinter) == 0) 
    {
        if (!bNewDlg && printDlg != NULL) 
			delete (printDlg);
        return (-1);
    }
	m_DC.m_bPrinting = TRUE;

    if (!bNewDlg && printDlg != NULL) 
		delete (printDlg);
	return (0);
}
Beispiel #5
0
// Sends the bitmap extracted from the View window to a printer of your choice
// This function provides a useful reference for printing bitmaps in general
void CDoc::Print()
{
	// Get the dimensions of the View window
	CRect rcView = GetView().GetClientRect();
	int Width = rcView.Width();
	int Height = rcView.Height();

	// Copy the bitmap from the View window
	CClientDC ViewDC(GetView());
	CMemDC MemDC(ViewDC);
	CBitmap bmView;
	bmView.CreateCompatibleBitmap(ViewDC, Width, Height);
	MemDC.SelectObject(bmView);
	MemDC.BitBlt(0, 0, Width, Height, ViewDC, 0, 0, SRCCOPY);

	CPrintDialog PrintDlg;

	try
	{
		// Bring up a dialog to choose the printer
		if (PrintDlg.DoModal(GetView()) == IDOK)	// throws exception if there is no default printer
		{
			// Zero and then initialize the members of a DOCINFO structure.
			DOCINFO di;
			memset(&di, 0, sizeof(DOCINFO));
			di.cbSize = sizeof(DOCINFO);
			di.lpszDocName = _T("Scribble Printout");
			di.lpszOutput = (LPTSTR)NULL;
			di.lpszDatatype = (LPTSTR)NULL;
			di.fwType = 0;

			// Begin a print job by calling the StartDoc function.
			CDC dcPrint = PrintDlg.GetPrinterDC();
			if (SP_ERROR == StartDoc(dcPrint, &di))
				throw CUserException(_T("Failed to start print job"));

			// Inform the driver that the application is about to begin sending data.
			if (0 > StartPage(dcPrint))
				throw CUserException(_T("StartPage failed"));

			BITMAPINFOHEADER bi;
			ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
			bi.biSize = sizeof(BITMAPINFOHEADER);
			bi.biHeight = Height;
			bi.biWidth = Width;
			bi.biPlanes = 1;
			bi.biBitCount = 24;
			bi.biCompression = BI_RGB;

			// Note: BITMAPINFO and BITMAPINFOHEADER are the same for 24 bit bitmaps
			// Get the size of the image data
			MemDC.GetDIBits(bmView, 0, Height, NULL, reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS);

			// Retrieve the image data
			std::vector<byte> vBits(bi.biSizeImage, 0);	// a vector to hold the byte array
			byte* pByteArray = &vBits.front();
			MemDC.GetDIBits(bmView, 0, Height, pByteArray, reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS);

			// Determine the scaling factors required to print the bitmap and retain its original proportions.
			float fLogPelsX1 = (float)ViewDC.GetDeviceCaps(LOGPIXELSX);
			float fLogPelsY1 = (float)ViewDC.GetDeviceCaps(LOGPIXELSY);
			float fLogPelsX2 = (float)GetDeviceCaps(dcPrint, LOGPIXELSX);
			float fLogPelsY2 = (float)GetDeviceCaps(dcPrint, LOGPIXELSY);
			float fScaleX = MAX(fLogPelsX1, fLogPelsX2) / MIN(fLogPelsX1, fLogPelsX2);
			float fScaleY = MAX(fLogPelsY1, fLogPelsY2) / MIN(fLogPelsY1, fLogPelsY2);

			// Compute the coordinates of the upper left corner of the centered bitmap.
			int cWidthPels = GetDeviceCaps(dcPrint, HORZRES);
			int xLeft = ((cWidthPels / 2) - ((int)(((float)Width) * fScaleX)) / 2);
			int cHeightPels = GetDeviceCaps(dcPrint, VERTRES);
			int yTop = ((cHeightPels / 2) - ((int)(((float)Height) * fScaleY)) / 2);

			// Use StretchDIBits to scale the bitmap and maintain its original proportions
			if (GDI_ERROR == (UINT)StretchDIBits(dcPrint, xLeft, yTop, (int)((float)Width * fScaleX),
				(int)((float)Height * fScaleY), 0, 0, Width, Height, pByteArray, reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS, SRCCOPY))
			{
				throw CUserException(_T("Failed to resize image for printing"));
			}

			// Inform the driver that the page is finished.
			if (0 > EndPage(dcPrint))
				throw CUserException(_T("EndPage failed"));

			// Inform the driver that document has ended.
			if (0 > EndDoc(dcPrint))
				throw CUserException(_T("EndDoc failed"));
		}
	}

	catch (const CException& e)
	{
		// Display a message box indicating why printing failed.
		CString strMsg = CString(e.GetText()) + CString("\n") + e.GetErrorString();
		CString strType = CString(e.what());
		::MessageBox(NULL, strMsg, strType, MB_ICONWARNING);
	}

}
Beispiel #6
0
//***********************************************************************************************************
BOOL CBCGPBaseVisualCtrl::DoPrint(CDC* pDCIn, CPrintInfo* pInfo)
{
	CObject* pBaseVisual = GetVisualBaseObject();
	if (pBaseVisual == NULL)
	{
		return FALSE;
	}

	CBCGPBaseVisualObject* pVisualObject = DYNAMIC_DOWNCAST(CBCGPBaseVisualObject, pBaseVisual);
	CBCGPVisualContainer* pVisualContainer = DYNAMIC_DOWNCAST(CBCGPVisualContainer, pBaseVisual);

	if (pVisualObject == NULL && pVisualContainer == NULL)
	{
		return FALSE;
	}

	CBCGPGraphicsManager* pGM = GetGraphicsManager();
	if (pGM == NULL)
	{
		return FALSE;
	}

	ASSERT_VALID(pGM);

	CDC* pDC = pDCIn;
	CPrintDialog* pPrintDlg = NULL;

	if (pDC == NULL)
	{
		pPrintDlg = new CPrintDialog(FALSE);
		
		if (pPrintDlg->DoModal() == IDCANCEL)
		{
			delete pPrintDlg;
			return FALSE;
		}

		pDC = CDC::FromHandle(pPrintDlg->GetPrinterDC());
		pDC->m_bPrinting = TRUE;
		
		CString strTitle;
		strTitle.LoadString(AFX_IDS_APP_TITLE);
		
		DOCINFO di;
		ZeroMemory(&di, sizeof (DOCINFO));
		di.cbSize = sizeof (DOCINFO);
		di.lpszDocName = strTitle;
		
		if (!pDC->StartDoc(&di))
		{	
			pDC->AbortDoc();
			delete pPrintDlg;
			return FALSE;
		}

		pInfo = new CPrintInfo();
		pInfo->m_rectDraw.SetRect(0,0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
	}

	CSize size(pInfo->m_rectDraw.Size());
	CBCGPRect rect(CBCGPPoint(), size);
	CBCGPRect rectControl(pVisualObject != NULL ? pVisualObject->GetRect() : pVisualContainer->GetRect());

	CBCGPSize sizeScaleRatio((double)size.cx / rectControl.Width(), (double)size.cy / rectControl.Height());

	double dAspect = min(sizeScaleRatio.cx, sizeScaleRatio.cy);
	sizeScaleRatio.cx = sizeScaleRatio.cy = dAspect;

	size.cx = bcg_clamp((int)(rectControl.Width() * dAspect), 0, size.cx);
	size.cy = bcg_clamp((int)(rectControl.Height() * dAspect), 0, size.cy);
	
	rect.SetSize(size);

	CDC	dcPrint;
	CBitmap	bmpPrint;
	CBitmap* pBmpPrintOld = NULL;
	CDC* pDCOut = NULL;

	CBrush brWhite(RGB(255, 255, 255));

	if (DYNAMIC_DOWNCAST(CBCGPGraphicsManagerGDI, pGM) != NULL)
	{
		dcPrint.CreateCompatibleDC(NULL);
		bmpPrint.Attach(CBCGPDrawManager::CreateBitmap_32(size, NULL));
		
		pBmpPrintOld = dcPrint.SelectObject (&bmpPrint);
		ASSERT(pBmpPrintOld != NULL);

		pDCOut = &dcPrint;
	}
	else
	{
		pGM->SetPrintInfo(pInfo);
		pDCOut = pDC;
	}

	pDCOut->FillRect((CRect)rect, &brWhite);
	pGM->BindDC(pDCOut);

	if (pGM->IsBindDCFailed())
	{
		pDCOut->FillRect((CRect)rect, &brWhite);
		pDCOut->TextOut(0, 0, _T("Out of memory"));
	}
	else
	{
		pGM->BeginDraw();

		CBCGPSize sizeScaleRatioOld;
		
		if (pVisualObject != NULL)
		{
			sizeScaleRatioOld = pVisualObject->GetScaleRatio();
			pVisualObject->SetScaleRatio(sizeScaleRatio);
			pVisualObject->SetRect(rect);
		}
		else
		{
			sizeScaleRatioOld = pVisualContainer->GetScaleRatio();
			pVisualContainer->SetScaleRatio(sizeScaleRatio);
			pVisualContainer->SetRect(rect);
		}

		pGM->Clear();

		if (pVisualObject != NULL)
		{
			pVisualObject->OnDraw (pGM, rect);
		}
		else
		{
			pVisualContainer->OnDraw (pGM, rect);
		}

		pGM->EndDraw();

		pGM->BindDC(NULL);

		if (pVisualObject != NULL)
		{
			pVisualObject->SetScaleRatio(sizeScaleRatioOld);
		}
		else
		{
			pVisualContainer->SetScaleRatio(sizeScaleRatioOld);
		}

		if (dcPrint.GetSafeHdc() != NULL)
		{
			CBCGPDrawManager::FillAlpha (rect, (HBITMAP)bmpPrint.GetSafeHandle (), 255);
		}
	}

	if (pVisualObject != NULL)
	{
		pVisualObject->SetRect(rectControl);
		pVisualObject->SetDirty ();
	}
	else
	{
		pVisualContainer->SetRect(rectControl);
		pVisualContainer->SetDirty ();
	}

	if (dcPrint.GetSafeHdc() != NULL)
	{
		BITMAP bmp = {0};
		bmpPrint.GetBitmap (&bmp);

		CRect rectOut(pInfo->m_rectDraw.TopLeft (), CSize(bmp.bmWidth, bmp.bmHeight));

		int mode = pDC->SetStretchBltMode(HALFTONE);

		pDC->BitBlt (rectOut.left, rectOut.top, rectOut.Width(), rectOut.Height(), &dcPrint, 0, 0, SRCCOPY);
		pDC->SetStretchBltMode(mode);

		dcPrint.SelectObject(pBmpPrintOld);
	}
	else
	{
		pGM->SetPrintInfo(NULL);
	}

	if (pPrintDlg != NULL)
	{
		pDC->EndDoc();
		delete pPrintDlg;
		delete pInfo;
	}

	return TRUE;
}
Beispiel #7
0
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;
}