📄 printer.cpp
字号:
//this file is part of notepad++
//Copyright (C)2003 Don HO ( donho@altern.org )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "Printer.h"
void Printer::init(HINSTANCE hInst, HWND hwnd, bool showDialog, int startPos, int endPos)
{
_startPos = startPos;
_endPos = endPos;
_pdlg.lStructSize = sizeof(PRINTDLG);
_pdlg.hwndOwner = hwnd;
_pdlg.hInstance = hInst;
_pdlg.Flags = PD_USEDEVMODECOPIES | PD_ALLPAGES | PD_RETURNDC;
_pdlg.nFromPage = 1;
_pdlg.nToPage = 1;
_pdlg.nMinPage = 1;
_pdlg.nMaxPage = 0xffffU; // We do not know how many pages in the
// document until the printer is selected and the paper size is known.
_pdlg.nCopies = 1;
_pdlg.hDC = 0;
_pdlg.hDevMode = NULL;
_pdlg.hDevNames = NULL;
_pdlg.lCustData = 0;
_pdlg.lpfnPrintHook = NULL;
_pdlg.lpfnSetupHook = NULL;
_pdlg.lpPrintTemplateName = NULL;
_pdlg.lpSetupTemplateName = NULL;
_pdlg.hPrintTemplate = NULL;
_pdlg.hSetupTemplate = NULL;
// See if a range has been selected
_pdlg.Flags |= (_startPos != _endPos)?PD_SELECTION:PD_NOSELECTION;
if (!showDialog)
{
// Don't display dialog box, just use the default printer and options
_pdlg.Flags |= PD_RETURNDEFAULT;
}
}
void Printer::doPrint(const ScintillaEditView & pSEView, const char *header, const char *footer)
{
if (!::PrintDlg(&_pdlg))
return;
POINT ptPage;
POINT ptDpi;
RECT rectMargins;
RECT rectPhysMargins;
// Get printer resolution
ptDpi.x = GetDeviceCaps(_pdlg.hDC, LOGPIXELSX); // dpi in X direction
ptDpi.y = GetDeviceCaps(_pdlg.hDC, LOGPIXELSY); // dpi in Y direction
// Start by getting the physical page size (in device units).
ptPage.x = GetDeviceCaps(_pdlg.hDC, PHYSICALWIDTH); // device units
ptPage.y = GetDeviceCaps(_pdlg.hDC, PHYSICALHEIGHT); // device units
// Get the dimensions of the unprintable
// part of the page (in device units).
rectPhysMargins.left = GetDeviceCaps(_pdlg.hDC, PHYSICALOFFSETX);
rectPhysMargins.top = GetDeviceCaps(_pdlg.hDC, PHYSICALOFFSETY);
// To get the right and lower unprintable area,
// we take the entire width and height of the paper and
// subtract everything else.
rectPhysMargins.right = ptPage.x // total paper width
- GetDeviceCaps(_pdlg.hDC, HORZRES) // printable width
- rectPhysMargins.left; // left unprintable margin
rectPhysMargins.bottom = ptPage.y // total paper height
- GetDeviceCaps(_pdlg.hDC, VERTRES) // printable height
- rectPhysMargins.top; // right unprintable margin
//TOMPORIREMENT
rectMargins.left = rectPhysMargins.left;
rectMargins.top = rectPhysMargins.top;
rectMargins.right = rectPhysMargins.right;
rectMargins.bottom = rectPhysMargins.bottom;
// Convert device coordinates into logical coordinates
DPtoLP(_pdlg.hDC, (LPPOINT)&rectMargins, 2);
DPtoLP(_pdlg.hDC, (LPPOINT)&rectPhysMargins, 2);
// Convert page size to logical units and we're done!
DPtoLP(_pdlg.hDC, &ptPage, 1);
TEXTMETRIC tm;
int headerLineHeight = ::MulDiv(12, ptDpi.y, 72);
HFONT fontHeader = ::CreateFont(headerLineHeight,
0, 0, 0,
FW_BOLD,
FALSE,
FALSE,
0, 0, 0,
0, 0, 0,
"Arial");
::SelectObject(_pdlg.hDC, fontHeader);
::GetTextMetrics(_pdlg.hDC, &tm);
headerLineHeight = tm.tmHeight + tm.tmExternalLeading;
int footerLineHeight = ::MulDiv(8, ptDpi.y, 72);
HFONT fontFooter = ::CreateFont(footerLineHeight,
0, 0, 0,
FW_NORMAL,
TRUE,
FALSE,
0, 0, 0,
0, 0, 0,
"Arial");
::SelectObject(_pdlg.hDC, fontFooter);
::GetTextMetrics(_pdlg.hDC, &tm);
footerLineHeight = tm.tmHeight + tm.tmExternalLeading;
//TEXTMETRIC tm ;
::GetTextMetrics(_pdlg.hDC, &tm);
int printMarge = tm.tmHeight + tm.tmExternalLeading;
printMarge = printMarge + printMarge / 2;
DOCINFO docInfo;
docInfo.cbSize = sizeof(DOCINFO);
docInfo.lpszDocName = pSEView.getCurrentTitle();
docInfo.lpszOutput = NULL;
if (::StartDoc(_pdlg.hDC, &docInfo) < 0)
{
MessageBox(NULL, "Can not start printer document.", 0, MB_OK);
return;
}
int pageNum = 1;
bool printPage;
// By default, we will print all the document
long lengthPrinted = 0;
long lengthDoc = pSEView.getCurrentDocLen();
long lengthDocMax = lengthDoc;
// In the case that the print dialog was launched and that there's a range of selection
// We print the range of selection
if ((!(_pdlg.Flags & PD_RETURNDEFAULT)) && (_pdlg.Flags & PD_SELECTION))
{
if (_startPos > _endPos)
{
lengthPrinted = _endPos;
lengthDoc = _startPos;
}
else
{
lengthPrinted = _startPos;
lengthDoc = _endPos;
}
if (lengthPrinted < 0)
lengthPrinted = 0;
if (lengthDoc > lengthDocMax)
lengthDoc = lengthDocMax;
}
RangeToFormat frPrint;
frPrint.hdc = _pdlg.hDC;
frPrint.hdcTarget = _pdlg.hDC;
frPrint.rc.left = rectMargins.left - rectPhysMargins.left;
frPrint.rc.top = rectMargins.top - rectPhysMargins.top;
frPrint.rc.right = ptPage.x - rectMargins.right - rectPhysMargins.left;
frPrint.rc.bottom = ptPage.y - rectMargins.bottom - rectPhysMargins.top;
frPrint.rcPage.left = 0;
frPrint.rcPage.top = 0;
frPrint.rcPage.right = ptPage.x - rectPhysMargins.left - rectPhysMargins.right - 1;
frPrint.rcPage.bottom = ptPage.y - rectPhysMargins.top - rectPhysMargins.bottom - 1;
frPrint.rc.top += printMarge;
frPrint.rc.bottom -= printMarge;
frPrint.rc.left += printMarge;
frPrint.rc.right -= printMarge;
if (header && header[0])
frPrint.rc.top += headerLineHeight + headerLineHeight / 2;
if (footer && footer[0])
frPrint.rc.bottom -= footerLineHeight + footerLineHeight / 2;
char header2display[256];
expandNppEnvironmentStrs(header, header2display, sizeof(header2display), _pdlg.hwndOwner);
char footer2display[256];
expandNppEnvironmentStrs(footer, footer2display, sizeof(footer2display), _pdlg.hwndOwner);
const char pageVar[] = "$(CURRENT_PRINTING_PAGE)";
while (lengthPrinted < lengthDoc)
{
printPage = (!(_pdlg.Flags & PD_PAGENUMS) ||
(pageNum >= _pdlg.nFromPage) && (pageNum <= _pdlg.nToPage));
char pageString[32];
sprintf(pageString, "%0d", pageNum);
if (printPage)
{
::StartPage(_pdlg.hDC);
if (header && header[0])
{
string sHeader = header2display;
size_t pos = sHeader.find(pageVar);
if (pos != sHeader.npos)
sHeader.replace(pos, strlen(pageVar), pageString);
//::SetTextColor(hdc, sdHeader.ForeAsLong());
//::SetBkColor(hdc, sdHeader.BackAsLong());
::SelectObject(_pdlg.hDC, fontHeader);
UINT ta = ::SetTextAlign(_pdlg.hDC, TA_BOTTOM);
RECT rcw = {frPrint.rc.left, frPrint.rc.top - headerLineHeight - headerLineHeight / 2,
frPrint.rc.right, frPrint.rc.top - headerLineHeight / 2};
rcw.bottom = rcw.top + headerLineHeight;
::ExtTextOut(_pdlg.hDC, frPrint.rc.left + 5, frPrint.rc.top - headerLineHeight / 2,
ETO_OPAQUE, &rcw, sHeader.c_str(),
static_cast<int>(sHeader.length()), NULL);
::SetTextAlign(_pdlg.hDC, ta);
HPEN pen = ::CreatePen(0, 1, 0x00000000);
HPEN penOld = static_cast<HPEN>(::SelectObject(_pdlg.hDC, pen));
::MoveToEx(_pdlg.hDC, frPrint.rc.left, frPrint.rc.top - headerLineHeight / 4, NULL);
::LineTo(_pdlg.hDC, frPrint.rc.right, frPrint.rc.top - headerLineHeight / 4);
::SelectObject(_pdlg.hDC, penOld);
::DeleteObject(pen);
}
}
frPrint.chrg.cpMin = lengthPrinted;
frPrint.chrg.cpMax = lengthDoc;
lengthPrinted = long(pSEView.execute(SCI_FORMATRANGE, printPage, reinterpret_cast<LPARAM>(&frPrint)));
if (printPage)
{
if (footer && footer[0])
{
string sFooter = footer2display;
size_t pos = sFooter.find(pageVar);
if (pos != sFooter.npos)
sFooter.replace(pos, strlen(pageVar), pageString);
//::SetTextColor(_pdlg.hDC, sdFooter.ForeAsLong());
//::SetBkColor(_pdlg.hDC, sdFooter.BackAsLong());
::SelectObject(_pdlg.hDC, fontFooter);
UINT ta = ::SetTextAlign(_pdlg.hDC, TA_TOP);
RECT rcw = {frPrint.rc.left, frPrint.rc.bottom + footerLineHeight / 2,
frPrint.rc.right, frPrint.rc.bottom + footerLineHeight + footerLineHeight / 2};
::ExtTextOut(_pdlg.hDC, frPrint.rc.left + 5, frPrint.rc.bottom + footerLineHeight / 2,
ETO_OPAQUE, &rcw, sFooter.c_str(),
static_cast<int>(sFooter.length()), NULL);
::SetTextAlign(_pdlg.hDC, ta);
HPEN pen = ::CreatePen(0, 1, 0x00000000);
HPEN penOld = static_cast<HPEN>(::SelectObject(_pdlg.hDC, pen));
//::SetBkColor(_pdlg.hDC, sdFooter.ForeAsLong());
::MoveToEx(_pdlg.hDC, frPrint.rc.left, frPrint.rc.bottom + footerLineHeight / 4, NULL);
::LineTo(_pdlg.hDC, frPrint.rc.right, frPrint.rc.bottom + footerLineHeight / 4);
::SelectObject(_pdlg.hDC, penOld);
::DeleteObject(pen);
}
::EndPage(_pdlg.hDC);
}
pageNum++;
if ((_pdlg.Flags & PD_PAGENUMS) && (pageNum > _pdlg.nToPage))
break;
}
pSEView.execute(SCI_FORMATRANGE, FALSE, 0);
::EndDoc(_pdlg.hDC);
::DeleteDC(_pdlg.hDC);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -