Hi,
we have a requirement where we need to carry out certain actions (update database, reload data) before a report is printed to a printer.
OnBeforePrint fires before the report is being generated, e.g. when preview is being generated, but not when printed afterwards.
Using a PrintingSystem.CommandHandler for the print command doesn't help either, because it is invoked BEFORE the print dialog is shown. Thus, when the user cancels out of the print dialog, the report is not printed.
We need to capture an event that occurs just after the user pressed OK in the print dialog.
How can we accomplish this task?
Thanks,
Matthias
Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.
Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.
Hi Martin,
Actually, you should be able to accomplish this task via a custom Print command handler. All you need to do is to invoke the PrintDialog manually.
Please refer to a sample code snippet:
Partial Public Class Form1 Inherits Form Public Sub New() InitializeComponent() End Sub Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Dim report As New XtraReport1() report.PrintingSystem.AddCommandHandler(New CustomPrintCommandHandler(report)) ' Show the report's print preview. report.ShowPreview() End Sub End Class Public Class CustomPrintCommandHandler Implements ICommandHandler Public Overridable Sub HandleCommand(ByVal command As PrintingSystemCommand, ByVal args() As Object, ByVal control As IPrintControl, ByRef handled As Boolean) If (Not CanHandleCommand(command, control)) Then Return End If ' Set handled to true to avoid the standard exporting procedure to be called. handled = True Dim dialog As New PrintDialog() Dim res As DialogResult = dialog.ShowDialog() If res = DialogResult.OK Then 'your code here report.Print(dialog.PrinterSettings.PrinterName) End If End Sub Private report As XtraReport = Nothing Public Sub New(ByVal report As XtraReport) MyBase.New() Me.report = report End Sub Public Overridable Function CanHandleCommand(ByVal command As PrintingSystemCommand, ByVal control As IPrintControl) As Boolean Return command Is PrintingSystemCommand.Print End Function End Class
Thanks,
Alex
That is a bit too simple… ;-)
A printer dialog is not just for selecting a printer but has many more options.
In your sample, apart from the printer selection, none of the other options are taken into account…
Martin,
Yes, I have provided a simplified example. However, I see no problem to implement a more complex printing handler within the HandleCommand method.
For instance, you can subscribe to the report.PrintingSystem.StartPrint event, and initialize the e.PrintDocument.PrinterSettings manually (using the information extracted from the PrintDialog). If you are experiencing any problem, please let me know. I will be glad to help you.
Thanks,
Alex
My concern with this approach ist this: When the user clicks on the "Preferences" Button in the PrintDialog, the user can modify printer specific settings. These settings are not contained in the PageSettings class. The PageSettings class wraps the DEVMODE structure which contains a device-independent part and a device specific part. The PageSettings class only wraps the device-independent part, so that printer-specific settings would be lost, when using XtraPageSettings::Assign…
Any idea how to solve that?
Thanks,
Matthias
Hi Martin,
I am afraid we do not have an alternative (native) Print Dialog implementation to overcome this limitation right away. Please also take into account that in some situations it is impossible to track printer hardware issues (e.g. when the paper is jammed or a power failure occurs) during printing. So, it seems that there is no generic solution to determine whether a document has been physically printed.
Thanks,
Alex
Hi Alex,
thanks for your help. We are now using a different approach with a custom print dialog.
Still the question remains how to propagate the printer specific settings to the printed document.
In our custom print dialog we are calling the WinApi function DocumentProperties (in winspool.drv), thus we receive a complete DEVMODE structure with device-specific setting. How can we transfer these settings to the Report/PrintingSystem?
Thanks,
Matthias
Hi Martin,
Thank you for the response. Unfortunately, we do not provide any built-in methods to accomplish this task. So, you might need to extract the required information and update the PrintingSystem.PageSettings property manually. Hope this will be of some help.
Thanks,
Alex
I now using PrintSettings.SetHdevmode and GetHdevmode.
At what point in time (event oder overridden method on XtraReport) should I use this method to update PrintingSystem.PageSettings?
Martin,
I believe you can handle the XtraReport.AfterPrint event to access a newly created PrintingSystem instance. Alternatively, you can apply printer specific settings by handling the PrintingSystem.PrintProgress or the PrintingSystem.StartPrint event. Please apply this solution and inform us of your results.
Thanks,
Alex
It's not really a straightforward approach.
For now I am using this code: (I have a private PrinterSettings object)
Protected Overrides Sub OnBeforePrint(ByVal e As System.Drawing.Printing.PrintEventArgs)
Me.Landscape = _PrinterSettings.DefaultPageSettings.Landscape
Me.PrintingSystem.PageSettings.Assign(_PrinterSettings.DefaultPageSettings)
Me.PaperKind = _PrinterSettings.DefaultPageSettings.PaperSize.Kind
If Me.PaperKind = System.Drawing.Printing.PaperKind.Custom Then
'TODO: Convert Units?
Me.PageSize = New Size(_PrinterSettings.DefaultPageSettings.PaperSize.Width, PrinterSettings.DefaultPageSettings.PaperSize.Height)
End If
MyBase.OnBeforePrint(e)
PrintingSystem.RemoveCommandHandler(Me)
PrintingSystem.AddCommandHandler(Me)
End Sub
Protected Overrides Sub OnAfterPrint(ByVal e As System.EventArgs)
MyBase.OnAfterPrint(e)
Me.PrintingSystem.PageSettings.Assign(_PrinterSettings.DefaultPageSettings)
PrintingSystem.RemoveCommandHandler(Me)
PrintingSystem.AddCommandHandler(Me)
End Sub
Protected Sub PrintingSystem_StartPrint(ByVal sender As Object, ByVal e As PrintDocumentEventArgs)
e.PrintDocument.PrinterSettings = _PrinterSettings
End Sub
Does that look right to you?
Thanks, M
Martin,
Thank you for posting the code snippet. An extra PageSettings.Assign method in the BeforePrint event seems unnecessary (since the report's page settings are already initialized in the BeforePrint event). To convert report units at runtime, you may use the XRConvert.Convert method. Other than that, if you notice any problem with your code, please feel free to update this thread.
Thanks,
Alex
Alex,
thanks very much for your assistance!
M
Dear Martin,
Please feel free to contact us if you have any further difficulties. We will do our best to help you.
Thanks,
Alex