Category : C++ Source Code
Archive   : WICS.ZIP
Filename : PRINTER.CPP

 
Output of file : PRINTER.CPP contained in archive : WICS.ZIP
/*==========================================================================================*/
/* */
/* Windows Interface Construction Set */
/* Version 1.00 */
/* */
/*------------------------------------------------------------------------------------------*/
/* PRINTER.CPP - Windows Printing Classes */
/*------------------------------------------------------------------------------------------*/
/* */
/* Copyright © 1993 by Microdyne Development Technologies */
/* All rights reserved. */
/* */
/*==========================================================================================*/

#include
#include
#include

/*------------------------------------------------------------------------------------------*/
/* Helper functions for the YieldProc procedure. */
/*------------------------------------------------------------------------------------------*/

BOOL ProcessDlgMsg(LPMSG PMessage, PTApplication Application)
{
if (Application->KBHandlerWnd && Application->KBHandlerWnd->HWindow)
return IsDialogMessage(Application->KBHandlerWnd->HWindow, PMessage);
else
return FALSE;
}

BOOL ProcessAccels(LPMSG PMessage, PTApplication Application)
{
return Application->HAccTable &&
TranslateAccelerator(Application->MainWindow->HWindow, Application->HAccTable, PMessage);
}

BOOL ProcessMDIAccels(LPMSG PMessage, PTApplication Application)
{
return (PTWindowsObject)(Application->MainWindow->GetClient()) &&
TranslateMDISysAccel(((PTWindowsObject)(Application->MainWindow->GetClient()))->HWindow, PMessage);
}

BOOL ProcessAppMsg(LPMSG PMessage)
{
PTApplication Application = GetApplicationObject();

if ( Application->KBHandlerWnd )
if ( Application->KBHandlerWnd->IsFlagSet(WB_MDICHILD) )
return ProcessMDIAccels(PMessage, Application) ||
ProcessDlgMsg(PMessage, Application) ||
ProcessAccels(PMessage, Application);
else
return ProcessDlgMsg(PMessage, Application) ||
ProcessMDIAccels(PMessage, Application) ||
ProcessAccels(PMessage, Application);
else
return ProcessMDIAccels(PMessage, Application) ||
ProcessAccels(PMessage, Application);
}

/*------------------------------------------------------------------------------------------*/
/* YieldProc */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* This procedure is used to allow messages waiting in the message queue to be processed */
/* by other windows while the printing process is being done. This allows Windows to */
/* multi-task during the (potentially) long printing process. */
/* */
/*------------------------------------------------------------------------------------------*/

BOOL FAR PASCAL _export YieldProc(BOOL UserAbort)
{
MSG Msg;

while (!UserAbort && PeekMessage(&Msg, NULL, NULL, NULL, PM_REMOVE))
if (!ProcessAppMsg(&Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return (!UserAbort);
}


/*------------------------------------------------------------------------------------------*/
/* Class TPrintedPage */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* TPrintedPage represents the physical printed document which is to be sent to a printer */
/* to be printed. TPrintedPage does the rendering of the document onto the printer. For */
/* every document, or document type, a corresponding TPrintedPage class should be created. */
/* */
/*------------------------------------------------------------------------------------------*/

TPrintedPage::TPrintedPage(Pchar ATitle)
{
HDC hdc ;

Title = new char[lstrlen(ATitle)+1];
lstrcpy (Title, ATitle);

hdc = GetDC (NULL);
ScreenDpi.x = GetDeviceCaps (hdc, LOGPIXELSX);
ScreenDpi.y = GetDeviceCaps (hdc, LOGPIXELSY);
ReleaseDC (NULL, hdc);
}

TPrintedPage::~TPrintedPage()
{
delete Title;
}

BOOL TPrintedPage::IsNextPage()
{
return FALSE;
}

/* This member takes a LOGFONT structure filled with a font created for the screen and
* computes the point size of the font. This routine can be used to obtain a point size
* of a screen font so that the font can be rendered on the page at the appropriate size.
*/

int TPrintedPage::GetPointSize (LOGFONT FAR *lplf)
{
int PixelSize;
int PointSize;
int LogPixelsY;
int RoundFactor;
DWORD lIntermediate;
HDC hdc;

/* The font size will come in pixel height. We must convert pixel height
* to its equivalent point size.
*
* First, if the input parameter is positive, eliminate the internal
* leading value to get the font height.
*/


if ( (int) lplf->lfHeight > 0 )
{
HFONT hCurrentFont ;
TEXTMETRIC tm;

hdc = GetDC (NULL);

hCurrentFont = CreateFontIndirect(lplf);
SelectObject( hdc, hCurrentFont );

GetTextMetrics (hdc, &tm);

PixelSize = lplf->lfHeight - tm.tmInternalLeading ;

ReleaseDC (NULL, hdc);
DeleteObject (hCurrentFont);
}
else
PixelSize = abs(lplf->lfHeight);

/* Now that we have the pixel height, calcuate the point size */

hdc = GetDC (NULL);
LogPixelsY = GetDeviceCaps (hdc, LOGPIXELSY);
ReleaseDC (NULL, hdc);

RoundFactor = LogPixelsY / 2 ;
lIntermediate = 72L * PixelSize + RoundFactor ;
PointSize = (int) (lIntermediate / LogPixelsY );

return PointSize;
}

/*------------------------------------------------------------------------------------------*/
/* Class TPrinterAbortDlg */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* TPrinterAbortDlg represents the "printing" dialog box that is displayed while TPrinter */
/* is printing a TPrintedPage. */
/* */
/*------------------------------------------------------------------------------------------*/

static BOOL RegFails(void *AWindowsObject, void *)
{
return !((PTWindowsObject)AWindowsObject)->Register();
}

TPrinterAbortDlg::TPrinterAbortDlg(PTWindowsObject AParent, PTDialogTemplate ADialogTemplate, Pchar Title, LPSTR Device, LPSTR Port, BOOL& fUserAbort)
: TIndirectDialog(AParent, ADialogTemplate)
{
LPCONTROLDATA lpcd;
LPSTR lpText;
WORD FAR * lpWord;

pfUserAbort = &fUserAbort;
ATitle = Title;
ADevice = Device;

APort = Port;

MaxPage = 0;
CurrentPage = 0;
}

TPrinterAbortDlg::~TPrinterAbortDlg()
{
}

void TPrinterAbortDlg::SetupWindow()
{
char szDevice[80];

TIndirectDialog::SetupWindow();

EnableMenuItem(GetSystemMenu(HWindow, FALSE), SC_CLOSE, MF_GRAYED);

SendDlgItemMsg (ID_TITLE, WM_SETTEXT, 0, (LPARAM) ATitle);

wsprintf (szDevice, "on the %s Printer", ADevice);
SendDlgItemMsg (ID_DEVICE, WM_SETTEXT, 0, (LPARAM) szDevice);

wsprintf (szDevice, "connected to %s", APort);
SendDlgItemMsg (ID_PORT, WM_SETTEXT, 0, (LPARAM) szDevice);

SendDlgItemMsg (ID_PAGEOFPAGE, WM_SETTEXT, 0, (LPARAM) "");
}

void TPrinterAbortDlg::SetMaxPage (int p)
{
char szLine[80];

MaxPage = p;

if ( MaxPage )
{
if ( MaxPage == -1 )
wsprintf (szLine, "Printing page %i . . .", CurrentPage);
else
wsprintf (szLine, "Printing page %i of %i", CurrentPage, MaxPage);

SendDlgItemMsg (ID_PAGEOFPAGE, WM_SETTEXT, 0, (LPARAM) szLine);
}
}

void TPrinterAbortDlg::SetCurrentPage (int p)
{
char szLine[80];

CurrentPage = p;

if ( MaxPage )
{
if ( MaxPage == -1 )
wsprintf (szLine, "Printing page %i . . .", CurrentPage);
else
wsprintf (szLine, "Printing page %i of %i", CurrentPage, MaxPage);

SendDlgItemMsg (ID_PAGEOFPAGE, WM_SETTEXT, 0, (LPARAM) szLine);
}
}

void TPrinterAbortDlg::WMCommand(RTMessage)
{
*pfUserAbort = TRUE;
}

/*------------------------------------------------------------------------------------------*/
/* Class TPrinter */
/*------------------------------------------------------------------------------------------*/
/* */
/* Abstract: */
/* */
/* TPrinter represents the physical printer device. To print a TPrintedPage, send the */
/* TPrintedPage to the TPrinter's Print function. */
/* */
/*------------------------------------------------------------------------------------------*/

TPrinter::TPrinter()
{
hDevNames = NULL;
hDevMode = NULL;

DeviceModule = 0;
Error = 0;

/* Determine the version of Windows...
*
* The following code sets fBefore31 to TRUE if the version of Windows that is currently
* running is a version prior to Version 3.1. If the current version of Windows is
* Version 3.1 or higher, fBefore31 is set to FALSE.
*
* This flag is used throughout the code to impliment version specific code.
*/

if ( LOBYTE(LOWORD(GetVersion())) < 3 )
fBefore31 = TRUE;
else
if ( LOBYTE(LOWORD(GetVersion())) == 3 )
if ( HIBYTE(LOWORD(GetVersion())) == 0 )
fBefore31 = TRUE;
else
fBefore31 = FALSE;
else
fBefore31 = FALSE;

SetDevice(); // Associate with default printer
}

// Deallocate allocated resources

TPrinter::~TPrinter()
{
ClearDevice();
}

// Clears the association of this object with the current device

void TPrinter::ClearDevice()
{
if ( hDevNames != NULL )
{
GlobalFree (hDevNames);
hDevNames = NULL;
}

if ( hDevMode != NULL )
{
GlobalFree (hDevMode);
hDevMode = NULL ;
}

if ((int)DeviceModule >= 32)
{
FreeLibrary(DeviceModule);
DeviceModule = 0;
}

Status = PSTAT_UNASSOCIATED;
}


/* Associates the printer object with a new device. If the ADevice parameter is NULL the
* Windows default printer is used, otherwise, the parameters must be ones contained in the
* [devices] section of the WIN.INI file.
*/

void TPrinter::SetDevice()
{
PRINTDLG pd ;

if ( hDevNames != NULL )
{
GlobalFree (hDevNames);
hDevNames = NULL;
}

if ( hDevMode != NULL )
{
GlobalFree (hDevMode);
hDevMode = NULL ;
}

pd.lStructSize = sizeof(PRINTDLG);
pd.hDevMode = NULL;
pd.hDevNames = NULL;
pd.Flags = PD_RETURNDEFAULT ;

if ( PrintDlg ( &pd ) )
{
hDevMode = pd.hDevMode ;
hDevNames = pd.hDevNames ;
Status = PSTAT_OK;
}
else
Status = PSTAT_UNASSOCIATED;
}

// Configure brings up a dialog as a child of the given window
// to configure the associated printer driver.

void TPrinter::Configure(PTWindowsObject Window)
{
PRINTDLG pd ;

pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = Window->HWindow;
pd.hDevMode = hDevMode;
pd.hDevNames = hDevNames;
pd.hDC = NULL;
pd.Flags = PD_PRINTSETUP | PD_SHOWHELP;
pd.hInstance = NULL;

if ( PrintDlg (&pd) )
{
hDevMode = pd.hDevMode;
hDevNames = pd.hDevNames;
Status = PSTAT_OK;
}
else
Status = PSTAT_UNASSOCIATED;
}

// Returns a device context for the associated printer, 0 if an
// error occurs or Status is != PSTAT_OK

HDC TPrinter::GetDC(PTWindowsObject ParentWin, Rint nCopies, Rint nFromPage, Rint nToPage)
{
PRINTDLG pd ;

pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = ParentWin->HWindow;
pd.hDevMode = hDevMode;
pd.hDevNames = hDevNames;
pd.hDC = NULL;
pd.nCopies = nCopies;
pd.nFromPage = nFromPage;
pd.nToPage = nToPage;
pd.nMinPage = 1;
pd.nMaxPage = 9999;
pd.Flags = PD_RETURNDC | PD_ALLPAGES | PD_SHOWHELP | PD_USEDEVMODECOPIES ;
pd.hInstance = NULL;

if ( Status == PSTAT_OK )
{
if ( PrintDlg (&pd) )
{
hDevMode = pd.hDevMode;
hDevNames = pd.hDevNames;

nFromPage = pd.nFromPage;
nToPage = pd.nToPage;
nCopies = pd.nCopies;

return pd.hDC ;
}
}

return 0;
}


BOOL TPrinter::Print(PTWindowsObject ParentWin, PTPrintedPage Printout)
{
typedef BOOL (FAR PASCAL *PTYieldProc)( BOOL );

int i;
int nCopies;
int nFromPage, nToPage;
int nMaxPage;
PTYieldProc YieldProcInst;
WORD PageNumber;
LPSTR lpName;
LPSTR Device;
LPSTR Port;
DEVNAMES FAR * lpDevNames;
PTDialogTemplate ADialogTemplate;

BOOL result = FALSE; // Assume error occurred
fUserAbort = FALSE; // Assume the user does not wish to cancel the print
Error = 0; // Clear Error Flag

/* Make sure all the required objects exist and that they are properly initialized...
*/

if ( Printout == NULL )
return result;

if ( ParentWin == NULL )
return result;

if ( Status != PSTAT_OK )
{
Error = SP_ERROR;
ReportError(ParentWin, Printout);
return result;
}

/* Get a handle to the Device Context for the printer...
*/

nMaxPage = Printout->GetMaxPage();

nCopies = 1;
nFromPage = 1 ;
nToPage = ( nMaxPage < 1 ) ? 9999 : nMaxPage ;
PrnDC = GetDC(ParentWin, nCopies, nFromPage, nToPage);

if ( PrnDC == 0 )
return result;

/* Display the "Printing" dialog box...
*/

lpDevNames = (DEVNAMES FAR *) GlobalLock(hDevNames);
lpName = (Pchar) lpDevNames ;
Device = (lpName + lpDevNames->wDeviceOffset);
Port = (lpName + lpDevNames->wOutputOffset);

ADialogTemplate = new TDialogTemplate ( DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
84, 46, 142, 92, "BorDlg", "Print");

ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, -1, 9, 9, 124, 8, DTCS_STATIC, "Printing");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 101, 9, 17, 124, 8, DTCS_STATIC, "%s");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 102, 9, 25, 124, 8, DTCS_STATIC, "on the %s Printer");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 103, 9, 33, 124, 8, DTCS_STATIC, "connected to %s");
ADialogTemplate->AddControl ( SS_CENTER | WS_VISIBLE | WS_CHILD | WS_GROUP, 104, 9, 49, 124, 8, DTCS_STATIC, "Printing page %i on %i");
ADialogTemplate->AddControl ( WBS_DEFPUSHBUTTON | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE | WS_TABSTOP,
IDCANCEL, 55, 69, 33, 15, "WICSButton", NULL);
ADialogTemplate->AddControl ( 1 | WS_CHILD | WS_VISIBLE, -1, 6, 6, 130, 56, "BorShade", NULL);

PTPrinterAbortDlg Dlg = (PTPrinterAbortDlg) GetApplicationObject()->MakeWindow(
new TPrinterAbortDlg(ParentWin, ADialogTemplate, Printout->GetTitle(), Device, Port, fUserAbort) );

Dlg->SetMaxPage ( nMaxPage );
Dlg->SetCurrentPage (nFromPage);

GlobalUnlock (hDevNames);

if ( Dlg == NULL )
{
DeleteDC(PrnDC);
return result;
}

/* Disable the parent window, create the Yield Procedure and call it to enable screen
* Painting.
*/

EnableWindow(ParentWin->HWindow, FALSE);

YieldProcInst = (PTYieldProc) MakeProcInstance( (FARPROC) YieldProc, GetApplicationObject()->hInstance);

if ( !(*YieldProcInst)(fUserAbort) )
Error = SP_APPABORT;

// Get the page size

PageSize.x = GetDeviceCaps(PrnDC, HORZRES);
PageSize.y = GetDeviceCaps(PrnDC, VERTRES);

dpi.x = GetDeviceCaps(PrnDC, LOGPIXELSX);
dpi.y = GetDeviceCaps(PrnDC, LOGPIXELSY);

if ( !(*YieldProcInst)(fUserAbort) )
Error = SP_APPABORT;

for ( i = 0 ; i < nCopies && !Error ; i++ )
{
Flags = PFUNC_BOTH;
PageNumber = nFromPage;

if ( fBefore31 )
{
if ((Error = Escape(PrnDC, STARTDOC, strlen(Printout->GetTitle()), Printout->GetTitle(), NULL)) == 0 )
{
BOOL fMorePages = TRUE;

while ( fMorePages && !Error )
{
Dlg->SetCurrentPage (PageNumber);

(*YieldProcInst)(fUserAbort);

if ( fUserAbort )
Error = SP_APPABORT;
else
{
Printout->PrintPage(PrnDC, PageNumber, PageSize, dpi);

if ((Error = Escape(PrnDC, NEWFRAME, 0, NULL, NULL)) == 0 )
{
PageNumber++;
fMorePages = Printout->IsNextPage();
}
}

if ( PageNumber > nToPage )
fMorePages = FALSE;
}

if ( Error )
Escape(PrnDC, ABORTDOC, 0, NULL, NULL);
else
Escape(PrnDC, ENDDOC, 0, NULL, NULL);
}
}
else
{
DOCINFO DocInfo;
BOOL fMorePages = TRUE ;

DocInfo.cbSize = sizeof(DOCINFO);
DocInfo.lpszDocName = Printout->GetTitle();
DocInfo.lpszOutput = NULL;

Error = ( StartDoc (PrnDC, &DocInfo) > 0 ) ? 0 : SP_ERROR ;

while ( fMorePages && !Error )
{
Dlg->SetCurrentPage (PageNumber);

Error = ( StartPage (PrnDC) > 0 ) ? 0 : SP_ERROR ;

if ( !Error )
{
Printout->PrintPage(PrnDC, PageNumber, PageSize, dpi);

Error = EndPage (PrnDC);

if ( Error > 0 )
Error = 0 ;

if ( !Error )
{
/* Call the Abort Proc between pages
*/

(*YieldProcInst)(fUserAbort);

if ( fUserAbort )
Error = SP_APPABORT;

PageNumber++;
fMorePages = Printout->IsNextPage();

}
}

if ( PageNumber > nToPage )
fMorePages = FALSE;
}

if ( Error )
AbortDoc (PrnDC);
else
Error = EndDoc (PrnDC);
}
}

// Free allocated resources

FreeProcInstance((FARPROC) YieldProcInst);
EnableWindow(ParentWin->HWindow, TRUE);
delete Dlg;
DeleteDC(PrnDC);

if ( Error & SP_NOTREPORTED )
ReportError(ParentWin, Printout);

result = (Error > 0) && (!fUserAbort);

fUserAbort = FALSE;

return result;
}

void TPrinter::ReportError(PTWindowsObject ParentWin, PTPrintedPage Printout)
{
PTDialogTemplate ADialogTemplate;
Pchar Title;
Pchar ErrorCaption;
Pchar ErrorMsg;
Pchar ErrorTemplate = "'%s' was not printed. Reason: %s.";
Pchar ErrorText = new char [128];

switch (Error)
{
case SP_APPABORT:
ErrorMsg = "Printing canceled";
break;

case SP_ERROR:
ErrorMsg = "Error encountered during print";
break;

case SP_OUTOFDISK:
ErrorMsg = "Out of disk space";
break;

case SP_OUTOFMEMORY:
ErrorMsg = "Out of memory";
break;

case SP_USERABORT:
ErrorMsg = "Printing aborted in Print Manager";
break;

default:
ErrorMsg = "Unknown error";
break;
}

Title = Printout->GetTitle();
ErrorCaption = "Print Error";

wsprintf(ErrorText, ErrorTemplate, Title, ErrorMsg);

ADialogTemplate = new TDialogTemplate ( DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
18, 18, 217, 92, "BorDlg", Title);

ADialogTemplate->AddControl ( SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 100, 35, 15, 170, 8, DTCS_STATIC, ErrorCaption);
ADialogTemplate->AddControl ( SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 101, 12, 32, 193, 29, DTCS_STATIC, ErrorText);
ADialogTemplate->AddControl ( SS_ICON | WS_CHILD | WS_VISIBLE | WS_GROUP, 102, 12, 11, 16, 16, DTCS_STATIC, "");
ADialogTemplate->AddControl ( WBS_DEFPUSHBUTTON | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE | WS_TABSTOP,
IDOK, 92, 72, 33, 15, "WICSButton", NULL);
ADialogTemplate->AddControl ( 1 | WS_CHILD | WS_VISIBLE, -1, 7, 7, 203, 58, "BorShade", NULL);

GetApplicationObject()->ExecDialog( new TPrinterErrorDlg(ParentWin, ADialogTemplate) );

delete ErrorText;
}


  3 Responses to “Category : C++ Source Code
Archive   : WICS.ZIP
Filename : PRINTER.CPP

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/