📄 print.c
字号:
* Check if device supports the BANDINFO escape.
*/
nTemp = BANDINFO;
bBandInfoDevice = Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR
)&nTemp, NULL);
/*
* Do each band -- Call Escape() with NEXTBAND, then the
* rect structure returned is the area where we are to
* print in. This loop exits when the rect area is empty.
*/
while (Escape(hPrnDC, NEXTBAND, 0, NULL, (LPSTR)&rect) && !
IsRectEmpty(&rect))
{
char szTmpBuf[100];
/*
* Do the BANDINFO, if needed.
*/
if (bBandInfoDevice)
Escape(hPrnDC, BANDINFO, sizeof(BANDINFOSTRUCT), (LPSTR)&
biBandInfo, (LPSTR)&biBandInfo);
wsprintf(szTmpBuf, "Printing Band Number %d", ++nBandCount);
SetDlgItemText(hDlgAbort, IDC_PERCENTAGE, (LPSTR)szTmpBuf);
/*
* Call PrintBand() to do actual output into band.
* Pass in our band-info flags to tell what sort
* of data to output into the band. Note that on
* non-banding devices, we pass in the default bandinfo
* stuff set above (i.e. bText=TRUE, bGraphics=TRUE).
*/
wErrorCode = PrintBand(hPrnDC, &rPrintRect, &rect,
biBandInfo.bText, biBandInfo.bGraphics,
lpDIBHdr, lpBits);
}
}
else
{
/*
* Print the whole page -- non-banding device.
*/
rect = rPrintRect;
SetDlgItemText(hDlgAbort, IDC_PERCENTAGE, (LPSTR)
"Sending bitmap to printer...");
wErrorCode = PrintBand(hPrnDC, &rPrintRect, &rect, TRUE, TRUE,
lpDIBHdr, lpBits);
/*
* Non-banding devices need a NEWFRAME
*/
if (Escape(hPrnDC, NEWFRAME, 0, NULL, NULL) < 0)
return (ERR_NEWFRAME);
}
/*
* End the print operation. Only send the ENDDOC if
* we didn't abort or error.
*/
if (!bAbort)
{
if (Escape(hPrnDC, ENDDOC, 0, NULL, NULL) < 0)
{
/*
* We errored out on ENDDOC, but don't return here - we still
* need to close the dialog box, free proc instances, etc.
*/
wErrorCode = ERR_ENDDOC;
}
DestroyWindow(hDlgAbort);
}
/*
* All done, clean up.
*/
DeleteDC(hPrnDC);
}
else
wErrorCode = ERR_GETDC; // Couldn't get Printer DC!
GlobalUnlock(hDib);
return (wErrorCode);
}
// *******************************************************************
// Auxiliary Functions
// -- Local to this module only
// *******************************************************************
/*********************************************************************
*
* CalculatePrintRect()
*
* Given fPrintOpt and a size of the DIB, return the area on the
* printer where the image should go (in printer coordinates). If
* fPrintOpt is PW_SCALE, then lpPrintRect.left and .top should
* contain WORDs which specify the scaling factor for the X and
* Y directions, respecively.
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created based on DIBVIEW
*
********************************************************************/
void CalculatePrintRect(HDC hDC, // HDC to printer DC
LPRECT lpPrintRect, // Returned PrintRect
WORD fPrintOpt, // Options
DWORD cxDIB, // Size of DIB - x
DWORD cyDIB) // Size of DIB - y
{
int cxPage, cyPage, cxInch, cyInch;
if (!hDC)
return;
/*
* Get some info from printer driver
*/
cxPage = GetDeviceCaps(hDC, HORZRES); // Width of printr page - pixels
cyPage = GetDeviceCaps(hDC, VERTRES); // Height of printr page - pixels
cxInch = GetDeviceCaps(hDC, LOGPIXELSX); // Printer pixels per inch - X
cyInch = GetDeviceCaps(hDC, LOGPIXELSY); // Printer pixels per inch - Y
switch (fPrintOpt)
{
/*
* Best Fit case -- create a rectangle which preserves
* the DIB's aspect ratio, and fills the page horizontally.
*
* The formula in the "->bottom" field below calculates the Y
* position of the printed bitmap, based on the size of the
* bitmap, the width of the page, and the relative size of
* a printed pixel (cyInch / cxInch).
*/
case PW_BESTFIT:
lpPrintRect->top = 0;
lpPrintRect->left = 0;
lpPrintRect->bottom = (int)(((double)cyDIB * cxPage * cyInch) / ((double
)cxDIB * cxInch));
lpPrintRect->right = cxPage;
break;
/*
* Scaling option -- lpPrintRect's top/left contain
* multipliers to multiply the DIB's height/width by.
*/
case PW_SCALE:
{
int cxMult, cyMult;
cxMult = lpPrintRect->left;
cyMult = lpPrintRect->top;
lpPrintRect->top = 0;
lpPrintRect->left = 0;
lpPrintRect->bottom = (int)(cyDIB * cyMult);
lpPrintRect->right = (int)(cxDIB * cxMult);
}
break;
/*
* Stretch To Page case -- create a rectangle
* which covers the entire printing page (note that this
* is also the default).
*/
case PW_STRETCHTOPAGE:
default:
lpPrintRect->top = 0;
lpPrintRect->left = 0;
lpPrintRect->bottom = cyPage;
lpPrintRect->right = cxPage;
break;
}
}
/*********************************************************************
*
* PrintBand()
*
* This routine does ALL output to the printer. It is called from
* the PrintDIB() routine. It is called for both banding and non-
* banding printing devices. lpRectClip contains the rectangular
* area we should do our output into (i.e. we should clip our output
* to this area). The flags fDoText and fDoGraphics should be set
* appropriately (if we want any text output to the rectangle, set
* fDoText to true). Normally these flags are returned on banding
* devices which support the BANDINFO escape.
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created based on DIBVIEW
*
********************************************************************/
WORD PrintBand(HDC hDC, // Handle to the Printer DC
LPRECT lpRectOut, // Rect where entire DIB is to go
LPRECT lpRectClip, // Clippping rect where this portion goes
BOOL fDoText, // TRUE if this band is for text
BOOL fDoGraphics, // TRUE if this band is for graphics
LPBITMAPINFOHEADER lpDIBHdr, // Pointer to DIB header
LPSTR lpDIBBits) // Pointer to DIB bits
{
RECT rect; // Temporary rectangle
double dblXScaling, // X and Y scaling factors
dblYScaling;
WORD wReturn = 0; // Return code
if (fDoGraphics)
{
dblXScaling = ((double)lpRectOut->right - lpRectOut->left) / (double)
lpDIBHdr->biWidth;
dblYScaling = ((double)lpRectOut->bottom - lpRectOut->top) / (double)
lpDIBHdr->biHeight;
/*
* Now we set up a temporary rectangle -- this rectangle
* holds the coordinates on the paper where our bitmap
* WILL be output. We can intersect this rectangle with
* the lpClipRect to see what we NEED to output to this
* band. Then, we determine the coordinates in the DIB
* to which this rectangle corresponds (using dbl?Scaling).
*/
IntersectRect(&rect, lpRectOut, lpRectClip);
if (!IsRectEmpty(&rect))
{
RECT rectIn;
rectIn.left = (int)((rect.left - lpRectOut->left) / dblXScaling + 0.5
);
rectIn.top = (int)((rect.top - lpRectOut->top) / dblYScaling + 0.5);
rectIn.right = (int)(rectIn.left + (rect.right - rect.left) /
dblXScaling + 0.5);
rectIn.bottom = (int)(rectIn.top + (rect.bottom - rect.top) /
dblYScaling + 0.5);
if (!StretchDIBits(hDC, // DestDC
rect.left, // DestX
rect.top, // DestY
rect.right - rect.left, // DestWidth
rect.bottom - rect.top, // DestHeight
rectIn.left, // SrcX
(int)(lpDIBHdr->biHeight) - // SrcY
rectIn.top - (rectIn.bottom - rectIn.top),
rectIn.right - rectIn.left, // SrcWidth
rectIn.bottom - rectIn.top, // SrcHeight
lpDIBBits, // lpBits
(LPBITMAPINFO)lpDIBHdr, // lpBitInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY)) // dwROP
wReturn = ERR_STRETCHDIBITS; // StretchDIBits() failed!
}
}
return wReturn;
}
/***********************************************************************
*
* GetPrinterDC()
*
* Return a DC to the currently selected printer.
* Returns NULL on error.
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created based on DIBVIEW
*
***********************************************************************/
HDC GetPrinterDC(void)
{
static char szPrinter[64];
char *szDevice, *szDriver, *szOutput;
GetProfileString("windows", "device", "", szPrinter, 64);
if ((szDevice = strtok(szPrinter, ",")) && (szDriver = strtok(NULL, ", "))
&& (szOutput = strtok(NULL, ", ")))
{
lstrcpy((LPSTR)gszDevice, (LPSTR)szDevice); // Copy to global variables
lstrcpy((LPSTR)gszOutput, (LPSTR)szOutput);
return CreateDC(szDriver, szDevice, szOutput, NULL);
}
return NULL;
}
/**********************************************************************
* PrintAbortProc()
*
* Abort procedure - contains the message loop while printing is
* in progress. By using a PeekMessage() loop, multitasking
* can occur during printing.
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created
*
**********************************************************************/
BOOL FAR PASCAL PrintAbortProc(HDC hDC, short code)
{
MSG msg;
while (!bAbort && PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
if (!IsDialogMessage(hDlgAbort, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (!bAbort);
}
/***********************************************************************
*
* PrintAbortDlg()
*
*
* This is the Dialog Procedure which will handle the "Now Printing"
* dialog box. When the user presses the "Cancel" button, the
* global variable bAbort is set to TRUE, which causes the
* PrintAbortProc to exit, which in turn causes the printing
* operation to terminate.
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created
*
***********************************************************************/
int FAR PASCAL PrintAbortDlg(HWND hWnd, /* Handle to dialog box */ unsigned
msg, /* Message */ WORD wParam, LONG lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
char szBuffer[100];
/*
* Fill in the text which specifies where this bitmap
* is going ("on HP LaserJet on LPT1", for example)
*/
wsprintf(szBuffer, "on %s on %s", (LPSTR)gszDevice, (LPSTR)gszOutput);
SetDlgItemText(hWnd, IDC_PRINTTEXT2, (LPSTR)szBuffer);
SetFocus(GetDlgItem(hWnd, IDCANCEL));
}
return TRUE; // Return TRUE because we called SetFocus()
case WM_COMMAND:
bAbort = TRUE;
DestroyWindow(hWnd);
return TRUE;
break;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -