374 lines
11 KiB
ObjectPascal
374 lines
11 KiB
ObjectPascal
|
unit KOLPrintDialogs;
|
||
|
{* Print and printer setup dialogs, implemented in KOL object.
|
||
|
|<br>
|
||
|
Ver 1.4
|
||
|
|<br>
|
||
|
Now the information about selected printer can be transferred to TKOLPrinter.
|
||
|
If DC is needed directly use new pdReturnDC option.}
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses Windows, Messages, KOL, KOLPrintCommon;
|
||
|
|
||
|
|
||
|
const
|
||
|
|
||
|
DN_DEFAULTPRN = $0001; {default printer }
|
||
|
HELPMSGSTRING = 'commdlg_help';
|
||
|
|
||
|
|
||
|
|
||
|
//******************************************************************************
|
||
|
// PrintDlg options
|
||
|
//******************************************************************************
|
||
|
|
||
|
PD_ALLPAGES = $00000000;
|
||
|
PD_SELECTION = $00000001;
|
||
|
PD_PAGENUMS = $00000002;
|
||
|
PD_NOSELECTION = $00000004;
|
||
|
PD_NOPAGENUMS = $00000008;
|
||
|
PD_COLLATE = $00000010;
|
||
|
PD_PRINTTOFILE = $00000020;
|
||
|
PD_PRINTSETUP = $00000040;
|
||
|
PD_NOWARNING = $00000080;
|
||
|
PD_RETURNDC = $00000100;
|
||
|
PD_RETURNIC = $00000200;
|
||
|
PD_RETURNDEFAULT = $00000400;
|
||
|
PD_SHOWHELP = $00000800;
|
||
|
PD_ENABLEPRINTHOOK = $00001000;
|
||
|
PD_ENABLESETUPHOOK = $00002000;
|
||
|
PD_ENABLEPRINTTEMPLATE = $00004000;
|
||
|
PD_ENABLESETUPTEMPLATE = $00008000;
|
||
|
PD_ENABLEPRINTTEMPLATEHANDLE = $00010000;
|
||
|
PD_ENABLESETUPTEMPLATEHANDLE = $00020000;
|
||
|
PD_USEDEVMODECOPIES = $00040000;
|
||
|
PD_USEDEVMODECOPIESANDCOLLATE = $00040000;
|
||
|
PD_DISABLEPRINTTOFILE = $00080000;
|
||
|
PD_HIDEPRINTTOFILE = $00100000;
|
||
|
PD_NONETWORKBUTTON = $00200000;
|
||
|
|
||
|
|
||
|
//******************************************************************************
|
||
|
// Error constants
|
||
|
//******************************************************************************
|
||
|
|
||
|
|
||
|
CDERR_DIALOGFAILURE = $FFFF;
|
||
|
CDERR_GENERALCODES = $0000;
|
||
|
CDERR_STRUCTSIZE = $0001;
|
||
|
CDERR_INITIALIZATION = $0002;
|
||
|
CDERR_NOTEMPLATE = $0003;
|
||
|
CDERR_NOHINSTANCE = $0004;
|
||
|
CDERR_LOADSTRFAILURE = $0005;
|
||
|
CDERR_FINDRESFAILURE = $0006;
|
||
|
CDERR_LOADRESFAILURE = $0007;
|
||
|
CDERR_LOCKRESFAILURE = $0008;
|
||
|
CDERR_MEMALLOCFAILURE = $0009;
|
||
|
CDERR_MEMLOCKFAILURE = $000A;
|
||
|
CDERR_NOHOOK = $000B;
|
||
|
CDERR_REGISTERMSGFAIL = $000C;
|
||
|
PDERR_PRINTERCODES = $1000;
|
||
|
PDERR_SETUPFAILURE = $1001;
|
||
|
PDERR_PARSEFAILURE = $1002;
|
||
|
PDERR_RETDEFFAILURE = $1003;
|
||
|
PDERR_LOADDRVFAILURE = $1004;
|
||
|
PDERR_GETDEVMODEFAIL = $1005;
|
||
|
PDERR_INITFAILURE = $1006;
|
||
|
PDERR_NODEVICES = $1007;
|
||
|
PDERR_NODEFAULTPRN = $1008;
|
||
|
PDERR_DNDMMISMATCH = $1009;
|
||
|
PDERR_CREATEICFAILURE = $100A;
|
||
|
PDERR_PRINTERNOTFOUND = $100B;
|
||
|
PDERR_DEFAULTDIFFERENT = $100C;
|
||
|
|
||
|
|
||
|
type
|
||
|
|
||
|
PDevNames = ^tagDEVNAMES;
|
||
|
tagDEVNAMES = packed record
|
||
|
{*}
|
||
|
wDriverOffset: Word;
|
||
|
wDeviceOffset: Word;
|
||
|
wOutputOffset: Word;
|
||
|
wDefault: Word;
|
||
|
end;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
{ Structure for PrintDlg function }
|
||
|
PtagPD = ^tagPD;
|
||
|
tagPD = packed record
|
||
|
{*}
|
||
|
lStructSize: DWORD;
|
||
|
hWndOwner: HWND;
|
||
|
hDevMode: HGLOBAL;
|
||
|
hDevNames: HGLOBAL;
|
||
|
hDC: HDC;
|
||
|
Flags: DWORD;
|
||
|
nFromPage: Word;
|
||
|
nToPage: Word;
|
||
|
nMinPage: Word;
|
||
|
nMaxPage: Word;
|
||
|
nCopies: Word;
|
||
|
hInstance: HINST;
|
||
|
lCustData: LPARAM;
|
||
|
lpfnPrintHook: function(Wnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): UINT stdcall;
|
||
|
lpfnSetupHook: function(Wnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): UINT stdcall;
|
||
|
lpPrintTemplateName: PAnsiChar;
|
||
|
lpSetupTemplateName: PAnsiChar;
|
||
|
hPrintTemplate: HGLOBAL;
|
||
|
hSetupTemplate: HGLOBAL;
|
||
|
end;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
function PrintDlg(var PrintDlg: tagPD): BOOL; stdcall;external 'comdlg32.dll' name 'PrintDlgA';
|
||
|
|
||
|
function CommDlgExtendedError():DWORD;stdcall; external 'comdlg32.dll' name 'CommDlgExtendedError';
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
type
|
||
|
|
||
|
//////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// Print dialog and printer setup dialog. //
|
||
|
// //
|
||
|
//////////////////////////////////////////////////////
|
||
|
|
||
|
TPrintDlgOption = (pdPrinterSetup,pdCollate,pdPrintToFile,pdPageNums,pdSelection,
|
||
|
pdWarning,pdDeviceDepend,pdHelp,pdReturnDC);
|
||
|
{* Options:
|
||
|
|<br>
|
||
|
|<ul>
|
||
|
|<li><b>pdPrinterSetup</b> : printer setup dialog </li>
|
||
|
|<li><b>pdCollate</b> : places checkmark in Collate check box.When Execute returns this flag
|
||
|
indicates that the user selected the Collate option but printer does not support it
|
||
|
|</li>
|
||
|
|<li><b>pdPrintToFile</b> : causes "Print to File" check box to be visible.When Execute returns this flag
|
||
|
indicates that this check box was selected and must be processed
|
||
|
|</li>
|
||
|
|<li><b>pdPageNums</b> : allow to select pages in dialog </li>
|
||
|
|<li><b>pdSelection</b> : set Selection field visible in dialog </li>
|
||
|
|<li><b>pdWarning</b> : when set, and there's no default printer in system, warning is generated (like in VCL TPrintDialog) </li>
|
||
|
|<li><b>pdDeviceDepend</b> : disables fields : Copies,Collate if this functions aren't supported by printer driver </li>
|
||
|
|<li><b>pdHelp</b> : Help button is visible (owner receive HELPMSGSTRING registered message)</li>
|
||
|
|<li><b>pdReturnDC</b> : returns DC of selected printer </li>
|
||
|
|</ul>
|
||
|
}
|
||
|
|
||
|
|
||
|
TPrintDlgOptions = Set of TPrintDlgOption;
|
||
|
{*}
|
||
|
|
||
|
PPrintDlg =^TPrintDlg;
|
||
|
TKOLPrintDialog = PPrintDlg;
|
||
|
TPrintDlg = object(TObj)
|
||
|
{*}
|
||
|
private
|
||
|
{ Private declarations }
|
||
|
fDevNames : PDevNames;
|
||
|
fAdvanced : WORD;
|
||
|
ftagPD : tagPD;
|
||
|
fOptions : TPrintDlgOptions;
|
||
|
PrinterInfo : TPrinterInfo;
|
||
|
protected
|
||
|
function GetError : Integer;
|
||
|
|
||
|
{ Protected declarations }
|
||
|
public
|
||
|
{ Public declarations }
|
||
|
destructor Destroy; virtual;
|
||
|
property Error : Integer read GetError;
|
||
|
{* Extended error}
|
||
|
property FromPage : WORD read ftagPD.nFromPage write ftagPD.nFromPage;
|
||
|
{* Starting page }
|
||
|
property ToPage : WORD read ftagPD.nToPage write ftagPD.nToPage;
|
||
|
{* Ending page}
|
||
|
property MinPage : WORD read ftagPD.nMinPage write ftagPD.nMinPage;
|
||
|
{* Minimal page number which is allowed to select}
|
||
|
property MaxPage : WORD read ftagPD.nMaxPage write ftagPD.nMaxPage;
|
||
|
{* Maximal page number which is allowed to select}
|
||
|
property Copies : WORD read ftagPD.nCopies write ftagPD.nCopies;
|
||
|
{* Number of copies}
|
||
|
property Options : TPrintDlgOptions read fOptions write fOptions;
|
||
|
{* Set of options}
|
||
|
property DC : hDC read ftagPD.hDC;
|
||
|
{* DC of selected printer}
|
||
|
function Execute : Boolean;
|
||
|
{* Main method}
|
||
|
function Info : PPrinterInfo;
|
||
|
{*}
|
||
|
{These below are usefull in Advanced mode }
|
||
|
property tagPD : tagPD read ftagPD write ftagPD;
|
||
|
{* For low-level access}
|
||
|
property Advanced : WORD read fAdvanced write fAdvanced;
|
||
|
{* 1 := You must assign properties to tagPD by yourself
|
||
|
|<br>
|
||
|
2 := Even more control...
|
||
|
}
|
||
|
procedure FillOptions(DlgOptions : TPrintDlgOptions);
|
||
|
{* Fill options}
|
||
|
procedure Prepare;
|
||
|
{* Destroy of prevoius context (DEVMODE,DEVNAMES,DC) .Usefull when Advanced > 0}
|
||
|
end;
|
||
|
|
||
|
function NewPrintDialog(AOwner : PControl; Options : TPrintDlgOptions) : PPrintDlg;
|
||
|
{* Global creating function}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
implementation
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// Print dialog and printer setup dialog (implementation) //
|
||
|
// //
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
function NewPrintDialog(AOwner : PControl; Options : TPrintDlgOptions) : PPrintDlg;
|
||
|
begin
|
||
|
New(Result,Create);
|
||
|
FillChar(Result.ftagPD,sizeof(tagPD),0);
|
||
|
Result.ftagPD.hWndOwner := AOwner.GetWindowHandle;
|
||
|
Result.ftagPD.hInstance := hInstance;
|
||
|
Result.fOptions := Options;
|
||
|
Result.fAdvanced := 0;
|
||
|
end;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
destructor TPrintDlg.Destroy;
|
||
|
begin
|
||
|
Prepare;
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
procedure TPrintDlg.Prepare;
|
||
|
begin
|
||
|
if ftagPD.hDevMode <> 0 then
|
||
|
begin
|
||
|
GlobalFree(ftagPD.hDevMode);
|
||
|
ftagPD.hDevMode :=0;
|
||
|
end;
|
||
|
if ftagPD.hDevNames <> 0 then
|
||
|
begin
|
||
|
GlobalUnlock(ftagPD.hDevNames);
|
||
|
GlobalFree(ftagPD.hDevNames);
|
||
|
ftagPD.hDevNames :=0;
|
||
|
end;
|
||
|
if ftagPD.hDC <> 0 then
|
||
|
begin
|
||
|
DeleteDC(ftagPD.hDC);
|
||
|
ftagPD.hDC :=0;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
|
||
|
procedure TPrintDlg.FillOptions(DlgOptions : TPrintDlgOptions);
|
||
|
begin
|
||
|
ftagPD.Flags := PD_ALLPAGES;
|
||
|
{ Return HDC if required}
|
||
|
if pdReturnDC in DlgOptions then Inc(ftagPD.Flags,PD_RETURNDC);
|
||
|
{ Show printer setup dialog }
|
||
|
if pdPrinterSetup in DlgOptions then Inc(ftagPD.Flags,PD_PRINTSETUP);
|
||
|
{ Process HELPMSGSTRING message. Note : AOwner control must register and
|
||
|
process this message.}
|
||
|
if pdHelp in DlgOptions then Inc(ftagPD.Flags, PD_SHOWHELP);
|
||
|
{ This flag indicates on return that printer driver does not support collation.
|
||
|
You must eigther provide collation or set pdDeviceDepend (and user won't see
|
||
|
collate checkbox if is not supported) }
|
||
|
if pdCollate in DlgOptions then Inc(ftagPD.Flags,PD_COLLATE);
|
||
|
{ Disable some parts of PrintDlg window }
|
||
|
if not (pdPrintToFile in DlgOptions) then Inc(ftagPD.Flags, PD_HIDEPRINTTOFILE);
|
||
|
if not (pdPageNums in DlgOptions) then Inc(ftagPD.Flags, PD_NOPAGENUMS);
|
||
|
if not (pdSelection in DlgOptions) then Inc(ftagPD.Flags, PD_NOSELECTION);
|
||
|
{ Disable warning if there is no default printer }
|
||
|
if not (pdWarning in DlgOptions) then Inc(ftagPD.Flags, PD_NOWARNING);
|
||
|
if pdDeviceDepend in DlgOptions then Inc(ftagPD.Flags,PD_USEDEVMODECOPIESANDCOLLATE);
|
||
|
|
||
|
end;
|
||
|
|
||
|
function TPrintDlg.GetError : Integer;
|
||
|
begin
|
||
|
Result := CommDlgExtendedError();
|
||
|
end;
|
||
|
|
||
|
function TPrintDlg.Execute : Boolean;
|
||
|
var
|
||
|
ExitCode : Boolean;
|
||
|
begin
|
||
|
case fAdvanced of
|
||
|
0 : //Not in advanced mode
|
||
|
begin
|
||
|
Prepare;
|
||
|
FillOptions(fOptions);
|
||
|
end;
|
||
|
1:Prepare; //Advanced mode . User must assign properties and/or hook procedures
|
||
|
end;
|
||
|
ftagPD.lStructSize := sizeof(tagPD);
|
||
|
ExitCode := PrintDlg(ftagPD);
|
||
|
fDevNames := PDevNames(GlobalLock(ftagPD.hDevNames));
|
||
|
if (ftagPD.Flags and PD_PRINTTOFILE) <> 0 then fOptions := fOptions + [pdPrintToFile]
|
||
|
else
|
||
|
fOptions := fOptions - [pdPrintToFile];
|
||
|
if (ftagPD.Flags and PD_COLLATE) <> 0 then fOptions := fOptions + [pdCollate]
|
||
|
else
|
||
|
fOptions := fOptions - [pdCollate];
|
||
|
Result := ExitCode;
|
||
|
end;
|
||
|
|
||
|
function TPrintDlg.Info : PPrinterInfo;
|
||
|
begin
|
||
|
try
|
||
|
FillChar(PrinterInfo,sizeof(PrinterInfo),0);
|
||
|
with PrinterInfo do
|
||
|
begin
|
||
|
ADriver := PChar(fDevNames) + fDevNames^.wDriverOffset;
|
||
|
ADevice := PChar(fDevNames) + fDevNames^.wDeviceOffset;
|
||
|
APort := PChar(fDevNames) + fDevNames^.wOutputOffset;
|
||
|
ADevMode := ftagPD.hDevMode ;
|
||
|
end;
|
||
|
finally //support situation when fDevNames=0 (user pressed Cancel)
|
||
|
Result := @PrinterInfo;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
begin
|
||
|
end.
|