I use the NTWAIN library, found a good solution for interacting with this library, modified it a little. This is actually it:
public class ScanningTwain
{
List<Image> ImagesScan;
DataSource myDS;
TwainSession session;
public ScanningTwain()
{
ImagesScan = new List<Image>();
}
public List<Image> Scan(decimal dpi)
{
ImagesScan.Clear();
var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly());
session = new TwainSession(appId);
session.TransferReady += session_TransferReady;
session.DataTransferred += session_DataTransferred;
session.SourceDisabled += session_SourceDisable;
session.Open();
IEnumerable<DataSource> lesSources = session.GetSources();
myDS = lesSources.FirstOrDefault();
myDS.Open();
PixelType typeCouleur = PixelType.Gray;
if (myDS.Capabilities.ICapPixelType.CanSet &&
myDS.Capabilities.ICapPixelType.GetValues().Contains(typeCouleur))
{
myDS.Capabilities.ICapPixelType.SetValue(typeCouleur);
}
TWFix32 DPI = (float)dpi;
if (myDS.Capabilities.ICapXResolution.CanSet &&
myDS.Capabilities.ICapXResolution.GetValues().Contains(DPI))
{
myDS.Capabilities.ICapXResolution.SetValue(DPI);
}
if (myDS.Capabilities.ICapYResolution.CanSet &&
myDS.Capabilities.ICapYResolution.GetValues().Contains(DPI))
{
myDS.Capabilities.ICapYResolution.SetValue(DPI);
}
myDS.Enable(SourceEnableMode.ShowUI, false, System.IntPtr.Zero);
EventWaitHandle session_SourceDisable_Wait = new EventWaitHandle(false, EventResetMode.AutoReset);
session_SourceDisable_Wait.WaitOne();
return ImagesScan;
}
void session_DataTransferred(object sender, NTwain.DataTransferredEventArgs e)
{
if (e.NativeData != IntPtr.Zero)
{
Bitmap img = null;
//Need to save out the data.
Stream s = e.GetNativeImageStream();
BitmapSource bitmapsource = s.ConvertToWpfBitmap();
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
img = new Bitmap(outStream);
}
if (img != null)
{
ImagesScan.Add(img);
}
}
}
void session_SourceDisable(object sender, EventArgs e)
{
myDS.Close();
session.Close();
}
void session_TransferReady(object sender, NTwain.TransferReadyEventArgs e)
{
}
}
The error occurs at the line: myDS.Open () ; in the public List <Image> Scan (decimal dpi) method writes that myDS = null , I suppose this is due to the fact that when this line is executed session.Open () ; DSM does not appear so that you can select a scanner. Although I downloaded DSM from the official site. Thank you in advance for your help!
I am using the below code to print RDCL Report directly ,
but the problem in the printed page , it is not same to what i choose in the report properties (A4), i tried to change page width and height in device info but same issue the printed paper huge and printed on 4 papers. please any idea?
private Stream CreateStream(string name,
string fileNameExtension, Encoding encoding,
string mimeType, bool willSeek)
{
Stream stream = new MemoryStream();
m_streams.Add(stream);
return stream;
}
// Export the given report as an EMF (Enhanced Metafile) file.
private void Export(LocalReport report)
{
string deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>8.27in</PageWidth>
<PageHeight>11.69in</PageHeight>
<MarginTop>0.25in</MarginTop>
<MarginLeft>0.25in</MarginLeft>
<MarginRight>0.25in</MarginRight>
<MarginBottom>0.25in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream,
out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
// Handler for PrintPageEvents
private void PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = new
Metafile(m_streams[m_currentPageIndex]);
// Adjust rectangular area with printer margins.
Rectangle adjustedRect = new Rectangle(
ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
ev.PageBounds.Width,
ev.PageBounds.Height);
// Draw a white background for the report
ev.Graphics.FillRectangle(Brushes.White, adjustedRect);
// Draw the report content
ev.Graphics.DrawImage(pageImage, adjustedRect);
// Prepare for the next page. Make sure we haven't hit the end.
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
private void Print()
{
if (m_streams == null || m_streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument printDoc = new PrintDocument();
if (!printDoc.PrinterSettings.IsValid)
{
throw new Exception("Error: cannot find the default printer.");
}
else
{
printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
m_currentPageIndex = 0;
printDoc.Print();
}
}
// Create a local report for Report.rdlc, load the data,
// export the report to an .emf file, and print it.
private void Run()
{
LocalReport report = new LocalReport();
report.ReportPath = #"Doctor_form.rdlc";
Export(report);
Print();
}
protected void print_Click1(object sender, EventArgs e)
{
LocalReport report = new LocalReport();
report.ReportPath = #"Doctor_form.rdlc";
report.SetParameters(parameters);
Export(report);
Print();}
Here is my code i work with:
set Dataset and parameter to RDLC report
private static int m_currentPageIndex;
report.DataSources.Add(new ReportDataSource("dsReceiptInfor", ReceiptInfor));
ReportParameter[] param = new ReportParameter[2];
param[0] = new ReportParameter("imgPath", FilePath);
param[1] = new ReportParameter("BaseCurrencyFormat", BaseCurrencyFormat);
report.SetParameters(param);
Export(report);
Print();
Functions
--Export
private static void Export(LocalReport report)
{
string deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>8.5in</PageWidth>
<PageHeight>11in</PageHeight>
<MarginTop>0in</MarginTop>
<MarginLeft>0in</MarginLeft>
<MarginRight>0in</MarginRight>
<MarginBottom>0in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream, out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
--Print
private static void Print()
{
if (m_streams == null || m_streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument PrintBill = new PrintDocument();
PrintBill.PrintPage += new PrintPageEventHandler(PrintPage);
PrintBill.PrinterSettings.PrinterName = PrinterName;
PrintBill.PrintController = new StandardPrintController();
m_currentPageIndex = 0;
PrintBill.Print();
}
--PrintPage
private static void PrintPage(object sender, PrintPageEventArgs ev)
{
try
{
Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
//Adjust rectangular area with printer margins.
Rectangle adjustedRect = new Rectangle(
0,
0,
765,
ev.PageBounds.Height);
//Draw a white background for the report
ev.Graphics.FillRectangle(Brushes.White, adjustedRect);
// Draw the report content
ev.Graphics.DrawImage(pageImage, adjustedRect);
// Prepare for the next page. Make sure we haven't hit the end.
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
catch (Exception ex)
{
}
}
When the data print (PageHeight > 11 inch) it will cut. Could you tell me how to print long as the paper.
thanks for your attention :)
after long time i have searching the answer but still not found. So i have found one solution without coding.
in Printer setting we can change printer preference :
Paper source --> Document (cut). Done
Im new to the c#, currently Im making a POS application witch can print a Receipt. I used reportviewer component for create the Receipt. I is working. but I couldn't pass the print command directly. When it is preview I have to press Print Button manually. but I need to print it automatically without a preview. here is my beginning of the code. Is there any way to bind this repotviewr with PrintDocument or how can I print this reportviewer automatically
Open FormReceipt
DateTime thisDay = DateTime.Today;
FormReceipt frmReceipt = new FormReceipt(order, String.Format("{0:n}", totalAmmount), String.Format("{0:n}", paidammount), String.Format("{0:n}",change), thisDay.ToString("g"), discount.ToString());
frmReceipt.ShowDialog();
Set Parameters and Binding Source
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Printing;
using Microsoft.Reporting.WinForms;
namespace Pos
{
public partial class FormReceipt : MetroFramework.Forms.MetroForm
{
List<Receipt> _list;
string _total, _cash, _change, _date, _user, _discount;
public FormReceipt(List<Receipt> datasource, string total,string cash, string change, string date, string discount)
{
InitializeComponent();
_list = datasource;
_total = total;
_cash = cash;
_change = change;
_date = date;
_user = Sessiondata.user;
_discount = discount;
}
private void FormReceipt_Load(object sender, EventArgs e)
{
ReceiptBindingSource.DataSource = _list;
Microsoft.Reporting.WinForms.ReportParameter[] para = new Microsoft.Reporting.WinForms.ReportParameter[]{
new Microsoft.Reporting.WinForms.ReportParameter("pTotal",_total),
new Microsoft.Reporting.WinForms.ReportParameter("pCash",_cash),
new Microsoft.Reporting.WinForms.ReportParameter("pChange",_change),
new Microsoft.Reporting.WinForms.ReportParameter("pDate",_date),
new Microsoft.Reporting.WinForms.ReportParameter("pUser",_user),
new Microsoft.Reporting.WinForms.ReportParameter("pItems",_list.Count.ToString()),
new Microsoft.Reporting.WinForms.ReportParameter("pDiscount",_discount+"%")
};
this.reportViewer1.LocalReport.SetParameters(para);
this.reportViewer1.RefreshReport();
}
private void reportViewer1_Load(object sender, EventArgs e)
{
}
}
}
I am posting my code which is working fine as you want. Check this code and do the customization in the code as needed.
List<Receipt> _list;
string _total, _cash, _change, _date, _user, _discount;
public FormReceipt(List<Receipt> datasource, string total,string cash, string change, string date, string discount)
{
InitializeComponent();
_list = datasource;
_total = total;
_cash = cash;
_change = change;
_date = date;
_user = Sessiondata.user;
_discount = discount;
}
private void FormReceipt_Load(object sender, EventArgs e)
{
ReceiptBindingSource.DataSource = _list;
Microsoft.Reporting.WinForms.ReportParameter[] para = new Microsoft.Reporting.WinForms.ReportParameter[]{
new Microsoft.Reporting.WinForms.ReportParameter("pTotal",_total),
new Microsoft.Reporting.WinForms.ReportParameter("pCash",_cash),
new Microsoft.Reporting.WinForms.ReportParameter("pChange",_change),
new Microsoft.Reporting.WinForms.ReportParameter("pDate",_date),
new Microsoft.Reporting.WinForms.ReportParameter("pUser",_user),
new Microsoft.Reporting.WinForms.ReportParameter("pItems",_list.Count.ToString()),
new Microsoft.Reporting.WinForms.ReportParameter("pDiscount",_discount+"%")
};
this.reportViewer1.LocalReport.SetParameters(para);
this.reportViewer1.RefreshReport();
Export(ReportViewer1.LocalReport, false);
Print();
Dispose();
}
private int m_currentPageIndex;
private IList<Stream> m_streams;
private Stream CreateStream(string name,
string fileNameExtension, Encoding encoding,
string mimeType, bool willSeek)
{
Stream stream = new MemoryStream();
m_streams.Add(stream);
return stream;
}
private void Export(LocalReport report, bool isLandscape)
{
string deviceInfo = string.Empty;
if (isLandscape)
{
deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>11in</PageWidth>
<PageHeight>8.5in</PageHeight>
<MarginTop>0.25in</MarginTop>
<MarginLeft>0.25in</MarginLeft>
<MarginRight>0.25in</MarginRight>
<MarginBottom>0.25in</MarginBottom>
</DeviceInfo>";
}
else
{
deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>8.5in</PageWidth>
<PageHeight>11in</PageHeight>
<MarginTop>0.25in</MarginTop>
<MarginLeft>0.25in</MarginLeft>
<MarginRight>0.25in</MarginRight>
<MarginBottom>0.25in</MarginBottom>
</DeviceInfo>";
}
Warning[] warnings;
m_streams = new List<Stream>();
// Create Report DataSource
ReportDataSource rds = new ReportDataSource();
rds.Value = _list;
ReportViewer1.LocalReport.DataSources.Clear();
ReportViewer1.LocalReport.DataSources.Add(rds);
report.Render("Image", deviceInfo, CreateStream,
out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
private void Print()
{
PrinterSettings settings = new PrinterSettings(); //set printer settings
string printerName = settings.PrinterName; //use default printer name
if (m_streams == null || m_streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument printDoc = new PrintDocument();
if (!printDoc.PrinterSettings.IsValid)
{
Response.Write("<script>alert('" + printerName + "')</script>");
}
else
{
printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
m_currentPageIndex = 0;
printDoc.Print();
}
}
private void PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = new
Metafile(m_streams[m_currentPageIndex]);
ev.Graphics.DrawImage(pageImage, ev.PageBounds);
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
public void Dispose()
{
if (m_streams != null)
{
foreach (Stream stream in m_streams)
stream.Close();
m_streams = null;
}
}
add this code to class and then call function PrintToPrinter and pass reportviewer as parameter then report will print silently
for more details :
https://learn.microsoft.com/en-us/previous-versions/ms252091(v=vs.140)?redirectedfrom=MSDN
private static List<Stream> m_streams;
private static int m_currentPageIndex = 0;
static LocalReport report = new LocalReport();
public static void PrintToPrinter(LocalReport report)
{
Export(report);
}
public static void Export(LocalReport report, bool print = true)
{
string deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>{pageSettings.PaperSize.Width * 100}in</PageWidth>
<PageHeight>{pageSettings.PaperSize.Height * 100}in</PageHeight>
<MarginTop>{pageSettings.Margins.Top * 100}in</MarginTop>
<MarginLeft>{pageSettings.Margins.Left * 100}in</MarginLeft>
<MarginRight>{pageSettings.Margins.Right * 100}in</MarginRight>
<MarginBottom>{pageSettings.Margins.Bottom * 100}in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream, out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
if (print)
{
Print();
}
}
public static void Print()
{
if (m_streams == null || m_streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument printDoc = new PrintDocument();
if (!printDoc.PrinterSettings.IsValid)
{
throw new Exception("Error: cannot find the default printer.");
}
else
{
printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
m_currentPageIndex = 0;
printDoc.Print();
}
}
public static Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
{
Stream stream = new MemoryStream();
m_streams.Add(stream);
return stream;
}
public static void PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = new
Metafile(m_streams[m_currentPageIndex]);
// Adjust rectangular area with printer margins.
Rectangle adjustedRect = new Rectangle(
ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
ev.PageBounds.Width,
ev.PageBounds.Height);
// Draw a white background for the report
ev.Graphics.FillRectangle(Brushes.White, adjustedRect);
// Draw the report content
ev.Graphics.DrawImage(pageImage, adjustedRect);
// Prepare for the next page. Make sure we haven't hit the end.
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
public static void DisposePrint()
{
if (m_streams != null)
{
foreach (Stream stream in m_streams)
stream.Close();
m_streams = null;
}
}
I was wondering if is possible to send/print data from DataGridView directly to rdlc report without binding it to ReportViewercontrol.
There are many threads about binding dgv data to report viewer control.
I don't want to create another form with report viewer control, but use existing form with data on DataGridView and on print button to send the data to RDLC report and print it.
Is it possible?
Thanks
You can print an RDLC report programmatically by using LocalReport object and CreateStreamCallback callback function. Here is a complete Microsoft docs walkthrough which you may find useful:
Walkthrough: Printing a Local Report without Preview
To make it easier to use, I've created a Print extension method which you can easily use it this way:
this.reportViewer1.LocalReport.Print();
Here is the extension method:
using Microsoft.Reporting.WinForms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
public static class LocalReportExtensions
{
public static void Print(this LocalReport report)
{
var pageSettings = new PageSettings();
pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize;
pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape;
pageSettings.Margins = report.GetDefaultPageSettings().Margins;
Print(report, pageSettings);
}
public static void Print(this LocalReport report, PageSettings pageSettings)
{
string deviceInfo =
$#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>{pageSettings.PaperSize.Width * 100}in</PageWidth>
<PageHeight>{pageSettings.PaperSize.Height * 100}in</PageHeight>
<MarginTop>{pageSettings.Margins.Top * 100}in</MarginTop>
<MarginLeft>{pageSettings.Margins.Left * 100}in</MarginLeft>
<MarginRight>{pageSettings.Margins.Right * 100}in</MarginRight>
<MarginBottom>{pageSettings.Margins.Bottom * 100}in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
var streams = new List<Stream>();
var currentPageIndex = 0;
report.Render("Image", deviceInfo,
(name, fileNameExtension, encoding, mimeType, willSeek) =>
{
var stream = new MemoryStream();
streams.Add(stream);
return stream;
}, out warnings);
foreach (Stream stream in streams)
stream.Position = 0;
if (streams == null || streams.Count == 0)
throw new Exception("Error: no stream to print.");
var printDocument = new PrintDocument();
printDocument.DefaultPageSettings = pageSettings;
if (!printDocument.PrinterSettings.IsValid)
throw new Exception("Error: cannot find the default printer.");
else
{
printDocument.PrintPage += (sender, e) =>
{
Metafile pageImage = new Metafile(streams[currentPageIndex]);
Rectangle adjustedRect = new Rectangle(
e.PageBounds.Left - (int)e.PageSettings.HardMarginX,
e.PageBounds.Top - (int)e.PageSettings.HardMarginY,
e.PageBounds.Width,
e.PageBounds.Height);
e.Graphics.FillRectangle(Brushes.White, adjustedRect);
e.Graphics.DrawImage(pageImage, adjustedRect);
currentPageIndex++;
e.HasMorePages = (currentPageIndex < streams.Count);
e.Graphics.DrawRectangle(Pens.Red, adjustedRect);
};
printDocument.EndPrint += (Sender, e) =>
{
if (streams != null)
{
foreach (Stream stream in streams)
stream.Close();
streams = null;
}
};
printDocument.Print();
}
}
}
Print with showing Print dialog
Just in case someone wants to print with showing Print dialog, you can put a ReportViewer on form and set the Visible property of the control to false then pass data to the report and when the RenderingComplete event fired, call PrintDialog:
ReportViewer.PrintDialog Method