|
-
April 15th, 2004, 08:03 AM
#1
BIG BIG Printer Problem
Hi,
I cannot get it work right for a week and I am about to lost the hope that it can work somehow. Here, I try to put as much info as possible, so perhaps someone can help.
The main problem is that printing works fine on one of the printers I am using but prints extremely large or small output on other units. The problem must be with calculation of the coordinates, I think. Here you are code snippets of what I do.
Code:
// Count vertical lines
int PrintLineCounter = 0;
// Create the print dialog
CPrintDialog PrintDialog(FALSE, PD_ALLPAGES);
if (PrintDialog.DoModal() != IDOK) {
return;
}
// Get Printer DC
HDC hdcPrinter = PrintDialog.GetPrinterDC();
if (hdcPrinter == NULL) {
return;
}
// Print on A4 only
DEVMODE *pDevMode = PrintDialog.GetDevMode();
if (((CString)A2CW("A4")).Compare(pDevMode->dmFormName) != 0) {
return;
}
// Attach to HDC
CDC dcPrinter;
dcPrinter.Attach(hdcPrinter);
// Get printer size in pixels.
// I saw references to that in posts here, took this routine from another website trusting that it works. Perhaps this fails? I include down there, together with CreateFontSize
CRect PrintArea = UserPage(&dcPrinter, 0.5);
// Font sizing is not my own, too
FontSize4 = CreateFontSize(&dcPrinter, 4);
FontSize8 = CreateFontSize(&dcPrinter, 6);
// Create fonts using the calculated sizes
FontCourier4Underline.CreateFont(FontSize4, 0, 0, 0, FW_NORMAL, 0, TRUE, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_CHARACTER_PRECIS, PROOF_QUALITY, FIXED_PITCH, A2CW("Courier New"));
FontCourier4.CreateFont(FontSize4, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_CHARACTER_PRECIS, PROOF_QUALITY, FIXED_PITCH, A2CW("Courier New"));
FontCourier8Bold.CreateFont(FontSize8, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_CHARACTER_PRECIS, PROOF_QUALITY, FIXED_PITCH, A2CW("Courier New"));
// call StartDoc() to begin printing
DOCINFO docinfo;
memset(&docinfo, 0, sizeof(docinfo));
docinfo.cbSize = sizeof(docinfo);
docinfo.lpszOutput = NULL;
docinfo.lpszDocName = A2CW("Order");
// If document start fails, no printing
if (dcPrinter.StartDoc(&docinfo) < 0) {
dcPrinter.Detach();
return;
}
// First page start
if (dcPrinter.StartPage() < 0) {
dcPrinter.AbortDoc();
return;
}
// Set coordinates to be right and down increasing, based on pixels
SetMapMode(hdcPrinter, MM_TEXT);
// Set printer font
CFont *pOldFont = dcPrinter.SelectObject(&FontCourier4);
// Draw a horizontal line
dcPrinter.Rectangle(PrintArea.left, (PrintLineCounter * (FontSize4 + 1)) + (FontSize4 / 2), PrintArea.right, (PrintLineCounter++ * (FontSize4 + 1)) + (FontSize4 / 2) + 1);
// Print some text
dcPrinter.TextOut(PrintArea.left, PrintLineCounter++ * (FontSize4 + 1), "Gurus, where are you?");
// Draw an additional horizontal line
dcPrinter.Rectangle(PrintArea.left, (PrintLineCounter * (FontSize4 + 1)) + (FontSize4 / 2), PrintArea.right, (PrintLineCounter++ * (FontSize4 + 1)) + (FontSize4 / 2) + 1);
// Print some more text
dcPrinter.TextOut(PrintArea.left, PrintLineCounter++ * (FontSize4 + 1), "I hope close");
// Print something to the middle of the page. Different font sizes lead to the conclusion to count vertical and horizontal points rather than rows and columns
dcPrinter.SelectObject(&FontCourier8Bold);
CSize Size = dcPrinter.GetTextExtent("CENTER");
dcPrinter.TextOut(PrintArea.left + ((PrintArea.right - PrintArea.left) / 2) - (Size.cx / 2), PrintArea.top, "CENTER");
// End of page
dcPrinter.EndPage();
// Send end document
dcPrinter.EndDoc();
// Restore font
dcPrinter.SelectObject(pOldFont);
// Cleanup
dcPrinter.Detach();
CDC::FromHandle(hdcPrinter)->DeleteDC();
The question can come easily, how do I know the width and the height of a page. I took a dirty approach, set font printed a full page with given margin and counted. I was in the hope that if CreateFontSize work really appropriately then same number of characters fit on page at each density.
But... something goes wrong. How can the size of a printing page and required font size calculated appropriately? I do not seek a miracle, just I would like to have the same printout from a CDialog based application on all printers... That should be some basic thing to do. Eh, eh, eh. I am very sad now. And did not even consider drawing boxes, putting pictures.
Code:
CRect COrderDialog::UserPage(CDC * pDC, float margin)
{
// This function returns the area in device units to be used to
// prints a page with a true boarder of "margin".
//
// You could use individual margins for each edge
// and apply below as needed.
//
// Set Map Mode - We do not want device units
// due to lack of consistency.
// If you do not use TWIPS you will have to change
// the scaling factor below.
int OriginalMapMode = pDC->SetMapMode(MM_TWIPS);
// Variable needed to store printer info.
CSize PrintOffset,Physical,Printable;
// This gets the Physical size of the page in Device Units
Physical.cx = pDC->GetDeviceCaps(PHYSICALWIDTH);
Physical.cy = pDC->GetDeviceCaps(PHYSICALHEIGHT);
// convert to logical
pDC->DPtoLP(&Physical);
// This gets the offset of the printable area from the
// top corner of the page in Device Units
PrintOffset.cx = pDC->GetDeviceCaps(PHYSICALOFFSETX);
PrintOffset.cy = pDC->GetDeviceCaps(PHYSICALOFFSETY);
// convert to logical
pDC->DPtoLP(&PrintOffset);
// Set Page scale to TWIPS, Which is 1440 per inch,
// Zero/Zero is the upper left corner
// Get Printable Page Size (This is in MM!) so convert to twips.
Printable.cx = (int)((float)pDC->GetDeviceCaps(HORZSIZE)*56.69);
Printable.cy = (int)((float)pDC->GetDeviceCaps(VERTSIZE)*56.69);
// Positive X -> RIGHT
// Positive Y -> UP
// Ref Zero is upper left corner
int inch = 1440; // Scaling Factor Inches to TWIPS
int Dx1, Dx2, Dy1, Dy2; // Distance printable area is from edge of paper
Dx1 = PrintOffset.cx;
Dy1 = PrintOffset.cy;
// calculate remaining borders
Dy2 = Physical.cy-Printable.cy-Dy1;
Dx2 = Physical.cx-Printable.cx-Dx1;
//
// Define the User Area's location
CRect PageArea;
PageArea.left = (long)(margin*inch-Dx1);
PageArea.right = (long)(Printable.cx-margin*inch+Dx2);
PageArea.top = (int)-(margin*inch-Dy1); // My scale is inverted for y
PageArea.bottom = (int)-(Printable.cy-margin*inch+Dy2);
// now put back to device units to return to the program.
pDC->LPtoDP(&PageArea);
//
// return
return PageArea;
}
// Input: pointer to device context for printer
// Input: desired point size of font (in points).
// Output: integer height to send to CreateFont function.
int COrderDialog::CreateFontSize(CDC *pdc, int points)
{
// This will calculate the font size for the printer that is specified
// by a point size.
//
// if points is:
// (-) negative uses height as value for Net Font Height
// (ie. point size)
// (+) positive height is Total Height plus Leading Height!
CSize size;
int perinch = pdc->GetDeviceCaps(LOGPIXELSY);
size.cx = size.cy = (perinch*points)/72;
pdc->DPtoLP(&size);
return size.cy;
}
-
April 15th, 2004, 10:00 AM
#2
Try to set the mapping mode BEFORE you call CreateFontSize(). perhaps that helps...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|