📄 print.cpp
字号:
/*
* PRINT.CPP
* Patron Chapter 22
*
* Implementation of printing functions for both CPatronDoc
* and CPages classes. These functions are here to keep clutter
* down in document.cpp and pages.cpp.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "patron.h"
static HWND g_hDlgPrint=NULL;
static BOOL g_fCancelPrint=FALSE;
/*
* CPatronDoc::Print
*
* Purpose:
* Prints the current document.
*
* Parameters:
* hWndFrame HWND of the frame to use for dialog parents.
*
* Return Value:
* BOOL TRUE if printing happened, FALSE if it didn't
* start or didn't complete.
*/
BOOL CPatronDoc::Print(HWND hWndFrame)
{
PRINTDLG pd;
BOOL fSuccess;
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize=sizeof(PRINTDLG);
pd.hwndOwner =hWndFrame;
pd.nCopies =1;
pd.nFromPage =(USHORT)-1;
pd.nToPage =(USHORT)-1;
pd.nMinPage =1;
pd.nMaxPage =m_pPG->NumPagesGet();
pd.lpfnPrintHook=PrintDlgHook;
//Get the current document printer settings
pd.hDevMode=m_pPG->DevModeGet();
pd.Flags=PD_RETURNDC | PD_ALLPAGES | PD_COLLATE
| PD_HIDEPRINTTOFILE | PD_NOSELECTION | PD_ENABLEPRINTHOOK;
if (!PrintDlg(&pd))
return FALSE;
if (NULL!=pd.hDevMode)
GlobalFree(pd.hDevMode);
if (NULL!=pd.hDevNames)
GlobalFree(pd.hDevNames);
//Go do the actual printing.
fSuccess=m_pPG->Print(pd.hDC, PSZ(IDS_DOCUMENTNAME), pd.Flags
, pd.nFromPage, pd.nToPage, pd.nCopies);
if (!fSuccess)
{
MessageBox(m_hWnd, PSZ(IDS_PRINTERROR)
, PSZ(IDS_DOCUMENTCAPTION), MB_OK);
}
return fSuccess;
}
/*
* CPatronDoc::PrinterSetup
*
* Purpose:
* Selects a new printer and options for this document.
*
* Parameters:
* hWndFrame HWND of the frame to use for dialog parents.
* fDefault BOOL to avoid any dialog and just use the
* default.
*
* Return Value:
* UINT Undefined
*/
UINT CPatronDoc::PrinterSetup(HWND hWndFrame, BOOL fDefault)
{
PRINTDLG pd;
//Attempt to get printer metrics for the default printer.
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize=sizeof(PRINTDLG);
if (fDefault)
pd.Flags=PD_RETURNDEFAULT;
else
{
pd.hwndOwner=hWndFrame;
pd.Flags=PD_PRINTSETUP;
//Get the current document printer settings
pd.hDevMode=m_pPG->DevModeGet();
}
if (!PrintDlg(&pd))
return FALSE;
if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
{
GlobalFree(pd.hDevNames);
GlobalFree(pd.hDevMode);
return FALSE;
}
FDirtySet(TRUE);
return 1;
}
/*
* PrintDlgHook
*
* Purpose:
* Callback hook for the Print Dialog so we can hide the Setup
* button. Patron only allows Setup before anything exists on
* the page, and is not written to handle setup at Print time.
*/
UINT CALLBACK PrintDlgHook(HWND hDlg, UINT iMsg, WPARAM wParam
, LPARAM lParam)
{
if (WM_INITDIALOG==iMsg)
{
HWND hWnd;
hWnd=GetDlgItem(hDlg, psh1);
ShowWindow(hWnd, SW_HIDE);
return TRUE;
}
return FALSE;
}
/*
* CPatronDoc::FQueryPrinterSetup
*
* Purpose:
* Returns whether or not the Printer Setup menu item can be
* enabled. Once you create a tenant in any page, Printer Setup
* is voided simply to keep this sample simple, that is, we don't
* have to worry about reorganizing potentially large amounts
* of layout after we start plopping down objects.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE to enable the menu, FALSE otherwise.
*/
BOOL CPatronDoc::FQueryPrinterSetup(void)
{
return m_fPrintSetup;
}
/*
* CPages::DevModeSet
*
* Purpose:
* Provides the Pages with the current printer information.
*
* Parameters:
* hDevMode HGLOBAL to the memory containing the DEVMODE.
* This function assumes responsibility for this
* handle.
* hDevNames HGLOBAL providing the driver name and device
* name from which we can create a DC for
* information.
*
* Return Value:
* BOOL TRUE if we could accept this configuration,
* FALSE otherwise. If we return TRUE we also
* delete the old memory we hold.
*/
BOOL CPages::DevModeSet(HGLOBAL hDevMode, HGLOBAL hDevNames)
{
LPDEVNAMES pdn;
LPTSTR psz;
HGLOBAL hMem;
PDEVICECONFIG pdc;
LPDEVMODE pdm;
LPSTREAM pIStream;
HRESULT hr;
ULONG cbDevMode, cbWrite;
BOOL fRet=FALSE;
if (NULL==hDevMode || NULL==hDevNames)
return FALSE;
hr=m_pIStorage->OpenStream(SZSTREAMDEVICECONFIG, 0, STGM_DIRECT
| STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
if (FAILED(hr))
return FALSE;
/*
* DEVMODE is variable length--total length in hDevMode, so the
* amount to write is that plus string space. We subtract
* sizeof(DEVMODE) as that is already included from GlobalSize.
*/
cbDevMode=GlobalSize(hDevMode);
cbWrite=cbDevMode+sizeof(DEVICECONFIG)-sizeof(DEVMODE);
hMem=GlobalAlloc(GHND, cbWrite);
if (NULL==hMem)
{
pIStream->Release();
return FALSE;
}
pdc=(PDEVICECONFIG)GlobalLock(hMem); //This always works
pdm=(LPDEVMODE)GlobalLock(hDevMode); //This might not
if (NULL!=pdm)
{
pdc->cb=cbWrite;
pdc->cbDevMode=cbDevMode;
memcpy(&pdc->dm, pdm, (int)cbDevMode);
GlobalUnlock(hDevMode);
psz=(LPTSTR)GlobalLock(hDevNames);
if (NULL!=psz)
{
pdn=(LPDEVNAMES)psz;
lstrcpy(pdc->szDriver, psz+pdn->wDriverOffset);
lstrcpy(pdc->szDevice, psz+pdn->wDeviceOffset);
lstrcpy(pdc->szPort, psz+pdn->wOutputOffset);
pIStream->Write(pdc, cbWrite, &cbWrite);
GlobalUnlock(hDevNames);
fRet=TRUE;
}
}
GlobalUnlock(hMem);
GlobalFree(hMem);
pIStream->Release();
if (!fRet)
return FALSE;
GlobalFree(hDevNames);
GlobalFree(hDevMode);
return ConfigureForDevice();
}
/*
* CPages::DevModeGet
*
* Purpose:
* Retrieves a copy of the current DEVMODE structure for this
* Pages window. The caller is responsible for this memory.
*
* Parameters:
* None
*
* Return Value:
* HGLOBAL Handle to the memory containing the DEVMODE
* structure.
*/
HGLOBAL CPages::DevModeGet(void)
{
HGLOBAL hMem;
LPVOID pv;
ULONG cbDevMode, cbRead;
LARGE_INTEGER li;
LPSTREAM pIStream;
HRESULT hr;
hr=m_pIStorage->OpenStream(SZSTREAMDEVICECONFIG, 0, STGM_DIRECT
| STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
if (FAILED(hr))
return FALSE;
//Read how much to allocate for the DEVMODE structure
LISet32(li, CBSEEKOFFSETCBDEVMODE);
pIStream->Seek(li, STREAM_SEEK_SET, NULL);
pIStream->Read(&cbDevMode, sizeof(ULONG), &cbRead);
hMem=GlobalAlloc(GHND, cbDevMode);
if (NULL!=hMem)
{
pv=(LPVOID)GlobalLock(hMem);
pIStream->Read(pv, cbDevMode, &cbRead);
GlobalUnlock(hMem);
}
pIStream->Release();
return hMem;
}
/*
* CPages::DevReadConfig
*
* Purpose:
* Public function to read the current device configuration and
* optionally return an information context for it.
*
*
* Parameters:
* ppcd PCOMBINEDEVICE * in which to return a pointer
* to an allocated structure that has all the
* device information we want. Ignored if NULL.
* This is allocated with the task allocator.
* phDC HDC * in which to return the information
* context. If NULL, no IC is created. Caller
* becomes responsible for the returned IC.
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CPages::DevReadConfig(PCOMBINEDEVICE *ppcd, HDC *phDC)
{
HRESULT hr;
LPSTREAM pIStream;
LPMALLOC pIMalloc;
PCOMBINEDEVICE pcd;
ULONG cb, cbRead;
LARGE_INTEGER li;
hr=m_pIStorage->OpenStream(SZSTREAMDEVICECONFIG, 0, STGM_DIRECT
| STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
if (FAILED(hr))
return FALSE;
/*
* Allocate the COMBINEDEVICE structure including the variable
* information past the DEVMODE part.
*/
hr=CoGetMalloc(MEMCTX_TASK, &pIMalloc);
if (FAILED(hr))
{
pIStream->Release();
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -