See the following article on how to detect if a user printed to the printer. Once this occurs, you should be able to restrict the data your user has access to.
Years ago I had to do a similar thing in that I had to detect if:
- the user actually sent output to printer, not to screen, file or archive - the user printed the entire range (not a sub range of pages) - the user did not cancel printing
If all that was true, I had to assume it made it to the printer - that it was in the windows print spooler and would print ok.
Because there were serious side effects if they printed the same document twice, when the printdialog closed I popped up a dialog box telling the user to "click ok if the printing succeeded, or cancel if printer jammed/failed".
I never did bother to figure out if my print job successfully printed - I just made sure the end-users got used to waiting for the output!
I had a TppReport in a form by itself (could/should have used datamodule)
Here's the basic code I used for this:
private FUserCancelled : Boolean; // did User Cancel print? FSentToPrinter : Boolean; // did report get sent to the printer, or just viewed/exported FPgSetting : TppPageSettingType; FPgRange : TppPageRangeType;
//---EJB---2005.08.28----------------------------- procedure TfrmRepPSIView.ResetPrintStateFlags; begin FPgSetting := psFirstPage; // force to anything but "all" so we default to false FPgRange := prOddPages; // force to anything but "all" so we default to false FUserCancelled := False; // assume print not cancel FSentToPrinter := False; // assume not sent to printer end;
procedure TfrmRepPSIView.ppReport1PrintDialogCreate(Sender: TObject); begin ResetPrintStateFlags; // reset again now because user can print, cancel, print again end;
procedure TfrmRepPSIView.ppReport1PrintDialogClose(Sender: TObject); begin // we accept only sent to printer, but NOT if printtofile FSentToPrinter:= ( (ppReport1.PrintDialog.DeviceType='Printer') and not (ppReport1.PrintDialog.PrintToArchive) and not (ppReport1.PrintDialog.PrintToFile) ); end;
//---EJB---2005.08.28----------------------------- procedure TfrmRepPSIView.ppReport1Cancel(Sender: TObject); begin if ( Assigned(ppReport1.CancelDialog) and ppReport1.CancelDialog.Active and ppReport1.CancelDialog.Visible ) then FUserCancelled:=True; end;
and called it with:
frmRepPSIView.ResetPrintStateFlags; frmRepPSIView.ppReport1.Print; SentToPrinter := frmRepPSIView.WasSentToPrinterEx; // return whether or not this was sent to a printer DidUserCancel := frmRepPSIView.FUserCancelled; // return whether or not this print job got cancelled
if ( SentToPrinter and (not DidUserCancel)) then if AskUserToWaitDialog then ...
Comments
See the following article on how to detect if a user printed to the
printer. Once this occurs, you should be able to restrict the data your
user has access to.
http://www.digital-metaphors.com/rbWiki/Output/Printer/Detecting_Whether_Report_Printed_to_Printer
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Years ago I had to do a similar thing in that I had to detect if:
- the user actually sent output to printer, not to screen, file or
archive
- the user printed the entire range (not a sub range of pages)
- the user did not cancel printing
If all that was true, I had to assume it made it to the printer - that
it was in the windows print spooler and would print ok.
Because there were serious side effects if they printed the same
document twice, when the printdialog closed I popped up a dialog box
telling the user to "click ok if the printing succeeded, or cancel if
printer jammed/failed".
I never did bother to figure out if my print job successfully printed -
I just made sure the end-users got used to waiting for the output!
I had a TppReport in a form by itself (could/should have used
datamodule)
Here's the basic code I used for this:
private
FUserCancelled : Boolean; // did User Cancel print?
FSentToPrinter : Boolean; // did report get sent to the
printer, or just viewed/exported
FPgSetting : TppPageSettingType;
FPgRange : TppPageRangeType;
//---EJB---2005.08.28-----------------------------
procedure TfrmRepPSIView.ResetPrintStateFlags;
begin
FPgSetting := psFirstPage; // force to anything but "all" so we
default to false
FPgRange := prOddPages; // force to anything but "all" so we
default to false
FUserCancelled := False; // assume print not cancel
FSentToPrinter := False; // assume not sent to printer
end;
procedure TfrmRepPSIView.ppReport1PrintDialogCreate(Sender: TObject);
begin
ResetPrintStateFlags; // reset again now because user can print,
cancel, print again
end;
procedure TfrmRepPSIView.ppReport1PrintDialogClose(Sender: TObject);
begin
// we accept only sent to printer, but NOT if printtofile
FSentToPrinter:= ( (ppReport1.PrintDialog.DeviceType='Printer') and
not (ppReport1.PrintDialog.PrintToArchive) and
not (ppReport1.PrintDialog.PrintToFile)
);
end;
//---EJB---2005.08.28-----------------------------
procedure TfrmRepPSIView.ppReport1Cancel(Sender: TObject);
begin
if ( Assigned(ppReport1.CancelDialog) and
ppReport1.CancelDialog.Active and
ppReport1.CancelDialog.Visible
) then FUserCancelled:=True;
end;
and called it with:
frmRepPSIView.ResetPrintStateFlags;
frmRepPSIView.ppReport1.Print;
SentToPrinter := frmRepPSIView.WasSentToPrinterEx; // return
whether or not this was sent to a printer
DidUserCancel := frmRepPSIView.FUserCancelled; // return
whether or not this print job got cancelled
if ( SentToPrinter and (not DidUserCancel)) then
if AskUserToWaitDialog then
...
Cheers,
EdB