Code:
int APIENTRY Print (
HWND hWnd)
{
HDC hdc; // printer DC
char sz[32];
int cch;
int nChars; // number of chars in line
WORD Offset; // line offset into MLE buffer
PSTR pch; // current line
PSTR pchEOL; // pointer to end of string from MLE
PSTR pNextLine; // next bit of line to try printing; leftovers
WORD LineNum; // current line number
WORD wpNumLines; // number of lines to print
HANDLE hEditData; // handle to MLE text HGLOBAL
DWORD dy;
int yCurpos; // current y-position rel. to top margin
int xCurpos; // current x-position rel. to left margin
int nPixelsLeft; // number of pixels left to print in
int nLinesPerPage; // not inc. header and footer
int guess; // number of chars that can print
int nPrintedLines;
double xDl; // stuff for calculating margins
double xDr; // "
double yDt; // "
double yDb; // "
double xLpix; // "
double xRpix; // "
double yTpix; // "
double yBpix; // "
char *stopstring; // "
int count; // counter for strings larger than margins
static const char letter[] = " ";
WORD fError = TRUE;
HWND hWndEdit = (HWND)GetWindowLong(hWnd, WL_HWNDEDIT);
LPSTR lpEditData;
LONG wLength; // WPARAM
TEXTMETRIC Metrics;
SIZE sSize;
fAbort = FALSE;
// Create the job title by loading the title string from STRINGTABLE
cch = LoadString ((HANDLE)GetModuleHandle (NULL), IDS_PRINTJOB, sz, sizeof(sz));
szTitle = sz + cch;
cch += GetWindowText (hWnd, sz + cch, 32 - cch);
sz[31] = 0;
// Initialize the printer
hdc = GetPrinterDC();
if (!hdc)
AlertBox (hWnd, MB_OK | MB_ICONHAND,
IDS_PRINTERROR,
lpszYyz);
// Retrieve margin strings from pagesetup dialog and convert to double
xDl = strtod (szLft, &stopstring); // convert char string to double
xDr = strtod (szRt, &stopstring);
yDt = strtod (szTop, &stopstring);
yDb = strtod (szBtm, &stopstring);
// Width of the display, in pixels
xPrintRes = GetDeviceCaps (hdc, HORZRES);
// Height of the display, in raster lines
yPrintRes = GetDeviceCaps (hdc, VERTRES);
// Pixels per inch for margins
xLpix = xDl * GetDeviceCaps (hdc, LOGPIXELSX);
xRpix = xDr * GetDeviceCaps (hdc, LOGPIXELSX);
yTpix = yDt * GetDeviceCaps (hdc, LOGPIXELSY);
yBpix = yDb * GetDeviceCaps (hdc, LOGPIXELSY);
// Round off double so we can store as integer
lMargin = (int)floor(xLpix + 0.5);
rMargin = (int)floor(xRpix + 0.5);
tMargin = (int)floor(yTpix + 0.5);
bMargin = (int)floor(yBpix + 0.5);
// Offset of the printable area from top hand corner, in device units
xPhysOff = GetDeviceCaps (hdc, PHYSICALOFFSETX);
yPhysOff = GetDeviceCaps (hdc, PHYSICALOFFSETY);
// Error handling for margins just in
// case someone inputs an invalid character
if (lMargin <= xPhysOff)
lMargin = xPhysOff * 2;
if (rMargin <= xPhysOff)
rMargin = xPhysOff * 2;
if (tMargin <= yPhysOff)
tMargin = yPhysOff * 2;
if (bMargin <= yPhysOff)
bMargin = yPhysOff * 2;
// compute margins in pixels
dxLeft = (lMargin - xPhysOff);
dxRight = (rMargin - xPhysOff);
dyTop = (tMargin - yPhysOff);
dyBottom = (bMargin - yPhysOff);
SetBkMode (hdc, TRANSPARENT);
// Calculate necessary metrics for file
GetTextMetrics (hdc, &Metrics);
yPrintChar = Metrics.tmHeight + Metrics.tmExternalLeading ; // the height
tabSize = Metrics.tmAveCharWidth * 8; // 8 ave char width pixels for tabs
// Number of lines on a page with margins
nLinesPerPage = ((yPrintRes - dyTop - dyBottom) / yPrintChar);
// Disable the main application window and create the Cancel dialog
EnableWindow (hWnd, FALSE);
hCancelDlg = CreateDialog ((HANDLE)GetModuleHandle (NULL),
IDD_CANCELDLG,
hWnd,
(DLGPROC) AbortDlgProc);
if (!hCancelDlg)
return IDS_CANCELDLGFAILED;
// job started, so display cancel dialog
ShowWindow (hCancelDlg, SW_SHOW);
UpdateWindow (hCancelDlg);
// set AbortProc callback
SetAbortProc (hdc, AbortProc);
if (!AbortProc)
{
// on error, clean up and go away
DestroyWindow (hCancelDlg);
DeleteDC (hdc);
return IDS_SETABORTPROCFAILED;
}
// Initialize the document
if (Escape (hdc, STARTDOC, cch, (LPSTR)sz, NULL) < 0)
{
// on error, clean up and go away
DestroyWindow (hCancelDlg);
DeleteDC (hdc);
return IDS_STARTDOCFAILED;
}
// Get the height of one line and the height of a page
{
SIZE sLine;
GetTextExtentPoint (hdc, letter, 1, &sLine);
dy = sLine.cy;
}
// Get the lines in document and a handle to the text buffer
LineNum = 0;
yCurpos = 0;
xCurpos = 0;
nPrintedLines = 0;
wpNumLines = (WORD)SendMessage (hWndEdit, EM_GETLINECOUNT, 0, 0L);
// length in bytes of edit control text
wLength = SendMessage (hWndEdit, WM_GETTEXTLENGTH, 0, 0L);
wLength++;
hEditData = (HANDLE)LocalAlloc (LHND, (DWORD)wLength);
lpEditData = (LPSTR)LocalLock (hEditData);
SendMessage (hWndEdit, WM_GETTEXT, wLength, (LPARAM)lpEditData);
// Print text line by line from top to bottom
while (LineNum < wpNumLines) {
count = 0; // reset counter for textout handling strings larger than margins
// If at end of page, start a new page
if (yCurpos + (int)dy > (yPrintRes - dyTop - dyBottom)) {
// Reached the end of a page. Tell the device driver to eject a
// page
//
if (Escape (hdc, NEWFRAME, 0, NULL, NULL) < 0 || fAbort)
{
DestroyWindow (hCancelDlg);
LocalUnlock (hEditData);
LocalFree (hEditData);
DeleteDC (hdc);
return IDS_PRINTABORTED;
}
yCurpos = 0;
nPrintedLines = 0; // reset lines printed
}
// Print out header if we are about to print
// the first line on the page
if (nPrintedLines == 0) {
// print header if one exists
yCurpos = 0;
if (PrintHeader(hdc))
yCurpos = 0;
xCurpos = 0;
}
// Get the length and position of the line in the buffer
// and lock from that offset into the buffer
Offset = (WORD)SendMessage (hWndEdit, EM_LINEINDEX, LineNum, 0L);
nChars = (WORD)SendMessage (hWndEdit, EM_LINELENGTH, Offset, 0L); // length in bytes=chars
pch = (PSTR)LocalLock(hEditData) + Offset;
pchEOL = ((PSTR)LocalLock(hEditData) + Offset) + nChars;
// find what to print - up to EOL
pNextLine = pch; // find end of line
while (pNextLine != pchEOL)
pNextLine++; // increment till EOL
// find out how many characters will fit on line
nPixelsLeft = xPrintRes - dxRight - dxLeft - xCurpos; // in logical units
GetTextExtentExPoint (hdc, pch, pNextLine-pch,
nPixelsLeft, &guess, NULL, &sSize);
do {
if (nChars > guess) {
// Print the current line and unlock the text handle
TabbedTextOut (hdc, dxLeft+xCurpos, yCurpos+dyTop, (LPSTR)pch, guess,
0, NULL, dxLeft+xCurpos);
pch += guess; // add quantity of guess to pch; limit set by nPixelsLeft
nChars -= guess; // how many chars left to print in current line
yCurpos += dy; // move down the page one line
xCurpos = 0; // reset x position to zero
count++; // increment by one every time string is larger than margins
if (nChars <= guess) {
guess = nChars; // put remaining char count in guess
// print remaining characters on next line
TabbedTextOut (hdc, dxLeft+xCurpos, yCurpos+dyTop, (LPSTR)pch, guess,
0, NULL, dxLeft+xCurpos);
pch += guess;
nChars -= guess;
// since string was larger than the margin
// calculate the x starting point for the
// next string on this current line
xCurpos += (sSize.cx - nPixelsLeft*count); // account for printing
LineNum++; // increment line count by one here since
// string was larger than horizontal margin
}
}
else {
// If string is smaller or equal to nPixelsLeft
TabbedTextOut (hdc, dxLeft+xCurpos, yCurpos+dyTop, (LPSTR)pch, guess,
0, NULL, dxLeft+xCurpos);
xCurpos = 0; // reset x position to zero
yCurpos += dy; // move down the page one line
LineNum++; // increment line count by one
}
LocalUnlock (hEditData);
// Test and see if the Abort flag has been set. If yes, exit.
if (fAbort)
goto getout2;
// Increment line count and line printed
nPrintedLines++; // increment lines printed by one
// If remaining chars is still larger than margins
if (nChars > guess)
guess = guess;
} while (guess < nChars); // end while/do loop
} // end of while (LineNum < wpNumLines) loop
// Eject the last page.
if (Escape (hdc, NEWFRAME, 0, NULL, NULL) < 0)
goto getout2;
// Complete the document.
if (Escape (hdc, ENDDOC, 0, NULL, NULL) < 0) {
getout2:
// Ran into a problem before NEWFRAME? Abort the document
Escape (hdc, ABORTDOC, 0, NULL, NULL);
}
else
fError=FALSE;
// Error? make sure the user knows...
if (fError)
AlertBox (hWnd, MB_OK | MB_ICONEXCLAMATION, IDS_PRINTERROR, (LPSTR)szTitle);
// end cancel dialog box, clean up, re-enable main app. window and exit
DestroyWindow (hCancelDlg);
DeleteDC(hdc);
LocalUnlock (hEditData);
LocalFree (hEditData);
EnableWindow (hWnd, TRUE);
return TRUE;
}
In addition, I posted this code just in case some of the people who viewed this post where looking for answers to there own printer code problems in C.