unit KOLPrintDialogs; {* Print and printer setup dialogs, implemented in KOL object. |
Ver 1.4 |
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: |
| } 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 |
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.