Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

605 lines (494 sloc) 18.311 kb
/******************************************************************************
*
*
* Notepad2
*
* Print.cpp
* Scintilla Printing Functionality
* Mostly taken from SciTE, (c) Neil Hodgson, http://www.scintilla.org
*
* See Readme.txt for more information about this source code.
* Please send me your comments to this work.
*
* See License.txt for details about distribution and modification.
*
* (c) Florian Balmer 1996-2010
* florian.balmer@gmail.com
* http://www.flos-freeware.ch
*
*
******************************************************************************/
#define _WIN32_WINNT 0x501
#include <windows.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <commdlg.h>
#include <string.h>
#include "platform.h"
#include "scintilla.h"
#include "scilexer.h"
extern "C" {
#include "dialogs.h"
#include "helpers.h"
}
#include "resource.h"
extern "C" HINSTANCE g_hInstance;
// Global settings...
extern "C" int iPrintHeader;
extern "C" int iPrintFooter;
extern "C" int iPrintColor;
extern "C" int iPrintZoom;
extern "C" RECT pagesetupMargin;
// Stored objects...
HGLOBAL hDevMode = NULL;
HGLOBAL hDevNames = NULL;
//=============================================================================
//
// EditPrint() - Code from SciTE
//
extern "C" HWND hwndStatus;
void StatusUpdatePrintPage(int iPageNum)
{
WCHAR tch[32];
FormatString(tch,COUNTOF(tch),IDS_PRINTFILE,iPageNum);
StatusSetText(hwndStatus,255,tch);
StatusSetSimple(hwndStatus,TRUE);
InvalidateRect(hwndStatus,NULL,TRUE);
UpdateWindow(hwndStatus);
}
extern "C" BOOL EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
{
// Don't print empty documents
if (SendMessage(hwnd,SCI_GETLENGTH,0,0) == 0) {
MsgBox(MBINFO,IDS_PRINT_EMPTY);
return TRUE;
}
int startPos;
int endPos;
HDC hdc;
RECT rectMargins;
RECT rectPhysMargins;
RECT rectSetup;
POINT ptPage;
POINT ptDpi;
//RECT rectSetup;
TEXTMETRIC tm;
int headerLineHeight;
HFONT fontHeader;
int footerLineHeight;
HFONT fontFooter;
WCHAR dateString[256];
DOCINFO di = {sizeof(DOCINFO), 0, 0, 0, 0};
LONG lengthDoc;
LONG lengthDocMax;
LONG lengthPrinted;
struct RangeToFormat frPrint;
int pageNum;
BOOL printPage;
WCHAR pageString[32];
HPEN pen;
HPEN penOld;
PRINTDLG pdlg = { sizeof(PRINTDLG), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
pdlg.hwndOwner = GetParent(hwnd);
pdlg.hInstance = g_hInstance;
pdlg.Flags = PD_USEDEVMODECOPIES | PD_ALLPAGES | PD_RETURNDC;
pdlg.nFromPage = 1;
pdlg.nToPage = 1;
pdlg.nMinPage = 1;
pdlg.nMaxPage = 0xffffU;
pdlg.nCopies = 1;
pdlg.hDC = 0;
pdlg.hDevMode = hDevMode;
pdlg.hDevNames = hDevNames;
startPos = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);;
endPos = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0);
if (startPos == endPos) {
pdlg.Flags |= PD_NOSELECTION;
} else {
pdlg.Flags |= PD_SELECTION;
}
if (0) {
// Don't display dialog box, just use the default printer and options
pdlg.Flags |= PD_RETURNDEFAULT;
}
if (!PrintDlg(&pdlg)) {
return TRUE; // False means error...
}
hDevMode = pdlg.hDevMode;
hDevNames = pdlg.hDevNames;
hdc = pdlg.hDC;
// Get printer resolution
ptDpi.x = GetDeviceCaps(hdc, LOGPIXELSX); // dpi in X direction
ptDpi.y = GetDeviceCaps(hdc, LOGPIXELSY); // dpi in Y direction
// Start by getting the physical page size (in device units).
ptPage.x = GetDeviceCaps(hdc, PHYSICALWIDTH); // device units
ptPage.y = GetDeviceCaps(hdc, PHYSICALHEIGHT); // device units
// Get the dimensions of the unprintable
// part of the page (in device units).
rectPhysMargins.left = GetDeviceCaps(hdc, PHYSICALOFFSETX);
rectPhysMargins.top = GetDeviceCaps(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(hdc, HORZRES) // printable width
- rectPhysMargins.left; // left unprintable margin
rectPhysMargins.bottom = ptPage.y // total paper height
- GetDeviceCaps(hdc, VERTRES) // printable height
- rectPhysMargins.top; // right unprintable margin
// At this point, rectPhysMargins contains the widths of the
// unprintable regions on all four sides of the page in device units.
// Take in account the page setup given by the user (if one value is not null)
if (pagesetupMargin.left != 0 || pagesetupMargin.right != 0 ||
pagesetupMargin.top != 0 || pagesetupMargin.bottom != 0) {
// Convert the hundredths of millimeters (HiMetric) or
// thousandths of inches (HiEnglish) margin values
// from the Page Setup dialog to device units.
// (There are 2540 hundredths of a mm in an inch.)
WCHAR localeInfo[3];
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, localeInfo, 3);
if (localeInfo[0] == L'0') { // Metric system. L'1' is US System
rectSetup.left = MulDiv (pagesetupMargin.left, ptDpi.x, 2540);
rectSetup.top = MulDiv (pagesetupMargin.top, ptDpi.y, 2540);
rectSetup.right = MulDiv(pagesetupMargin.right, ptDpi.x, 2540);
rectSetup.bottom = MulDiv(pagesetupMargin.bottom, ptDpi.y, 2540);
} else {
rectSetup.left = MulDiv(pagesetupMargin.left, ptDpi.x, 1000);
rectSetup.top = MulDiv(pagesetupMargin.top, ptDpi.y, 1000);
rectSetup.right = MulDiv(pagesetupMargin.right, ptDpi.x, 1000);
rectSetup.bottom = MulDiv(pagesetupMargin.bottom, ptDpi.y, 1000);
}
// Dont reduce margins below the minimum printable area
rectMargins.left = max(rectPhysMargins.left, rectSetup.left);
rectMargins.top = max(rectPhysMargins.top, rectSetup.top);
rectMargins.right = max(rectPhysMargins.right, rectSetup.right);
rectMargins.bottom = max(rectPhysMargins.bottom, rectSetup.bottom);
} else {
rectMargins.left = rectPhysMargins.left;
rectMargins.top = rectPhysMargins.top;
rectMargins.right = rectPhysMargins.right;
rectMargins.bottom = rectPhysMargins.bottom;
}
// rectMargins now contains the values used to shrink the printable
// area of the page.
// Convert device coordinates into logical coordinates
DPtoLP(hdc, (LPPOINT)&rectMargins, 2);
DPtoLP(hdc, (LPPOINT)&rectPhysMargins, 2);
// Convert page size to logical units and we're done!
DPtoLP(hdc, (LPPOINT) &ptPage, 1);
headerLineHeight = MulDiv(8,ptDpi.y, 72);
fontHeader = CreateFont(headerLineHeight,
0, 0, 0,
FW_BOLD,
0,
0,
0, 0, 0,
0, 0, 0,
L"Arial");
SelectObject(hdc, fontHeader);
GetTextMetrics(hdc, &tm);
headerLineHeight = tm.tmHeight + tm.tmExternalLeading;
if (iPrintHeader == 3)
headerLineHeight = 0;
footerLineHeight = MulDiv(7,ptDpi.y, 72);
fontFooter = CreateFont(footerLineHeight,
0, 0, 0,
FW_NORMAL,
0,
0,
0, 0, 0,
0, 0, 0,
L"Arial");
SelectObject(hdc, fontFooter);
GetTextMetrics(hdc, &tm);
footerLineHeight = tm.tmHeight + tm.tmExternalLeading;
if (iPrintFooter == 1)
footerLineHeight = 0;
di.lpszDocName = pszDocTitle;
di.lpszOutput = 0;
di.lpszDatatype = 0;
di.fwType = 0;
if (StartDoc(hdc, &di) < 0) {
DeleteDC(hdc);
if (fontHeader)
DeleteObject(fontHeader);
if (fontFooter)
DeleteObject(fontFooter);
return FALSE;
}
// Get current date...
SYSTEMTIME st;
GetLocalTime(&st);
GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,dateString,256);
// Get current time...
if (iPrintHeader == 0)
{
WCHAR timeString[128];
GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&st,NULL,timeString,128);
lstrcat(dateString,L" ");
lstrcat(dateString,timeString);
}
// Set print color mode
int printColorModes[5] = {
SC_PRINT_NORMAL,
SC_PRINT_INVERTLIGHT,
SC_PRINT_BLACKONWHITE,
SC_PRINT_COLOURONWHITE,
SC_PRINT_COLOURONWHITEDEFAULTBG };
SendMessage(hwnd,SCI_SETPRINTCOLOURMODE,printColorModes[iPrintColor],0);
// Set print zoom...
SendMessage(hwnd,SCI_SETPRINTMAGNIFICATION,(WPARAM)iPrintZoom,0);
lengthDoc = SendMessage(hwnd,SCI_GETLENGTH,0,0);
lengthDocMax = lengthDoc;
lengthPrinted = 0;
// Requested to print selection
if (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;
}
// We must substract the physical margins from the printable area
frPrint.hdc = hdc;
frPrint.hdcTarget = 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 += headerLineHeight + headerLineHeight / 2;
frPrint.rc.bottom -= footerLineHeight + footerLineHeight / 2;
// Print each page
pageNum = 1;
while (lengthPrinted < lengthDoc) {
printPage = (!(pdlg.Flags & PD_PAGENUMS) ||
(pageNum >= pdlg.nFromPage) && (pageNum <= pdlg.nToPage));
wsprintf(pageString, pszPageFormat, pageNum);
if (printPage) {
// Show wait cursor...
SendMessage(hwnd,SCI_SETCURSOR,SC_CURSORWAIT,0);
// Display current page number in Statusbar
StatusUpdatePrintPage(pageNum);
StartPage(hdc);
SetTextColor(hdc, RGB(0,0,0));
SetBkColor(hdc, RGB(255,255,255));
SelectObject(hdc, fontHeader);
UINT ta = SetTextAlign(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;
if (iPrintHeader < 3)
{
ExtTextOut(hdc, frPrint.rc.left + 5, frPrint.rc.top - headerLineHeight / 2,
/*ETO_OPAQUE*/0, &rcw, pszDocTitle,
lstrlen(pszDocTitle), NULL);
}
// Print date in header
if (iPrintHeader == 0 || iPrintHeader == 1)
{
SIZE sizeInfo;
SelectObject(hdc,fontFooter);
GetTextExtentPoint32(hdc,dateString,lstrlen(dateString),&sizeInfo);
ExtTextOut(hdc, frPrint.rc.right - 5 - sizeInfo.cx, frPrint.rc.top - headerLineHeight / 2,
/*ETO_OPAQUE*/0, &rcw, dateString,
lstrlen(dateString), NULL);
}
if (iPrintHeader < 3)
{
SetTextAlign(hdc, ta);
pen = CreatePen(0, 1, RGB(0,0,0));
penOld = (HPEN)SelectObject(hdc, pen);
MoveToEx(hdc, frPrint.rc.left, frPrint.rc.top - headerLineHeight / 4, NULL);
LineTo(hdc, frPrint.rc.right, frPrint.rc.top - headerLineHeight / 4);
SelectObject(hdc, penOld);
DeleteObject(pen);
}
}
frPrint.chrg.cpMin = lengthPrinted;
frPrint.chrg.cpMax = lengthDoc;
lengthPrinted = SendMessage(hwnd,SCI_FORMATRANGE,printPage,(LPARAM)&frPrint);
if (printPage) {
SetTextColor(hdc, RGB(0,0,0));
SetBkColor(hdc, RGB(255,255,255));
SelectObject(hdc, fontFooter);
UINT ta = SetTextAlign(hdc, TA_TOP);
RECT rcw = {frPrint.rc.left, frPrint.rc.bottom + footerLineHeight / 2,
frPrint.rc.right, frPrint.rc.bottom + footerLineHeight + footerLineHeight / 2};
if (iPrintFooter == 0)
{
SIZE sizeFooter;
GetTextExtentPoint32(hdc,pageString,lstrlen(pageString),&sizeFooter);
ExtTextOut(hdc, frPrint.rc.right - 5 - sizeFooter.cx, frPrint.rc.bottom + footerLineHeight / 2,
/*ETO_OPAQUE*/0, &rcw, pageString,
lstrlen(pageString), NULL);
SetTextAlign(hdc, ta);
pen = ::CreatePen(0, 1, RGB(0,0,0));
penOld = (HPEN)SelectObject(hdc, pen);
SetBkColor(hdc, RGB(0,0,0));
MoveToEx(hdc, frPrint.rc.left, frPrint.rc.bottom + footerLineHeight / 4, NULL);
LineTo(hdc, frPrint.rc.right, frPrint.rc.bottom + footerLineHeight / 4);
SelectObject(hdc, penOld);
DeleteObject(pen);
}
EndPage(hdc);
}
pageNum++;
if ((pdlg.Flags & PD_PAGENUMS) && (pageNum > pdlg.nToPage))
break;
}
SendMessage(hwnd,SCI_FORMATRANGE, FALSE, 0);
EndDoc(hdc);
DeleteDC(hdc);
if (fontHeader)
DeleteObject(fontHeader);
if (fontFooter)
DeleteObject(fontFooter);
// Reset Statusbar to default mode
StatusSetSimple(hwndStatus,FALSE);
// Remove wait cursor...
SendMessage(hwnd,SCI_SETCURSOR,SC_CURSORNORMAL,0);
return TRUE;
}
//=============================================================================
//
// EditPrintSetup() - Code from SciTE
//
// Custom controls: 30 Zoom
// 31 Spin
// 32 Header
// 33 Footer
// 34 Colors
//
extern "C" UINT_PTR CALLBACK PageSetupHook(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch (uiMsg)
{
case WM_INITDIALOG:
{
WCHAR tch[512];
WCHAR *p1,*p2;
SendDlgItemMessage(hwnd,30,EM_LIMITTEXT,32,0);
SendDlgItemMessage(hwnd,31,UDM_SETRANGE,0,MAKELONG((short)20,(short)-10));
SendDlgItemMessage(hwnd,31,UDM_SETPOS,0,MAKELONG((short)iPrintZoom,0));
// Set header options
GetString(IDS_PRINT_HEADER,tch,COUNTOF(tch));
lstrcat(tch,L"|");
p1 = tch;
while (p2 = StrChr(p1,L'|')) {
*p2++ = L'\0';
if (*p1)
SendDlgItemMessage(hwnd,32,CB_ADDSTRING,0,(LPARAM)p1);
p1 = p2; }
SendDlgItemMessage(hwnd,32,CB_SETCURSEL,(WPARAM)iPrintHeader,0);
// Set footer options
GetString(IDS_PRINT_FOOTER,tch,COUNTOF(tch));
lstrcat(tch,L"|");
p1 = tch;
while (p2 = StrChr(p1,L'|')) {
*p2++ = L'\0';
if (*p1)
SendDlgItemMessage(hwnd,33,CB_ADDSTRING,0,(LPARAM)p1);
p1 = p2; }
SendDlgItemMessage(hwnd,33,CB_SETCURSEL,(WPARAM)iPrintFooter,0);
// Set color options
GetString(IDS_PRINT_COLOR,tch,COUNTOF(tch));
lstrcat(tch,L"|");
p1 = tch;
while (p2 = StrChr(p1,L'|')) {
*p2++ = L'\0';
if (*p1)
SendDlgItemMessage(hwnd,34,CB_ADDSTRING,0,(LPARAM)p1);
p1 = p2; }
SendDlgItemMessage(hwnd,34,CB_SETCURSEL,(WPARAM)iPrintColor,0);
// Make combos handier
SendDlgItemMessage(hwnd,32,CB_SETEXTENDEDUI,TRUE,0);
SendDlgItemMessage(hwnd,33,CB_SETEXTENDEDUI,TRUE,0);
SendDlgItemMessage(hwnd,34,CB_SETEXTENDEDUI,TRUE,0);
SendDlgItemMessage(hwnd,1137,CB_SETEXTENDEDUI,TRUE,0);
SendDlgItemMessage(hwnd,1138,CB_SETEXTENDEDUI,TRUE,0);
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
LONG lPos = SendDlgItemMessage(hwnd,31,UDM_GETPOS,0,0);
if (HIWORD(lPos) == 0)
iPrintZoom = (int)(short)LOWORD(lPos);
else
iPrintZoom = 0;
iPrintHeader = SendDlgItemMessage(hwnd,32,CB_GETCURSEL,0,0);
iPrintFooter = SendDlgItemMessage(hwnd,33,CB_GETCURSEL,0,0);
iPrintColor = SendDlgItemMessage(hwnd,34,CB_GETCURSEL,0,0);
}
break;
default:
break;
}
return(0);
}
extern "C" void EditPrintSetup(HWND hwnd)
{
DLGTEMPLATE* pDlgTemplate =
LoadThemedDialogTemplate(MAKEINTRESOURCE(IDD_PAGESETUP),g_hInstance);
PAGESETUPDLG pdlg;
ZeroMemory(&pdlg,sizeof(PAGESETUPDLG));
pdlg.lStructSize = sizeof(PAGESETUPDLG);
pdlg.Flags = PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATEHANDLE;
pdlg.lpfnPageSetupHook = PageSetupHook;
pdlg.hPageSetupTemplate = pDlgTemplate;
pdlg.hwndOwner = GetParent(hwnd);
pdlg.hInstance = g_hInstance;
if (pagesetupMargin.left != 0 || pagesetupMargin.right != 0 ||
pagesetupMargin.top != 0 || pagesetupMargin.bottom != 0) {
pdlg.Flags |= PSD_MARGINS;
pdlg.rtMargin.left = pagesetupMargin.left;
pdlg.rtMargin.top = pagesetupMargin.top;
pdlg.rtMargin.right = pagesetupMargin.right;
pdlg.rtMargin.bottom = pagesetupMargin.bottom;
}
pdlg.hDevMode = hDevMode;
pdlg.hDevNames = hDevNames;
if (PageSetupDlg(&pdlg)) {
pagesetupMargin.left = pdlg.rtMargin.left;
pagesetupMargin.top = pdlg.rtMargin.top;
pagesetupMargin.right = pdlg.rtMargin.right;
pagesetupMargin.bottom = pdlg.rtMargin.bottom;
hDevMode = pdlg.hDevMode;
hDevNames = pdlg.hDevNames;
}
LocalFree(pDlgTemplate);
}
//=============================================================================
//
// EditPrintInit() - Setup default page margin if no values from registry
//
extern "C" void EditPrintInit()
{
if (pagesetupMargin.left == -1 || pagesetupMargin.top == -1 ||
pagesetupMargin.right == -1 || pagesetupMargin.bottom == -1)
{
WCHAR localeInfo[3];
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, localeInfo, 3);
if (localeInfo[0] == L'0') { // Metric system. L'1' is US System
pagesetupMargin.left = 2000;
pagesetupMargin.top = 2000;
pagesetupMargin.right = 2000;
pagesetupMargin.bottom = 2000; }
else {
pagesetupMargin.left = 1000;
pagesetupMargin.top = 1000;
pagesetupMargin.right = 1000;
pagesetupMargin.bottom = 1000; }
}
}
// End of Print.cpp
Jump to Line
Something went wrong with that request. Please try again.