mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
15 KiB
482 lines
15 KiB
#include <math.h>
|
|
|
|
#include "textbox.h"
|
|
#include "tables.h"
|
|
|
|
#define SEPJOBLEVEL 2
|
|
#define SEPPRINTERLEVEL 2
|
|
#define SEPMAXTEXTBOX 2000
|
|
|
|
#define SEPEXTRA 0x20
|
|
#define SEPBEGIN 0x10
|
|
#define SEPADJ 0x08
|
|
#define SEPATTACH 0x04
|
|
#define SEPFIRST 0x02
|
|
#define SEPEVERY 0x01
|
|
|
|
void SepHeaderPage(HANDLE hPrintProcessor, LPWSTR pDocumentName);
|
|
void SepTrailerPage(HANDLE hPrintProcessor, LPWSTR pDocumentName);
|
|
void SepPrintSepFile(PTCHAR szFileName, PTCHAR szPrinterName);
|
|
void ResolveJobInfo(PTCHAR text, JOB_INFO_2* pJob, PRINTER_INFO_2* pPrinter);
|
|
PTCHAR SysTimeToTimeString(SYSTEMTIME *pSystemTime, PTCHAR string);
|
|
PTCHAR SysTimeToShortDateString(SYSTEMTIME *pSystemTime, PTCHAR string);
|
|
PTCHAR SysTimeToLongDateString(SYSTEMTIME *pSystemTime, PTCHAR string);
|
|
PTCHAR SysTimeToDiff(SYSTEMTIME* pStart, SYSTEMTIME* pEnd, PTCHAR string);
|
|
BOOL SepReadRegistry();
|
|
void DrawSepPage(HDC hDC, RECT* pBound, PTCHAR szFileName);
|
|
void SepAttachFirstPage(HDC hDC);
|
|
void SepAttachEveryPage(HDC hDC);
|
|
void SepAttachLastPage(HDC hDC);
|
|
|
|
// registry path
|
|
static const PTCHAR szSepRegistryRoot = L"System\\CurrentControlSet\\Control\\Print\\Printers\\";
|
|
static const PTCHAR szSepKey = L"Separator Page";
|
|
// record printing start and end time
|
|
static SYSTEMTIME Started, Ended;
|
|
static BOOL bEndValid;
|
|
// control data
|
|
static JOB_INFO_2* pJob;
|
|
static PRINTER_INFO_2* pPrinter;
|
|
static HGLOBAL hJobMem, hPrtMem;
|
|
static TCHAR szExtraFile[MAX_PATH+1], szAttachFile[MAX_PATH+1];
|
|
static DWORD dwOptions;
|
|
static DEVMODE* pDevMode;
|
|
static BOOL bSepValid;
|
|
static PTCHAR szLastUser = NULL;
|
|
|
|
void SepHeaderPage(HANDLE hPrintProcessor, LPWSTR pDocumentName)
|
|
{
|
|
PPRINTPROCESSORDATA pData;
|
|
HANDLE hPrinter;
|
|
DWORD cbSize;
|
|
// per-job initialize
|
|
GetSystemTime(&Started);
|
|
bEndValid = FALSE;
|
|
pJob = NULL;
|
|
pPrinter = NULL;
|
|
hJobMem = hPrtMem = NULL;
|
|
dwOptions = 0;
|
|
pDevMode = NULL;
|
|
bSepValid = FALSE;
|
|
|
|
// initialize control data
|
|
if (!(pData = ValidateHandle(hPrintProcessor))) return;
|
|
|
|
// Get printer and job info
|
|
if (OpenPrinter(pData->pPrinterName,&hPrinter,NULL))
|
|
{
|
|
if (!GetJob(hPrinter, pData->JobId, SEPJOBLEVEL, NULL, 0, &cbSize)) // get size of info
|
|
if (!(hJobMem = GlobalAlloc(GMEM_MOVEABLE, cbSize)) ||
|
|
!(pJob = (JOB_INFO_2*)GlobalLock(hJobMem)) ||
|
|
!GetJob(hPrinter, pData->JobId, SEPJOBLEVEL, (LPBYTE)pJob, cbSize, &cbSize))
|
|
pJob = NULL;
|
|
if (!GetPrinter(hPrinter, SEPPRINTERLEVEL, NULL, 0, &cbSize)) // get size of info
|
|
if (!(hPrtMem = GlobalAlloc(GMEM_MOVEABLE, cbSize)) ||
|
|
!(pPrinter = (PRINTER_INFO_2*)GlobalLock(hPrtMem)) ||
|
|
!GetPrinter(hPrinter, SEPPRINTERLEVEL, (LPBYTE)pPrinter, cbSize, &cbSize))
|
|
pPrinter = NULL;
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
|
|
if (!pJob || !pPrinter) return;
|
|
|
|
if (!SepReadRegistry()) return;
|
|
|
|
bSepValid = TRUE;
|
|
|
|
// check if begin sep page is set
|
|
if ((dwOptions & SEPEXTRA) && (dwOptions & SEPBEGIN))
|
|
// check for user names for adjacent jobs
|
|
if ((dwOptions & SEPADJ) || !szLastUser || !pData->pPrinterName ||
|
|
wcscmp(szLastUser, pJob->pUserName))
|
|
SepPrintSepFile(szExtraFile, pData->pPrinterName);
|
|
|
|
// set new last user name
|
|
if (szLastUser) {HeapFree(GetProcessHeap(), 0, szLastUser); szLastUser = NULL;}
|
|
if (pJob->pUserName)
|
|
{
|
|
szLastUser = (PTCHAR)HeapAlloc(GetProcessHeap(), 0,
|
|
(wcslen(pJob->pUserName)+1)*sizeof(TCHAR));
|
|
if (szLastUser) wcscpy(szLastUser, pJob->pUserName);
|
|
}
|
|
}
|
|
|
|
BOOL SepReadRegistry()
|
|
{
|
|
TCHAR szRegPath[MAX_PATH+1];
|
|
HKEY hKey;
|
|
DWORD cbSize, dwType;
|
|
BOOL bResult;
|
|
if (!pPrinter) return FALSE;
|
|
wcscat(wcscpy(szRegPath, szSepRegistryRoot), pPrinter->pPrinterName);
|
|
wcscat(wcscat(szRegPath, L"\\"), szSepKey);
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, 0, KEY_READ, &hKey)
|
|
!= ERROR_SUCCESS) return FALSE;
|
|
|
|
cbSize = sizeof(DWORD);
|
|
bResult = RegQueryValueEx(hKey, L"Options", 0, &dwType, (LPBYTE)&dwOptions,
|
|
&cbSize) == ERROR_SUCCESS && dwType == REG_DWORD;
|
|
cbSize = MAX_PATH*sizeof(TCHAR);
|
|
bResult = bResult && RegQueryValueEx(hKey, L"Extra File", 0, &dwType, (LPBYTE)szExtraFile,
|
|
&cbSize) == ERROR_SUCCESS && (dwType & REG_SZ);
|
|
cbSize = MAX_PATH*sizeof(TCHAR);
|
|
bResult = bResult && RegQueryValueEx(hKey, L"Attach File", 0, &dwType, (LPBYTE)szAttachFile,
|
|
&cbSize) == ERROR_SUCCESS && (dwType & REG_SZ);
|
|
cbSize=0;
|
|
bResult = bResult && RegQueryValueEx(hKey, L"Extra Dev Mode", 0, NULL, NULL,
|
|
&cbSize) == ERROR_SUCCESS;
|
|
if (bResult && cbSize)
|
|
{
|
|
bResult = bResult && (pDevMode = (DEVMODE*)HeapAlloc(GetProcessHeap(), 0, cbSize));
|
|
if (bResult)
|
|
{
|
|
bResult = bResult && RegQueryValueEx(hKey, L"Extra Dev Mode", 0, &dwType, (LPBYTE)pDevMode,
|
|
&cbSize) == ERROR_SUCCESS && (dwType & REG_BINARY);
|
|
if (!bResult) { HeapFree(GetProcessHeap(), 0, pDevMode); pDevMode=NULL; }
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
return bResult;
|
|
}
|
|
|
|
void SepTrailerPage(HANDLE hPrintProcessor, LPWSTR pDocumentName)
|
|
{
|
|
PPRINTPROCESSORDATA pData;
|
|
// end-job initialize
|
|
GetSystemTime(&Ended);
|
|
bEndValid = TRUE;
|
|
|
|
// initialize control data
|
|
if ((pData = ValidateHandle(hPrintProcessor)) && bSepValid)
|
|
// check if end sep page is set
|
|
if ((dwOptions & SEPEXTRA) && !(dwOptions & SEPBEGIN))
|
|
SepPrintSepFile(szExtraFile, pData->pPrinterName);
|
|
|
|
// release memory
|
|
if (pJob) GlobalUnlock(hJobMem);
|
|
if (hJobMem) GlobalFree(hJobMem);
|
|
if (pPrinter) GlobalUnlock(hPrtMem);
|
|
if (hPrtMem) GlobalFree(hJobMem);
|
|
if (pDevMode) HeapFree(GetProcessHeap(), 0, pDevMode);
|
|
}
|
|
|
|
void SepPrintSepFile(PTCHAR szFileName, PTCHAR szPrinterName)
|
|
{
|
|
HDC hDC;
|
|
DOCINFO DocInfo;
|
|
RECT rectPaper;
|
|
|
|
// Start separator page document
|
|
hDC = CreateDC(L"", szPrinterName, L"", pDevMode);
|
|
DocInfo.lpszDocName = L"Separator Page";
|
|
DocInfo.lpszOutput = 0;
|
|
DocInfo.cbSize = sizeof(DOCINFO);
|
|
DocInfo.lpszDatatype = NULL;
|
|
DocInfo.fwType = 0;
|
|
|
|
StartDoc(hDC, (LPDOCINFO)&DocInfo);
|
|
StartPage(hDC);
|
|
|
|
rectPaper.left = rectPaper.top = 0;
|
|
rectPaper.right = GetDeviceCaps(hDC, HORZRES);
|
|
rectPaper.bottom = GetDeviceCaps(hDC, VERTRES);
|
|
|
|
// draw sep page on this DC
|
|
DrawSepPage(hDC, &rectPaper, szFileName);
|
|
|
|
//End page
|
|
EndPage(hDC);
|
|
EndDoc(hDC);
|
|
DeleteDC(hDC);
|
|
}
|
|
|
|
|
|
void ResolveJobInfo(PTCHAR text, JOB_INFO_2* pJob, PRINTER_INFO_2* pPrinter)
|
|
{
|
|
JOBINFO* pInfo;
|
|
PTCHAR ptr, ins, repl;
|
|
TCHAR insert[MAX_PATH];
|
|
TCHAR buf[MAX_PATH];
|
|
TCHAR temp[SEPMAXTEXTBOX];
|
|
|
|
for (pInfo = JobInfo; pInfo->insert; pInfo++)
|
|
{
|
|
ptr = text;
|
|
wsprintf(insert,L"%hs",pInfo->insert);
|
|
while (ins = wcsstr(ptr, insert))
|
|
{
|
|
switch (pInfo - JobInfo)
|
|
{
|
|
case DOCUMENTNAME: repl = pJob->pDocument; break;
|
|
case USERLOGINNAME: repl = pJob->pUserName; break;
|
|
case SOURCEWORKSTATION: repl = pJob->pMachineName; break;
|
|
|
|
case USERFULLNAME: repl = L"To be implemented"; break;
|
|
case USERDOMAIN: repl = L"To be implemented"; break;
|
|
case USERWORKGROUP: repl = L"To be implemented"; break;
|
|
case USERPHONENUMBER: repl = L"To be implemented"; break;
|
|
case USEREMAIL: repl = L"To be implemented"; break;
|
|
case USEROFFICE: repl = L"To be implemented"; break;
|
|
|
|
case PRINTERNAME: repl = pPrinter->pPrinterName; break;
|
|
case PRINTERSHARENAME: repl = pPrinter->pShareName; break;
|
|
case PRINTERLOCATION: repl = pPrinter->pLocation; break;
|
|
case PRINTERCOMMENT: repl = pPrinter->pComment; break;
|
|
case PRINTSERVER: repl = pPrinter->pServerName; break;
|
|
|
|
case JOBNUMBER: wsprintf(buf, L"%lu", pJob->JobId); repl = buf; break;
|
|
case JOBPAGES: wsprintf(buf, L"%lu", pJob->TotalPages); repl = buf; break;
|
|
case JOBSIZE: wsprintf(buf, L"%lu", pJob->Size); repl = buf; break;
|
|
|
|
case REQUESTTIME: repl = SysTimeToTimeString(&(pJob->Submitted), buf); break;
|
|
case REQUESTSHORTDATE: repl = SysTimeToShortDateString(&(pJob->Submitted), buf); break;
|
|
case REQUESTLONGDATE: repl = SysTimeToLongDateString(&(pJob->Submitted), buf); break;
|
|
|
|
case STARTTIME: repl = SysTimeToTimeString(&Started, buf); break;
|
|
case STARTSHORTDATE: repl = SysTimeToShortDateString(&Started, buf); break;
|
|
case STARTLONGDATE: repl = SysTimeToLongDateString(&Started, buf); break;
|
|
|
|
case ENDTIME: repl = bEndValid ? SysTimeToTimeString(&Ended, buf) : L""; break;
|
|
case ENDSHORTDATE: repl = bEndValid ? SysTimeToShortDateString(&Ended, buf) : L""; break;
|
|
case ENDLONGDATE: repl = bEndValid ? SysTimeToLongDateString(&Ended, buf) : L""; break;
|
|
|
|
case QUEUINGDELAY: repl = SysTimeToDiff(&(pJob->Submitted), &Started, buf); break;
|
|
|
|
default: repl = insert; break;
|
|
}
|
|
wcscpy(temp, ins + wcslen(insert));
|
|
wcscpy(ins, repl);
|
|
wcscat(ins, temp);
|
|
ptr = ins + wcslen(repl);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
PTCHAR SysTimeToTimeString(SYSTEMTIME *pSystemTime, PTCHAR string)
|
|
{
|
|
SYSTEMTIME LocalTime;
|
|
LCID lcid;
|
|
SystemTimeToTzSpecificLocalTime(NULL, pSystemTime, &LocalTime);
|
|
lcid=GetSystemDefaultLCID();
|
|
GetTimeFormat(lcid, 0, &LocalTime, NULL, string, MAX_PATH);
|
|
return string;
|
|
}
|
|
|
|
|
|
PTCHAR SysTimeToShortDateString(SYSTEMTIME* pSystemTime, PTCHAR string)
|
|
{
|
|
SYSTEMTIME LocalTime;
|
|
LCID lcid;
|
|
SystemTimeToTzSpecificLocalTime(NULL, pSystemTime, &LocalTime);
|
|
lcid = GetSystemDefaultLCID();
|
|
GetDateFormat(lcid, DATE_SHORTDATE, &LocalTime, NULL, string, MAX_PATH);
|
|
return string;
|
|
}
|
|
|
|
PTCHAR SysTimeToLongDateString(SYSTEMTIME* pSystemTime, PTCHAR string)
|
|
{
|
|
SYSTEMTIME LocalTime;
|
|
LCID lcid;
|
|
SystemTimeToTzSpecificLocalTime(NULL, pSystemTime, &LocalTime);
|
|
lcid = GetSystemDefaultLCID();
|
|
GetDateFormat(lcid, DATE_LONGDATE, &LocalTime, NULL, string, MAX_PATH);
|
|
return string;
|
|
}
|
|
|
|
PTCHAR SysTimeToDiff(SYSTEMTIME* pStart, SYSTEMTIME* pEnd, PTCHAR string)
|
|
{
|
|
FILETIME ftStart, ftEnd;
|
|
double dDiff;
|
|
ULONG tsec, tenseconds;
|
|
ULONG sec, seconds;
|
|
ULONG min, minutes;
|
|
ULONG hour, hours;
|
|
ULONG days;
|
|
PTCHAR ptr;
|
|
|
|
SystemTimeToFileTime(pStart, &ftStart);
|
|
SystemTimeToFileTime(pEnd, &ftEnd);
|
|
dDiff = ((pow(2,32) * ftEnd.dwHighDateTime + ftEnd.dwLowDateTime) -
|
|
(pow(2,32) * ftStart.dwHighDateTime + ftStart.dwLowDateTime)) / pow(10,6);
|
|
|
|
*string = L'\0';
|
|
|
|
if (dDiff < 0) return string;
|
|
|
|
tenseconds = (ULONG) dDiff;
|
|
tsec = tenseconds % 10;
|
|
seconds = tenseconds / 10;
|
|
sec = seconds % 60;
|
|
minutes = seconds / 60;
|
|
min = minutes % 60;
|
|
hours = minutes / 60;
|
|
hour = hours % 24;
|
|
days = hours / 24;
|
|
|
|
ptr = string;
|
|
if (days > 0)
|
|
{ wsprintf(ptr, L"%lu Day(s) ", days); ptr = string + wcslen(string); }
|
|
if (days >0 || hour > 0)
|
|
{ wsprintf(ptr, L"%lu Hour(s) ", hour); ptr = string + wcslen(string); }
|
|
if (days >0 || hour > 0 || min > 0)
|
|
{ wsprintf(ptr, L"%lu Minute(s) ", min); ptr = string + wcslen(string); }
|
|
|
|
wsprintf(ptr, L"%lu.%lu Second(s) ", sec, tsec);
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
void DrawSepPage(HDC hDC, RECT* pBound, PTCHAR szFileName)
|
|
{
|
|
HENHMETAFILE hEmf;
|
|
HANDLE hFile;
|
|
HANDLE hFileMapping;
|
|
DWORD dwFileSizeLo;
|
|
PCHAR pFileStart;
|
|
DWORD cbRead,cbWritten;
|
|
DWORD dwEmfLen, dwTextRecords;
|
|
SIZE sizePage;
|
|
TEXTBOX* pTextRec;
|
|
RECT rect, trect;
|
|
HFONT hFont, hOldFont;
|
|
TCHAR text[SEPMAXTEXTBOX];
|
|
|
|
// open separator file
|
|
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
|
if (hFile==INVALID_HANDLE_VALUE) return;
|
|
|
|
// get EMF and text size
|
|
ReadFile(hFile, &dwEmfLen, sizeof(DWORD), &cbRead, NULL);
|
|
if (cbRead != sizeof(DWORD)) { CloseHandle(hFile); return;}
|
|
ReadFile(hFile, &dwTextRecords, sizeof(DWORD), &cbRead, NULL);
|
|
if (cbRead != sizeof(DWORD)) { CloseHandle(hFile); return;}
|
|
ReadFile(hFile, &sizePage, sizeof(SIZE), &cbRead, NULL);
|
|
if (cbRead != sizeof(SIZE)) { CloseHandle(hFile); return;}
|
|
|
|
// create mapping
|
|
dwFileSizeLo = GetFileSize(hFile, NULL);
|
|
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
if (!hFileMapping || dwFileSizeLo==-1) { CloseHandle(hFile); return;}
|
|
|
|
// map view of file
|
|
pFileStart = (char *)MapViewOfFile(hFileMapping, FILE_MAP_READ,
|
|
0, 0, 2 * sizeof(DWORD) + sizeof(SIZE) + dwEmfLen + dwTextRecords * sizeof(TEXTBOX));
|
|
if (!pFileStart) { CloseHandle(hFileMapping); CloseHandle(hFile); return;}
|
|
|
|
// create EMF
|
|
hEmf = SetEnhMetaFileBits(dwEmfLen, pFileStart + 2 * sizeof(DWORD) + sizeof(SIZE));
|
|
if (hEmf)
|
|
{
|
|
PlayEnhMetaFile(hDC, hEmf, pBound);
|
|
DeleteEnhMetaFile(hEmf);
|
|
}
|
|
|
|
// Set Map Mode
|
|
SetMapMode(hDC, MM_ANISOTROPIC);
|
|
SetViewportExtEx(hDC, pBound->right - pBound->left, pBound->bottom - pBound->top, NULL);
|
|
SetWindowExtEx(hDC, sizePage.cx, -sizePage.cy, NULL);
|
|
SetViewportOrgEx(hDC, pBound->left, pBound->top, NULL);
|
|
SetWindowOrgEx(hDC, -sizePage.cx/2, sizePage.cy/2, NULL);
|
|
|
|
// Process Text Objects
|
|
pTextRec = (TEXTBOX*) (pFileStart + 2 * sizeof(DWORD) + sizeof(SIZE) + dwEmfLen);
|
|
while (dwTextRecords--)
|
|
{
|
|
// get draw rectangle
|
|
rect = pTextRec -> position;
|
|
|
|
// normalize rectangle
|
|
trect.left = min(rect.left, rect.right);
|
|
trect.top = max(rect.top, rect.bottom);
|
|
trect.right = max(rect.left, rect.right);
|
|
trect.bottom = min(rect.top, rect.bottom);
|
|
|
|
// leave margins to border, as in editor
|
|
trect.left = min(trect.left + 2, trect.right);
|
|
trect.top = max(trect.top - 2, trect.bottom);
|
|
trect.right = max(trect.left, trect.right - 2);
|
|
trect.bottom = min(trect.top, trect.bottom + 2);
|
|
|
|
// create font
|
|
hFont = CreateFontIndirectA(&(pTextRec->lf));
|
|
if (hFont)
|
|
hOldFont = SelectObject(hDC, hFont);
|
|
|
|
// set text color
|
|
SetTextColor(hDC, pTextRec->color);
|
|
|
|
// convert text to UNICODE if defined
|
|
wsprintf(text, L"%hs", pTextRec->text);
|
|
|
|
// resolve job info for text
|
|
ResolveJobInfo(text, pJob, pPrinter);
|
|
|
|
// draw text
|
|
DrawText(hDC, text, wcslen(text), &trect, DT_WORDBREAK|AlignTable[pTextRec->align].drawstyle);
|
|
|
|
// restore and delete font
|
|
if (hFont)
|
|
{
|
|
SelectObject(hDC, hOldFont);
|
|
DeleteObject(hFont);
|
|
}
|
|
|
|
pTextRec++;
|
|
}
|
|
|
|
// close file
|
|
UnmapViewOfFile(pFileStart);
|
|
CloseHandle(hFileMapping);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
void SepAttachFirstPage(HDC hDC)
|
|
{
|
|
RECT rectPaper;
|
|
int nID;
|
|
// check if begin sep page is set
|
|
if ((dwOptions & SEPATTACH) && (dwOptions & SEPFIRST || dwOptions & SEPEVERY))
|
|
{
|
|
rectPaper.left = rectPaper.top = 0;
|
|
rectPaper.right = GetDeviceCaps(hDC, HORZRES);
|
|
rectPaper.bottom = GetDeviceCaps(hDC, VERTRES);
|
|
nID = SaveDC(hDC);
|
|
DrawSepPage(hDC, &rectPaper, szAttachFile);
|
|
RestoreDC(hDC, nID);
|
|
}
|
|
}
|
|
|
|
void SepAttachEveryPage(HDC hDC)
|
|
{
|
|
RECT rectPaper;
|
|
int nID;
|
|
// check if begin sep page is set
|
|
if ((dwOptions & SEPATTACH) && (dwOptions & SEPEVERY))
|
|
{
|
|
rectPaper.left = rectPaper.top = 0;
|
|
rectPaper.right = GetDeviceCaps(hDC, HORZRES);
|
|
rectPaper.bottom = GetDeviceCaps(hDC, VERTRES);
|
|
nID = SaveDC(hDC);
|
|
DrawSepPage(hDC, &rectPaper, szAttachFile);
|
|
RestoreDC(hDC, nID);
|
|
}
|
|
}
|
|
|
|
void SepAttachLastPage(HDC hDC)
|
|
{
|
|
RECT rectPaper;
|
|
int nID;
|
|
// check if begin sep page is set
|
|
if ((dwOptions & SEPATTACH) && !(dwOptions & SEPFIRST))
|
|
{
|
|
rectPaper.left = rectPaper.top = 0;
|
|
rectPaper.right = GetDeviceCaps(hDC, HORZRES);
|
|
rectPaper.bottom = GetDeviceCaps(hDC, VERTRES);
|
|
nID = SaveDC(hDC);
|
|
DrawSepPage(hDC, &rectPaper, szAttachFile);
|
|
RestoreDC(hDC, nID);
|
|
}
|
|
}
|