📄 print.c
字号:
//********************************************************************
//
// print.c
//
// Source file for Device-Independent Bitmap (DIB) API. Provides
// the following functions:
//
// PrintWindow() - Prints all or part of a window
// PrintScreen() - Prints the entire screen
// PrintDIB() - Prints the specified DIB
//
// Development Team: Mark Bader
// Patrick Schreiber
// Garrett McAuliffe
// Eric Flo
// Tony Claflin
// Dan Ruder
//
// Written by Microsoft Product Support Services, Developer Support.
// COPYRIGHT:
//
// (C) Copyright Microsoft Corp. 1993. All rights reserved.
//
// You have a royalty-free right to use, modify, reproduce and
// distribute the Sample Files (and/or any modified version) in
// any way you find useful, provided that you agree that
// Microsoft has no warranty obligations or liability for any
// Sample Application Files which are modified.
//
//********************************************************************
#include <windows.h>
#include <string.h>
#include "dibdll.h" // Header for printing dialog & DLL instance handle
#include "dibapi.h" // Header for DIB functions
#include "dibutil.h" // Auxiliary functions
HANDLE ghDLLInst; // Global handle to DLL's instance
/***************************************************************
* Typedefs
**************************************************************/
/* Structure used for Banding */
typedef struct
{
BOOL bGraphics;
BOOL bText;
RECT GraphicsRect;
} BANDINFOSTRUCT;
/****************************************************************
* Variables
***************************************************************/
HWND hDlgAbort; // Handle to Abort Dialog
char szPrintDlg[] = "Printing"; // Name of Print dialog from .RC
BOOL bAbort = FALSE; // Abort a print operation?
char gszDevice[50]; // Keeps track out device (e.g. "HP LaserJet")
char gszOutput[50]; // Output device (e.g. "LPT1:")
/***************************************************************
* Function prototypes for functions local to this module
**************************************************************/
BOOL FAR PASCAL PrintAbortProc(HDC, short);
int FAR PASCAL PrintAbortDlg(HWND, unsigned, WORD, LONG);
WORD PrintBand(HDC, LPRECT, LPRECT, BOOL, BOOL, LPBITMAPINFOHEADER, LPSTR);
HDC GetPrinterDC(void);
void CalculatePrintRect(HDC, LPRECT, WORD, DWORD, DWORD);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpvReserved )
{
if (fdwReason==DLL_PROCESS_ATTACH) ghDLLInst=hinstDLL;
return TRUE;
}
/**********************************************************************
*
* PrintWindow()
*
*
* Description:
*
* This function prints the specified window on the default
* printer.
*
* Parameters:
*
* HWND hWnd - Specifies the window to print. The window must
* not be iconic and must be topmost on the display.
*
* WORD fPrintArea - Specifies the area of the window to print. Must be
* one of PW_ALL, PW_CLIENT, PW_CAPTION, or PW_MENUBAR
*
* WORD fPrintOpt - Print options (one of PW_BESTFIT, PW_STRETCHTOPAGE, or
* PW_SCALE)
*
* WORD wXScale, wYScale - X and Y scaling factors if PW_SCALE is specified
*
* LPSTR szJobName - Name that you would like to give to this print job (this
* name shows up in the Print Manager as well as the
* "Now Printing..." dialog box).
* Return Value:
* ERR_DIBFUNCTION or any return value from PrintDIB
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created
*
**********************************************************************/
WORD FAR PrintWindow(HWND hWnd, // Window to be printed
WORD fPrintArea, // Area of window to be printed
WORD fPrintOpt, // Print options
WORD wXScale, // X Scaling factor if PW_SCALE is used
WORD wYScale, // Y Scaling factor if PW_SCALE is used
LPSTR szJobName) // Name of print job
{
HDIB hDib; // Handle to the DIB
WORD wReturn; // our return value
/*
* Parameter validation
*/
if (!hWnd)
return (ERR_INVALIDHANDLE); // Invalid Window
/*
* Copy the Window to a DIB and print it.
*/
hDib = CopyWindowToDIB(hWnd, fPrintArea);
if (!hDib)
return (ERR_DIBFUNCTION); // CopyWindowToDIB failed!
wReturn = PrintDIB(hDib, fPrintOpt, wXScale, wYScale, szJobName);
/*
* Call DestroyDIB to free the memory the dib takes up.
*/
DestroyDIB(hDib);
return wReturn; // return the value from PrintDIB
}
/**********************************************************************
*
* PrintScreen()
*
*
* Description:
*
* This function prints the specified portion of the display screen on the
* default printer using the print options specified. The print
* options are listed in dibapi.h.
*
* Parameters:
*
* LPRECT rRegion - Specifies the region of the screen (in screen
* coordinates) to print
*
* WORD fPrintOpt - Print options (PW_BESTFIT, PW_STRETCHTOPAGE, or PW_SCALE)
*
* WORD wXScale, wYScale - X and Y scaling factors if PW_SCALE is specified
*
* LPSTR szJobName - Name that you would like to give to this print job (this
* name shows up in the Print Manager as well as the
* "Now Printing..." dialog box).
*
* Return Value:
* ERR_DIBFUNCTION or any return value from PrintDIB
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created
*
**********************************************************************/
WORD FAR PrintScreen(LPRECT rRegion, // Region to print (in screen coords)
WORD fPrintOpt, // print options
WORD wXScale, // X scaling (used if PW_SCALE specified)
WORD wYScale, // Y scaling (used if PW_SCALE specified)
LPSTR szJobName) // Name of print job
{
HDIB hDib; // A Handle to our DIB
WORD wReturn; // Return value
/*
* Copy the screen contained in the specified rectangle to a DIB
*/
hDib = CopyScreenToDIB(rRegion);
if (!hDib)
return (ERR_DIBFUNCTION); // CopyScreenToDIB failed!
wReturn = PrintDIB(hDib, fPrintOpt, wXScale, wYScale, szJobName);
DestroyDIB(hDib);
return wReturn; // Return the value that PrintDIB returned
}
/**********************************************************************
*
* PrintDIB()
*
* Description:
*
* This routine prints the specified DIB. The actual printing is done
* in the PrintBand() routine (see below), this procedure drives the
* printing operation. PrintDIB() has the code to handle both banding
* and non-banding printers. A banding printer can be distinguished by
* the GetDeviceCaps() API (see the code below). On banding devices,
* must repeatedly call the NEXTBAND escape to get the next banding
* rectangle to print into. If the device supports the BANDINFO escape,
* it should be used to determine whether the band "wants" text or
* graphics (or both). On non-banding devices, we can ignore all this
* and call PrintBand() on the entire page.
*
* Parameters:
*
* HDIB hDib - Handle to dib to be printed
*
* WORD fPrintOpt - tells which print option to use (PW_BESTFIT,
* PW_STRETCHTOPAGE, OR PW_SCALE)
*
* WORD wXScale, wYScale - X and Y scaling factors (integers) for
* printed output if the PW_SCALE option is used.
*
* LPSTR szJobName - Name that you would like to give to this print job (this
* name shows up in the Print Manager as well as the
* "Now Printing..." dialog box).
*
* Return Value: (see errors.h for description)
*
* One of: ERR_INVALIDHANDLE
* ERR_LOCK
* ERR_SETABORTPROC
* ERR_STARTDOC
* ERR_NEWFRAME
* ERR_ENDDOC
* ERR_GETDC
* ERR_STRETCHDIBITS
*
* History:
*
* Date Author Reason
* 9/15/91 Mark Bader Created, based on DIBVIEW's DibPrint()
*
********************************************************************/
WORD FAR PrintDIB(HDIB hDib, // Handle to the DIB
WORD fPrintOpt, // Print Options
WORD wXScale, // X Scaling factor
WORD wYScale, // Y Scaling factor
LPSTR szJobName) // Name of print job
{
HDC hPrnDC; // DC to the printer
RECT rect; // Rect structure used for banding
BANDINFOSTRUCT biBandInfo; // Used for banding
int nTemp; // Temp number used to check banding capability
LPSTR lpBits; // pointer to the DIB bits
LPBITMAPINFOHEADER lpDIBHdr; // Pointer to DIB header
int nBandCount = 0; // used for print dialog box to count bands
WORD wErrorCode = 0; // Error code to return
RECT rPrintRect; // Rect which specifies the area on the printer
// (in printer coordinates) which we
// want the DIB to go to
char szBuffer[70]; // Buffer to hold message for "Printing" dlg box
char szJobNameTrunc[35]; // szJobName truncated to 31 characters, since
// STARTDOC can't accept a string longer than 31
/*
* Paramter validation
*/
if (!hDib)
return (ERR_INVALIDHANDLE);
/*
* Get pointer to DIB header
*/
lpDIBHdr = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (!lpDIBHdr) // Check that we have a valid pointer
return (ERR_LOCK);
lpBits = FindDIBBits((LPSTR)lpDIBHdr); // Find pointer to DIB bits
if (hPrnDC = GetPrinterDC())
{
SetStretchBltMode(hPrnDC, COLORONCOLOR);
/*
* Determine rPrintRect (printer area to print to) from the
* fPrintOpt. Fill in rPrintRect.left and .top from wXScale and
* wYScale just in case we use PW_SCALE (see the function
* CalculatePrintRect).
*/
rPrintRect.left = wXScale;
rPrintRect.top = wYScale;
CalculatePrintRect(hPrnDC, &rPrintRect, fPrintOpt, lpDIBHdr->biWidth,
lpDIBHdr->biHeight);
/*
* Initialize the abort procedure.
*/
hDlgAbort = CreateDialog(ghDLLInst, szPrintDlg, GetFocus(), PrintAbortDlg);
/*
* Set the text inside the dialog to the name of our print job
*/
lstrcpy(szJobNameTrunc, szJobName);
szJobNameTrunc[31] = '\0'; // Truncate string to 31 chars
wsprintf(szBuffer, "Printing '%s'", (LPSTR)szJobNameTrunc);
SetDlgItemText(hDlgAbort, IDC_PRINTTEXT1, (LPSTR)szBuffer);
/*
* Set global variable bAbort to FALSE. This will get set to TRUE
* in our PrintAbortDlg() procedure if the user selects the
* CANCEL button in our dialog box
*/
bAbort = FALSE;
/*
* Call the Escape() which will set up the Abort Procedure
*/
if (Escape(hPrnDC, SETABORTPROC, 0, (LPSTR)PrintAbortProc, NULL
) < 0)
return (ERR_SETABORTPROC);
/*
* Call Escape() with STARTDOC -- starts print job
*/
if (Escape(hPrnDC, STARTDOC, lstrlen((LPSTR)szJobNameTrunc), (LPSTR)
szJobNameTrunc, NULL) < 0)
{
// Oops, something happened, let's clean up here and return
DestroyWindow(hDlgAbort); // Remove abort dialog box
DeleteDC(hPrnDC);
GlobalUnlock(hDib);
return (ERR_STARTDOC);
}
/*
* Fill in initial values for our BandInfo Structure to
* tell driver we can want to do graphics and text, and
* also which area we want the graphics to go in.
*/
biBandInfo.bGraphics = TRUE;
biBandInfo.bText = TRUE;
biBandInfo.GraphicsRect = rPrintRect;
/*
* Check if need to do banding. If we do, loop through
* each band in the page, calling NEXTBAND and BANDINFO
* (if supported) calling PrintBand() on the band. Else,
* call PrintBand() with the entire page as our clipping
* rectangle!
*/
nTemp = NEXTBAND;
if (Escape(hPrnDC, QUERYESCSUPPORT, sizeof(int), (LPSTR)&nTemp, NULL))
{
BOOL bBandInfoDevice;
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -