📄 print.cpp
字号:
/*
* Read size of the DEVICECONFIG structure including variable
* portion of DEVMODE. We need to load all this information
* for CreateIC. To this size we'll add the size of
* DVTARGETDEVICE in order to allocate a COMBINEDEVICE.
*/
pIStream->Read(&cb, sizeof(DWORD), &cbRead);
pcd=(PCOMBINEDEVICE)pIMalloc->Alloc(cb+sizeof(DVTARGETDEVICE));
if (NULL==pcd)
{
pIMalloc->Release();
pIStream->Release();
return FALSE;
}
//Now get the real information.
LISet32(li, 0);
pIStream->Seek(li, STREAM_SEEK_SET, NULL);
pIStream->Read(&(pcd->dc), cb, &cbRead);
pIStream->Release();
/*
* If requested, complete the DVTARGETDEVICE structure in
* pcd and store pcd in *ppcd for return.
*/
if (NULL!=ppcd)
{
WORD cb=sizeof(DVTARGETDEVICE);
pcd->td.tdSize=cb;
pcd->td.tdExtDevmodeOffset=cb;
pcd->td.tdDriverNameOffset=cb+sizeof(DEVMODE);
pcd->td.tdDeviceNameOffset=cb+sizeof(DEVMODE)
+(CCHDEVICENAME*sizeof(TCHAR));
pcd->td.tdPortNameOffset =cb+sizeof(DEVMODE)
+(CCHDEVICENAME*2*sizeof(TCHAR));
*ppcd=pcd;
}
//Create an IC if requested.
if (NULL!=phDC)
{
//Get the DC then configure
*phDC=CreateIC(pcd->dc.szDriver, pcd->dc.szDevice
, pcd->dc.szPort, &(pcd->dc.dm));
if (NULL==*phDC)
return FALSE;
}
//pcd is a temporary allocation in this case
if (NULL==ppcd)
pIMalloc->Free(pcd);
pIMalloc->Release();
return (NULL!=*phDC);
}
//End CHAPTER12MOD
/*
* CPages::ConfigureForDevice
*
* Purpose:
* Recalculates our drawing configuration based on the contents of
* an hDC. If no HDC is given we use the contents of our DevMode
* stream.
*
* Parameters:
* None
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CPages::ConfigureForDevice(void)
{
POINT ptOffset, ptPaper;
RECT rc;
HDC hDC;
CHourglass hg;
//CHAPTER12MOD
if (!DevReadConfig(NULL, &hDC))
return FALSE;
//End CHAPTER12MOD
//Get usable page dimensions: already sensitive to orientation
m_cx=GetDeviceCaps(hDC, HORZSIZE)*10-16; //*10: mm to LOMETRIC
m_cy=GetDeviceCaps(hDC, VERTSIZE)*10-16; //-16: for driver bugs.
//Calculate the printer-limited margins on sides in LOMETRIC.
Escape(hDC, GETPRINTINGOFFSET, NULL, NULL, &ptOffset);
Escape(hDC, GETPHYSPAGESIZE, NULL, NULL, &ptPaper);
SetRect(&rc, ptOffset.x, ptOffset.y, ptPaper.x, ptPaper.y);
SetMapMode(hDC, MM_LOMETRIC);
RectConvertMappings(&rc, hDC, FALSE);
//Left and top margins are the printing offset.
m_xMarginLeft= rc.left+8; //+8 to match -16 above
m_yMarginTop =-rc.top+8; //LOMETRIC makes this negative.
//Right is (paper width)-(usable width)-(left margin)
m_xMarginRight =rc.right-m_cx-m_xMarginLeft;
//Bottom is (paper height)-(usable height)-(top margin)+1
m_yMarginBottom=-rc.bottom-m_cy-m_yMarginTop+1;
UpdateScrollRanges();
DeleteDC(hDC);
return TRUE;
}
/*
* CPages::Print
*
* Purpose:
* Prints a specified range of pages to a given hDC. Repeats for
* a given number of copies.
*
* Parameters:
* hDC HDC to which we print.
* pszDoc LPTSTR providing the document name.
* dwFlags DWORD flags from PrintDlg
* iPageStart UINT starting page index (one based)
* iPageEnd UINT ending page index (one based). Includes
* this page.
* cCopies UINT number of copies to print. If PD_COLLATE
* in dwFlags is set, we print multiple copies of
* each page as we cycle through. Otherwise we
* cycle multiple times.
*
* Return Value:
* None
*/
BOOL CPages::Print(HDC hDC, LPTSTR pszDoc, DWORD dwFlags
, UINT iPageStart, UINT iPageEnd, UINT cCopies)
{
BOOL fError=FALSE;
int iPage, iPageInc;
int iUserPage, cPages;
UINT iRepeat, cRepeat;
UINT iCycle, cCycles;
UINT iPageHold=m_iPageCur;
HWND hWndT, hWndTop=NULL;
DOCINFO di;
PCDocument pDoc;
//Validate hDC and page ranges
if (NULL==hDC)
return FALSE;
if ((PD_PAGENUMS & dwFlags))
{
if (-1==iPageStart)
iPageStart=0;
else
iPageStart--; //Switch to zero offset.
if (-1==iPageEnd)
iPageEnd=m_cPages-1;
else
iPageEnd--; //Switch to zero offset.
}
else //Can't test PD_ALLPAGES with & since it's defined as 0L
{
iPageStart=0;
iPageEnd=m_cPages-1;
}
//Arrange cycles and repeats depending on cCopies and collating
if (PD_COLLATE & dwFlags)
{
cCycles=cCopies;
cRepeat=1;
}
else
{
cCycles=1;
cRepeat=cCopies;
}
//Disable the frame window to prevent reentrancy while printing.
hWndT=GetParent(m_hWnd);
pDoc=(PCDocument)SendMessage(hWndT, DOCM_PDOCUMENT, 0, 0L);
if (NULL!=pDoc)
{
PCFrame pFR;
pFR=pDoc->FrameGet();
hWndTop=pFR->Window();
EnableWindow(hWndTop, FALSE);
}
SetAbortProc(hDC, AbortProc);
g_fCancelPrint=FALSE;
//If these don't work then we'll just live without a dialog.
g_hDlgPrint=CreateDialog(m_hInst, MAKEINTRESOURCE(IDD_PRINTING)
, hWndTop, PrintDlgProc);
//Increment for either direction.
iPageInc=(iPageStart > iPageEnd) ? -1 : 1;
//Initial entries in dialog box.
cPages=1+((int)(iPageEnd-iPageStart)*iPageInc);
SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE, 1, (LPARAM)cPages);
SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, 1, (LPARAM)cRepeat);
di.cbSize=sizeof(DOCINFO);
di.lpszDocName=pszDoc;
di.lpszOutput=NULL;
if (StartDoc(hDC, &di) > 0)
{
/*
* Iterate over the pages, repeating each page depending on
* the copies we want and if we have collate enabled.
*/
for (iCycle=1; iCycle <= cCycles; iCycle++)
{
if (PD_COLLATE & dwFlags)
{
SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, iCycle
, (LPARAM)cCycles);
}
//iPageInc controls direction
for (iPage=iPageStart; ; iPage+=iPageInc)
{
iUserPage=1+((iPage-(int)iPageStart)*iPageInc);
SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE
, iUserPage, (LPARAM)cPages);
m_iPageCur=iPage; //We restore this later.
for (iRepeat=1; iRepeat <= cRepeat; iRepeat++)
{
if (!(PD_COLLATE & dwFlags))
{
SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE
, iRepeat, (LPARAM)cRepeat);
}
StartPage(hDC);
Draw(hDC, TRUE, TRUE);
if (EndPage(hDC) < 0)
fError=TRUE;
if (fError || g_fCancelPrint)
break;
}
if (fError || g_fCancelPrint)
break;
//If we just printed the last page, time to quit.
if (iPage==(int)iPageEnd)
break;
}
if (fError || g_fCancelPrint)
break;
}
if (!fError)
EndDoc(hDC);
else
AbortDoc(hDC);
}
else
fError=TRUE;
//Set the page back to what it was before all this started.
m_iPageCur=iPageHold;
EnableWindow(hWndTop, TRUE);
SetFocus(hWndTop);
DestroyWindow(g_hDlgPrint);
DeleteDC(hDC);
return !fError;
}
/*
* AbortProc
*
* Purpose:
* Abort procedure for printing the pages.
*
* Parameters:
* hDC HDC on which printing is happening.
* iErr int error code.
*
* Return Value:
* BOOL TRUE to continue the print job, FALSE otherwise.
*/
BOOL APIENTRY AbortProc(HDC hDC, int iErr)
{
MSG msg;
while (!g_fCancelPrint
&& PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (NULL==g_hDlgPrint
|| !IsDialogMessage(g_hDlgPrint, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return !g_fCancelPrint;
}
/*
* PrintDlgProc
*
* Purpose:
* Modeless dialog procedure for the dialog displayed while Patron
* is printing pages.
*/
BOOL APIENTRY PrintDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam
, LPARAM lParam)
{
TCHAR szFormat[40];
TCHAR szOutput[80];
switch (iMsg)
{
case WM_INITDIALOG:
EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE
, MF_GRAYED);
return TRUE;
case WM_COMMAND:
//Cancel button was pressed.
g_fCancelPrint=TRUE;
ShowWindow(hDlg, SW_HIDE);
return TRUE;
case PRINTM_PAGEUPDATE:
GetDlgItemText(hDlg, ID_PAGESTRING, szFormat
, sizeof(szFormat));
wsprintf(szOutput, szFormat, wParam, (UINT)lParam);
SetDlgItemText(hDlg, ID_CURRENTPAGE, szOutput);
return TRUE;
case PRINTM_COPYUPDATE:
GetDlgItemText(hDlg, ID_COPYSTRING, szFormat
, sizeof(szFormat));
wsprintf(szOutput, szFormat, wParam, (UINT)lParam);
SetDlgItemText(hDlg, ID_CURRENTCOPY, szOutput);
return TRUE;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -