PrintToFile, Version 1.3c (alt)
Hinweis: dies ist nicht die neueste Version!
Datei: README.txt
PrintToFile.pas Delphi unit giving the ability to directly specify the filename for printing when the "Print to file" option is checked, bypassing the query where to save the file. See the included README.txt for more information and how to use it. Version 1.3c - Always find the most current version at http://flocke.vssd.de/prog/code/pascal/prt2file/ Copyright (C) 2005, 2006 Volker Siebert <flocke@vssd.de> All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------- Delphi versions: 5, 6, 7, 2005, and 2006. The reason for writing this code is to have the ability to directly specify the filename when printing to file. At the API level, the filename can be specified in the call to "StartDoc", but that's not possible with Delphi's TPrinter object, because "BeginDoc" is not a virtual function and thus can't be overridden. Furthermore, there are tons of Delphi components that print but don't give the ability to specify an output file or even have the ability to print to file. This is where you can use the "PrintToFile" unit. It hooks onto the "StartDoc" API function and patches the passed TDocInfo structure with a filename of your choice. USAGE: After initialization (more on that later), all you have to do is to assign the output filename to the global variable "PrintToThisFile" each time you want to print to file. The next time a print is started, the output is written to this file. Here is an example usage, printing the contents of the RichEdit-control "RichEdit1" to file when clicking the button "Button1". +------------------------------------------------------------------------- | uses | PrintToFile; | | ... | | procedure Button1Click(Sender: TObject); | begin | PrintToThisFile := 'C:\PrinterOutput.prn'; | RichEdit1.Print('My Document'); | end; +------------------------------------------------------------------------- If you leave it blank, the old behaviour is used instead. Every time "PrintToThisFile" is used, it is reset to blank again. INITIALIZATION: The unit gives you three opportunities about the level to patch. - Patch_TPrinter_BeginDoc This function scans the code of TPrinter.BeginDoc for the call to the "StartDoc" API function and replaces it with a call to our replacement function. -> All components using Delphi's TPrinter objects resp. the predefined "Printer" object can print to file. - Patch_StartDoc_ImportTable This function patches the import table entry that points to the "StartDoc" API function and replaces it with a pointer to our replacement function. -> All components that are linked to your application and that are directly using Windows.StartDoc can print to file. - Patch_StartDoc_DLL_Entry This function patches the very first bytes of the real "StartDoc" API function and create a new code fragment in memory to be able to call the old code. Attention: this does not work under Windows 95/98/Me - you have to use one of the functions above for these operating systems. -> All components, linked directly to your application or used via DLL can print to file, even if GetProcAddress is used. Each of the three functions return TRUE upon successful initialzation and FALSE, if they were not able to apply the patch. Once patched successfully, you cannot change the patching level. Any call to one of the three functions immediately returns TRUE in this case. So it is no problem to call any of the three functions more than once. Here our example with initialization: +------------------------------------------------------------------------- | uses | PrintToFile; | | ... | | procedure Button1Click(Sender: TObject); | begin | if not Patch_StartDoc_ImportTable then | raise Exception.Create('Print to file not possible!'); | PrintToThisFile := 'C:\PrinterOutput.prn'; | RichEdit1.Print('My Document'); | end; +------------------------------------------------------------------------- Also take a look at the included sample application. OUTPUT: To really print the captured printer output, you can use the function "SendFileToPrinter". Here is an example with the filename from above: +------------------------------------------------------------------------- | SendFileToPrinter('C:\PrinterOutput.prn'); +------------------------------------------------------------------------- |