|
|
/* File: D:\WACKER\tdll\printset.c (Created: 02-Feb-1994)
* * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 11 $ * $Date: 7/08/02 6:46p $ */ #include <windows.h>
#pragma hdrstop
#include <stdio.h>
#include <limits.h>
#include <term\res.h>
#include "stdtyp.h"
#include "mc.h"
#include "misc.h"
#include "assert.h"
#include "print.h"
#include "print.hh"
#include "globals.h"
#include "session.h"
#include "term.h"
#include "tdll.h"
#include "htchar.h"
#include "load_res.h"
#include "open_msc.h"
#include "open_msc.h"
#include "sf.h"
#include "file_msc.h"
static int printsetPrintToFile(const HPRINT hPrint); static UINT_PTR APIENTRY printPageSetupHook( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam );
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printsetSetup * * DESCRIPTION: * This function is used to display the common print dialogs. * * ARGUMENTS: * hPrint - An external print handle. * hwnd - owner window handle * * RETURNS: * void * */ void printsetSetup(const HPRINT hPrint, const HWND hwnd) { const HHPRINT hhPrint = (HHPRINT)hPrint; #ifdef INCL_USE_NEWPRINTDLG
PRINTDLGEX pd; HRESULT hResult; #else
PRINTDLG pd; #endif
LPDEVNAMES pstDevNames; PDEVMODE pstDevMode;
TCHAR *pszPrinterName; TCHAR *pTemp; DWORD dwSize; DWORD dwError;
#if defined(_DEBUG)
TCHAR ach[100]; #endif
if (hhPrint == 0) { assert(FALSE); return; }
// Initialize basic structure elements.
//
#ifdef INCL_USE_NEWPRINTDLG
memset (&pd, 0, sizeof(PRINTDLGEX)); pd.lStructSize = sizeof(PRINTDLGEX); pd.Flags2 = 0; pd.nStartPage = START_PAGE_GENERAL; pd.dwResultAction = 0; #else
memset (&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); #endif
pd.Flags = PD_NOWARNING | PD_NOPAGENUMS; pd.hwndOwner = hwnd;
if (SendMessage(sessQueryHwndTerminal(hhPrint->hSession), WM_TERM_Q_MARKED, 0, 0)) { pd.Flags |= PD_SELECTION; }
// Use the previously stored information to initialize the print
// common dialogs. printGetDefaults initializes this information
// when a print handle is created.
//
if (hhPrint->pstDevMode) { // Allocate memory for the DEVMODE information and then
// initialize it with the stored values from the Print Handle.
//
dwSize = hhPrint->pstDevMode->dmSize + hhPrint->pstDevMode->dmDriverExtra;
if ((pd.hDevMode = GlobalAlloc(GMEM_MOVEABLE, dwSize))) { if ((pstDevMode = GlobalLock(pd.hDevMode))) { if (dwSize) MemCopy(pstDevMode, hhPrint->pstDevMode, dwSize); GlobalUnlock(pd.hDevMode); } } }
if (hhPrint->pstDevNames) { // Allocate memory for the DEVNAMES structure in pd, then
// initialize it with the stored values from the Print Handle.
// This sequence determines the variable structure size of
// DEVNAMES.
//
pTemp = (TCHAR *)hhPrint->pstDevNames; pTemp += hhPrint->pstDevNames->wOutputOffset; pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)hhPrint->pstDevNames);
if ((pd.hDevNames = GlobalAlloc(GMEM_MOVEABLE, dwSize))) { if ((pstDevNames = GlobalLock(pd.hDevNames))) { if (dwSize) MemCopy(pstDevNames, hhPrint->pstDevNames, dwSize); GlobalUnlock(pd.hDevNames); } } }
// Initialize the PrintToFilename array every time before we go
// into the dialog.
//
TCHAR_Fill(hhPrint->achPrintToFileName, TEXT('\0'), sizeof(hhPrint->achPrintToFileName) / sizeof(TCHAR));
// Display the dialog.
//
#ifdef INCL_USE_NEWPRINTDLG
pd.Flags2 = 0; hResult = PrintDlgEx( &pd ); if ( hResult != S_OK) #else
if (!PrintDlg(&pd)) #endif
{ dwError = CommDlgExtendedError();
#if defined(_DEBUG)
if (dwError != 0) { wsprintf(ach, "PrintDlg error 0x%x", dwError); MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK); } #endif
// If user canceled, we're done
//
if (dwError == 0) goto Cleanup;
// Some error occured, try to bring-up dialog with default
// data.
//
if (pd.hDevNames) { GlobalFree(pd.hDevNames); pd.hDevNames = 0; }
if (pd.hDevMode) { GlobalFree(pd.hDevMode); pd.hDevMode = 0; }
pd.Flags &= ~PD_NOWARNING;
#ifdef INCL_USE_NEWPRINTDLG
hResult = PrintDlgEx(&pd); if ( hResult != S_OK) #else
if (!PrintDlg(&pd)) #endif
{ #if defined(_DEBUG)
dwError = CommDlgExtendedError();
if (dwError != 0) { wsprintf(ach, "PrintDlg error 0x%x", dwError); MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK); } #endif
goto Cleanup; } }
#ifdef INCL_USE_NEWPRINTDLG
// in the NT 5 print dialog, if the user cancels, the print dialog returns S_OK.
// So we need to check the result code to see if we should save the settings.
if ( pd.dwResultAction == PD_RESULT_CANCEL ) goto Cleanup; #endif
// Store the flags returned from the dialog in the Print Handle.
// This has several pieces of info that will be used by the actual
// printing routines (i.e. print all, print selected).
//
hhPrint->nSelectionFlags = pd.Flags;
// Store the printer name and location in the Print Handle
// every time.
//
pstDevNames = GlobalLock(pd.hDevNames); if (!pstDevNames) { assert(FALSE); GlobalUnlock(pd.hDevMode); goto Cleanup; } pszPrinterName = (TCHAR *)pstDevNames; pszPrinterName += pstDevNames->wDeviceOffset; StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN); GlobalUnlock(pd.hDevNames);
// Save the DEVMODE information in the Print Handle. This memory
// must be freed and allocated every time as the size of the
// DEVMODE structure changes.
//
pstDevMode = GlobalLock(pd.hDevMode); dwSize = pstDevMode->dmSize + pstDevMode->dmDriverExtra;
if (hhPrint->pstDevMode) free(hhPrint->pstDevMode);
hhPrint->pstDevMode = (LPDEVMODE)malloc(dwSize);
if (hhPrint->pstDevMode == 0) { assert(FALSE); GlobalUnlock(pd.hDevMode); goto Cleanup; }
if (dwSize) MemCopy(hhPrint->pstDevMode, pstDevMode, dwSize); GlobalUnlock(pd.hDevMode);
// Save the DEVNAMES information in the Print Handle. Because the
// size of the information in this structure varies, it is freed and
// allocated each time it is saved.
//
pstDevNames = GlobalLock(pd.hDevNames);
// Determine the size of the structure.
//
pTemp = (TCHAR *)pstDevNames; pTemp += pstDevNames->wOutputOffset; pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)pstDevNames);
if (hhPrint->pstDevNames) { free(hhPrint->pstDevNames); hhPrint->pstDevNames = NULL; }
hhPrint->pstDevNames = (LPDEVNAMES)malloc(dwSize);
if (hhPrint->pstDevNames == 0) { assert(0); GlobalUnlock(pd.hDevNames); goto Cleanup; }
if (dwSize) MemCopy(hhPrint->pstDevNames, pstDevNames, dwSize); GlobalUnlock(pd.hDevNames);
// Has the user selected Print To File? Yes, you do need to look
// for the string "FILE:" to determinae this! If so, we will put
// up our own common dialog to get the save as file name.
//
pTemp = (CHAR *)hhPrint->pstDevNames + hhPrint->pstDevNames->wOutputOffset;
if (StrCharCmp("FILE:", pTemp) == 0) { if (printsetPrintToFile(hPrint) != 0) { goto Cleanup; } }
#ifdef INCL_USE_NEWPRINTDLG
// in the NT 5 print dialog, if the user cancels or click 'apply', the print dialog returns S_OK.
// So we need to check the result code to see if we should now print
if ( pd.dwResultAction != PD_RESULT_PRINT ) goto Cleanup; #endif
// Print the selected text.
//
printsetPrint(hPrint);
// Cleanup any memory that may have been allocated.
//
Cleanup:
if (pd.hDevNames) GlobalFree(pd.hDevNames);
if (pd.hDevMode) GlobalFree(pd.hDevMode);
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printsetPrint * * DESCRIPTION: * This function prints the selected text from then terninal and/or the * backscroll buffer. * * ARGUMENTS: * hPrint - An external Print handle. * * RETURNS: * void * */ void printsetPrint(const HPRINT hPrint) { const HHPRINT hhPrint = (HHPRINT)hPrint; int iLineHeight; int iVertRes; int iStatus, nRet; int iPrintableWidth;
RECT stRect;
DWORD dwCnt, dwTime1, dwTime2; POINT pX, pY;
ECHAR *pechBuf; TCHAR *pV, *pLS, *pLE, *pEnd, *pNext;
if (hPrint == 0) { assert(FALSE); return; }
// Get the text to print for selected text.
//
if (hhPrint->nSelectionFlags & PD_SELECTION) { if (!CopyMarkedTextFromTerminal(hhPrint->hSession, &pV, &dwCnt, FALSE)) { if (pV) { free(pV); pV = NULL; } assert(FALSE); return; }
if (dwCnt == 0) { if (pV) { free(pV); pV = NULL; } assert(FALSE); return; } }
// Get the text to print into a buffer for an ALL selection.
//
else { pX.x = 0; pX.y = INT_MIN;
pY.x = INT_MAX; pY.y = INT_MAX;
nRet = CopyTextFromTerminal(hhPrint->hSession, &pX, &pY, &pechBuf, &dwCnt, FALSE); if (nRet == FALSE) { if (pechBuf) { free(pechBuf); pechBuf = NULL; }
assert(FALSE); return; }
// Strip Out Any repeated Characters in the string
StrCharStripDBCSString(pechBuf, (long)StrCharGetEcharByteCount(pechBuf), pechBuf);
// hMem currently points to an array of ECHAR's, convert this to
// TCHARS before giving the results to the caller.
pV = malloc((ULONG)StrCharGetEcharByteCount(pechBuf) + 1);
CnvrtECHARtoMBCS(pV, (ULONG)StrCharGetEcharByteCount(pechBuf) + 1, pechBuf,StrCharGetEcharByteCount(pechBuf)+1); // mrw:5/17/95
free(pechBuf); pechBuf = NULL; dwCnt = (ULONG)StrCharGetByteCount(pV); }
// Create the DC.
//
hhPrint->hDC = printCtrlCreateDC(hPrint);
if (hhPrint->hDC == 0) { if (pV) { free(pV); pV = NULL; }
assert(FALSE); return; }
printSetFont( hhPrint ); printSetMargins( hhPrint );
// Initialize the DC. Set the abort flag, determine the number
// of lines per page, get the title of the window which will be used
// as the name of the document to print.
//
hhPrint->fError = FALSE; hhPrint->fUserAbort = FALSE; hhPrint->nLinesPrinted = 0; hhPrint->nPage = 1; EnableWindow(sessQueryHwnd(hhPrint->hSession), FALSE);
GetTextMetrics(hhPrint->hDC, &hhPrint->tm);
iLineHeight = hhPrint->tm.tmHeight + hhPrint->tm.tmExternalLeading; iVertRes = GetDeviceCaps(hhPrint->hDC, VERTRES); iVertRes -= (hhPrint->marginsDC.top + hhPrint->marginsDC.bottom);
if (iLineHeight == 0) //need to prevent a divide by zero error
iLineHeight = 1;
hhPrint->nLinesPerPage = max( iVertRes / iLineHeight, 1);
GetWindowText(sessQueryHwnd(hhPrint->hSession), hhPrint->achDoc, sizeof(hhPrint->achDoc));
// Create the Print Abort Dialog.
//
hhPrint->lpfnPrintDlgProc = printsetDlgProc;
hhPrint->hwndPrintDlg = DoModelessDialog(glblQueryDllHinst(), MAKEINTRESOURCE(IDD_PRINTABORT), sessQueryHwnd(hhPrint->hSession), hhPrint->lpfnPrintDlgProc, (LPARAM)hhPrint);
// Setup the Print Abort Procedure.
//
hhPrint->lpfnPrintAbortProc = printsetAbortProc;
nRet = SetAbortProc(hhPrint->hDC, (ABORTPROC)hhPrint->lpfnPrintAbortProc);
// Initialize and start the document.
//
hhPrint->di.cbSize = sizeof(DOCINFO); hhPrint->di.lpszDocName = hhPrint->achDoc; hhPrint->di.lpszDatatype = NULL; hhPrint->di.fwType = 0;
// Initialize di.lpszOutput for either printing to a file,
// or to a printer.
//
if (hhPrint->achPrintToFileName[0] == TEXT('\0')) { hhPrint->di.lpszOutput = (LPTSTR)NULL; } else { hhPrint->di.lpszOutput = (LPTSTR)hhPrint->achPrintToFileName; }
// StartDoc.
//
iStatus = StartDoc(hhPrint->hDC, &hhPrint->di); DbgOutStr("\r\nStartDoc: %d", iStatus, 0, 0, 0, 0); if (iStatus == SP_ERROR) { printCtrlDeleteDC(hPrint);
if (IsWindow(hhPrint->hwndPrintDlg)) DestroyWindow(hhPrint->hwndPrintDlg);
printTellError(hhPrint->hSession, hPrint, iStatus);
assert(FALSE); return; }
// StartPage.
// Get more info on this.
//
iStatus = StartPage(hhPrint->hDC); DbgOutStr("\r\nStartPage: %d", iStatus, 0, 0, 0, 0); printSetFont( hhPrint );
if (iStatus == SP_ERROR) { assert(FALSE); }
// Move through the buffer that contins the text to print, and
// get it done.
//
// pLS = pointerLineStart
// pLE = pointerLineEnd
// pEnd = pointerEndOfBuffer
//
pLS = pV; pLE = pV; pEnd = pV + (dwCnt - 1);
while ((pLE <= pEnd) && !hhPrint->fError && !hhPrint->fUserAbort) { if (*pLE == TEXT('\r') || *pLE == TEXT('\0')) { pNext = pLE;
// Remove trailing CR\LF\NULL as these mean nothing to
// a Windows DC.
//
while (pLE >= pLS) { if (*pLE == TEXT('\r') || *pLE == TEXT('\n') || *pLE == TEXT('\0')) { pLE--; continue; }
break; }
// Send the text out to the printer, bump the line count.
//
hhPrint->cx = hhPrint->marginsDC.left; hhPrint->cy = hhPrint->nLinesPrinted * hhPrint->tm.tmHeight + hhPrint->marginsDC.top;
iPrintableWidth = GetDeviceCaps( hhPrint->hDC, HORZRES ); iPrintableWidth -= hhPrint->marginsDC.right;
stRect.left = hhPrint->cx; stRect.right = iPrintableWidth; stRect.top = hhPrint->cy; stRect.bottom = hhPrint->cy + hhPrint->tm.tmHeight;
ExtTextOut( hhPrint->hDC, hhPrint->cx, hhPrint->cy, ETO_CLIPPED, &stRect, pLS, (UINT)((pLE - pLS) + 1), NULL );
hhPrint->nLinesPrinted += 1;
if (hhPrint->nLinesPrinted == 1) { DbgOutStr("\r\nPost WM_PRINT_NEWPAGE", 0, 0, 0, 0, 0); PostMessage(hhPrint->hwndPrintDlg, WM_PRINT_NEWPAGE, 0, (LPARAM)hhPrint); }
// Check for a new page condition.
//
if ((hhPrint->nLinesPrinted >= hhPrint->nLinesPerPage)) { hhPrint->nLinesPrinted = 0; hhPrint->nPage++;
iStatus = EndPage(hhPrint->hDC); if (iStatus < 0) { hhPrint->fError = TRUE; printTellError(hhPrint->hSession, hPrint, iStatus); } else { iStatus = StartPage(hhPrint->hDC); DbgOutStr("\r\nStartPage: %d", iStatus, 0, 0, 0, 0); printSetFont( hhPrint );
if (iStatus <= 0) { DbgShowLastError(); printTellError(hhPrint->hSession, hPrint, iStatus); } } }
pLS = pLE = (pNext + 1); continue; }
pLE++; }
// Did we issue an EndPage for this page yet?
//
if (hhPrint->nLinesPrinted > 0) { iStatus = EndPage(hhPrint->hDC); DbgOutStr("\r\nEndPage: %d", iStatus, 0, 0, 0, 0); if (iStatus <= 0) { DbgShowLastError(); printTellError(hhPrint->hSession, hPrint, iStatus); } }
// Call EndDoc.
//
iStatus = EndDoc(hhPrint->hDC); if (iStatus <= 0) { DbgShowLastError(); DbgOutStr("\r\nEndDoc: %d", iStatus, 0, 0, 0, 0); printTellError(hhPrint->hSession, hPrint, iStatus); }
// Final cleanup before exit.
//
if (!hhPrint->fUserAbort) { dwTime1 = (DWORD)GetWindowLongPtr(hhPrint->hwndPrintDlg, GWLP_USERDATA); dwTime2 = GetTickCount(); if (dwTime2 - dwTime1 < 3000) Sleep( 3000 - (dwTime2 - dwTime1));
EnableWindow(sessQueryHwnd(hhPrint->hSession), TRUE); DestroyWindow(hhPrint->hwndPrintDlg); }
printCtrlDeleteDC(hPrint);
if (pV) { free(pV); pV = NULL; }
return; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printsetAbortProc * * DESCRIPTION: * This is the print abort procedure used when printing selected text. * Note that this abort proc is not used for print echo, or for host * directed printing. * * ARGUMENTS: * HDC - A printer DC. * nCode - The status of the call. * * RETURNS: * The abort status. * */ BOOL CALLBACK printsetAbortProc(HDC hdcPrn, INT nCode) { MSG msg;
HHPRINT hhPrint = (HHPRINT)printCtrlLookupDC(hdcPrn);
DbgOutStr("\r\nprintsetAbortProc Code: %d", nCode, 0, 0, 0, 0);
while (!hhPrint->fUserAbort && PeekMessage((LPMSG)&msg, (HWND)0, 0, 0, PM_REMOVE)) { if (!hhPrint->hwndPrintDlg || !IsDialogMessage(hhPrint->hwndPrintDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
return !hhPrint->fUserAbort; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printsetDlgProc * * DESCRIPTION: * This is the dialog procedure for printing selected text. It contains * a CANCEL button that may be used to abort the printing process. * * ARGUMENTS: * Note that a print handle is passed into this procedure in the lPar * variable. * * RETURNS: * */ LRESULT CALLBACK printsetDlgProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar) { TCHAR achBuf[80]; TCHAR achMessage[80]; DWORD dwTime; HHPRINT hhPrint; LPTSTR acPtrs[3];
switch (uMsg) { case WM_INITDIALOG: DbgOutStr("\r\nprintsetDlgProc", 0, 0, 0, 0, 0); hhPrint = (HHPRINT)lPar; SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)lPar);
mscCenterWindowOnWindow(hwnd, sessQueryHwnd(hhPrint->hSession)); LoadString(glblQueryDllHinst(), IDS_PRINT_NOW_PRINTING, achBuf, sizeof(achBuf) / sizeof(TCHAR)); wsprintf(achMessage, achBuf, 1); SetDlgItemText(hwnd, 101, achMessage); LoadString(glblQueryDllHinst(), IDS_PRINT_OF_DOC, achBuf, sizeof(achBuf) / sizeof(TCHAR)); wsprintf(achMessage, achBuf, hhPrint->achDoc); SetDlgItemText(hwnd, 102, achMessage); LoadString(glblQueryDllHinst(), IDS_PRINT_ON_DEV, achBuf, sizeof(achBuf) / sizeof(TCHAR));
acPtrs[0] = hhPrint->achPrinterName; acPtrs[1] = (TCHAR *)hhPrint->pstDevNames + hhPrint->pstDevNames->wOutputOffset;
FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, achBuf, 0, /* Message ID, ignored */ 0, /* also ignored */ achMessage, /* result */ sizeof(achMessage) / sizeof(TCHAR), (va_list *)&acPtrs[0]);
SetDlgItemText(hwnd, 103, achMessage);
dwTime = GetTickCount(); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dwTime); return TRUE;
case WM_COMMAND: DbgOutStr("\r\nprintsetDlgProc - CANCEL", 0, 0, 0, 0, 0); hhPrint = (HHPRINT)GetWindowLongPtr(hwnd, DWLP_USER); hhPrint->fUserAbort = TRUE; EnableWindow(sessQueryHwnd(hhPrint->hSession), TRUE); DestroyWindow(hwnd); hhPrint->hwndPrintDlg = 0; return TRUE;
case WM_PRINT_NEWPAGE: DbgOutStr("\r\nprintsetDlgProc", 0, 0, 0, 0, 0); hhPrint = (HHPRINT)GetWindowLongPtr(hwnd, DWLP_USER); LoadString(glblQueryDllHinst(), IDS_PRINT_NOW_PRINTING, achBuf, sizeof(achBuf) / sizeof(TCHAR)); wsprintf(achMessage, achBuf, hhPrint->nPage); SetDlgItemText(hwnd, 101, achMessage); return TRUE;
default: break; }
return FALSE; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printPageSetup * * DESCRIPTION: * Invokes the common page-setup dialog * * ARGUMENTS: * HPRINT hPrint - public print handle * HWND hwnd - window handle used for parent * * RETURNS: * 0=OK,else error * */ int printPageSetup(const HPRINT hPrint, const HWND hwnd) { HHPRINT hhPrint = (HHPRINT)hPrint; PAGESETUPDLG psd; LPDEVNAMES pstDevNames; PDEVMODE pstDevMode;
TCHAR *pszPrinterName; TCHAR *pTemp; DWORD dwSize; RECT stMinMargins = {0,0,0,0};
if (hPrint == 0) return -1;
memset(&psd, 0, sizeof(psd));
psd.lStructSize = sizeof(psd); psd.hwndOwner = hwnd; psd.hInstance = glblQueryDllHinst();
psd.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK | PSD_MINMARGINS | PSD_MARGINS;
psd.rtMargin = hhPrint->margins; psd.rtMinMargin = stMinMargins; psd.lCustData = (LPARAM)hhPrint;
psd.lpPageSetupTemplateName = MAKEINTRESOURCE(IDD_CUSTOM_PAGE_SETUP); psd.lpfnPageSetupHook = printPageSetupHook;
// Use the previously stored information to initialize the print
// common dialogs. printGetDefaults initializes this information
// when a print handle is created.
//
if (hhPrint->pstDevMode) { // Allocate memory for the DEVMODE information and then
// initialize it with the stored values from the Print Handle.
//
dwSize = hhPrint->pstDevMode->dmSize + hhPrint->pstDevMode->dmDriverExtra;
if ((psd.hDevMode = GlobalAlloc(GMEM_MOVEABLE, dwSize))) { if ((pstDevMode = GlobalLock(psd.hDevMode))) { if (dwSize) MemCopy(pstDevMode, hhPrint->pstDevMode, dwSize); GlobalUnlock(psd.hDevMode); } } }
if (hhPrint->pstDevNames) { // Allocate memory for the DEVNAMES structure in pd, then
// initialize it with the stored values from the Print Handle.
// This sequence determines the variable structure size of
// DEVNAMES.
//
pTemp = (TCHAR *)hhPrint->pstDevNames; pTemp += hhPrint->pstDevNames->wOutputOffset; pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)hhPrint->pstDevNames);
if ((psd.hDevNames = GlobalAlloc(GMEM_MOVEABLE, dwSize))) { if ((pstDevNames = GlobalLock(psd.hDevNames))) { if (dwSize) MemCopy(pstDevNames, hhPrint->pstDevNames, dwSize); GlobalUnlock(psd.hDevNames); } } }
if (!PageSetupDlg(&psd)) { #if defined(_DEBUG)
TCHAR ach[100]; DWORD dwError = CommDlgExtendedError();
if (dwError != 0) { wsprintf(ach, "PrintDlg error 0x%x", dwError); MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK); } #endif
return -2; }
// store the margin settings in the print handle.
//
hhPrint->margins = psd.rtMargin;
// Store the printer name and location in the Print Handle
// every time.
//
pstDevNames = GlobalLock(psd.hDevNames); pszPrinterName = (TCHAR *)pstDevNames; pszPrinterName += pstDevNames->wDeviceOffset; StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN); GlobalUnlock(psd.hDevNames);
// Save the DEVMODE information in the Print Handle. This memory
// must be freed and allocated every time as the size of the
// DEVMODE structure changes.
//
pstDevMode = GlobalLock(psd.hDevMode); dwSize = pstDevMode->dmSize + pstDevMode->dmDriverExtra;
if (hhPrint->pstDevMode) { free(hhPrint->pstDevMode); hhPrint->pstDevMode = NULL; }
hhPrint->pstDevMode = (LPDEVMODE)malloc(dwSize);
if (hhPrint->pstDevMode == 0) { assert(FALSE); GlobalUnlock(psd.hDevMode); goto Cleanup; }
if (dwSize) MemCopy(hhPrint->pstDevMode, pstDevMode, dwSize); GlobalUnlock(psd.hDevMode);
// Save the DEVNAMES information in the Print Handle. Because the
// size of the information in this structure varies, it is freed and
// allocated each time it is saved.
//
pstDevNames = GlobalLock(psd.hDevNames);
// Determine the size of the structure.
//
pTemp = (TCHAR *)pstDevNames; pTemp += pstDevNames->wOutputOffset; pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)pstDevNames);
if (hhPrint->pstDevNames) { free(hhPrint->pstDevNames); hhPrint->pstDevNames = NULL; }
hhPrint->pstDevNames = (LPDEVNAMES)malloc(dwSize);
if (hhPrint->pstDevNames == 0) { assert(0); GlobalUnlock(psd.hDevNames); goto Cleanup; } if (dwSize) MemCopy(hhPrint->pstDevNames, pstDevNames, dwSize); GlobalUnlock(psd.hDevNames);
// Cleanup any memory that may have been allocated.
//
Cleanup:
if (psd.hDevNames) GlobalFree(psd.hDevNames);
if (psd.hDevMode) GlobalFree(psd.hDevMode);
return 0; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printPageSetupHook * * DESCRIPTION: * A hook function to process the font button on the page setup dialog * * ARGUMENTS: * hdlg - handle to the dialog box window * uiMsg - message identifier * wParam - message parameter * lParam - message parameter * * RETURNS: * 0 = message not processed 1 = message processeed * * Author: * Dwayne Newsome 02/19/97 * */
static UINT_PTR APIENTRY printPageSetupHook( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { static HHPRINT hhPrint; static PAGESETUPDLG * pPageSetup;
UINT processed = 0;
LPDEVNAMES pstDevNames; TCHAR * pszPrinterName;
//
// on the init dialog message save a pointer to the pagesetup dialog and
// save the print handle
//
if ( uiMsg == WM_INITDIALOG ) { pPageSetup = ( PAGESETUPDLG *) lParam; hhPrint = (HHPRINT) pPageSetup->lCustData; }
//
// Looking for the font button click here, if we get it set the currently
// selected printers name in the saved print handle and display the font
// dialog. We save the printer name so the font dialog can show the
// correct fonts for the currently selected printer.
//
else if ( uiMsg == WM_COMMAND ) { if ( HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 1027 ) { processed = 1; pstDevNames = GlobalLock(pPageSetup->hDevNames); pszPrinterName = (TCHAR *)pstDevNames; pszPrinterName += pstDevNames->wDeviceOffset; StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN); GlobalUnlock(pPageSetup->hDevNames);
DisplayFontDialog( hhPrint->hSession, TRUE ); } }
return processed; }
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: * printsetPrintToFile * * DESCRIPTION: * * * ARGUMENTS: * HPRINT hPrint - public print handle * * * RETURNS: * 0=OK,else error * */ static int printsetPrintToFile(const HPRINT hPrint) { const HHPRINT hhPrint = (HHPRINT)hPrint;
TCHAR acTitle[64], acMask[128], acDir[256], acFile[256];
LPTSTR pszPrintFile;
HWND hWnd; HINSTANCE hInst;
LPTSTR pszStr;
TCHAR_Fill(acTitle, TEXT('\0'), sizeof(acTitle) / sizeof(TCHAR)); TCHAR_Fill(acMask, TEXT('\0'), sizeof(acMask) / sizeof(TCHAR)); TCHAR_Fill(acDir, TEXT('\0'), sizeof(acDir) / sizeof(TCHAR)); TCHAR_Fill(acFile, TEXT('\0'), sizeof(acFile) / sizeof(TCHAR));
hWnd = glblQueryHwndFrame(); hInst = glblQueryDllHinst();
LoadString(hInst, IDS_PRINT_TOFILE, acTitle, sizeof(acTitle) / sizeof(TCHAR));
LoadString(hInst, IDS_PRINT_FILENAME, acFile, sizeof(acFile) / sizeof(TCHAR));
resLoadFileMask(hInst, IDS_PRINT_FILTER_1, 2, acMask, sizeof(acMask) / sizeof(TCHAR));
// Figure out which directory to propose to the user for the 'print to'
// file. If we have a session file, use that session files directory,
// otherwise use the current directory.
//
if (sfGetSessionFileName(sessQuerySysFileHdl(hhPrint->hSession), sizeof(acDir) / sizeof(TCHAR), acDir) == SF_OK) { mscStripName(acDir); } else { //Changed to use working folder rather than current folder - mpt 8-18-99
if ( !GetWorkingDirectory( acDir, sizeof(acDir) / sizeof(TCHAR)) ) { GetCurrentDirectory(sizeof(acDir) / sizeof(TCHAR), acDir); } }
pszStr = StrCharLast(acDir);
// Remove trailing backslash from the directory name if there is one.
//
if (pszStr && *pszStr == TEXT('\\')) *pszStr = TEXT('\0');
pszPrintFile = gnrcSaveFileDialog(hWnd, (LPCTSTR)acTitle, (LPCTSTR)acDir, (LPCTSTR)acMask , (LPCTSTR)acFile);
if (pszPrintFile == NULL) { return(1); }
// pszPrintFile gets allocated in gnrcSaveFileDlg.
//
StrCharCopyN(hhPrint->achPrintToFileName, pszPrintFile, PRINTER_NAME_LEN); free(pszPrintFile); pszPrintFile = NULL;
return(0);
}
|