Visual studio 2015 年社区报告查看器版本 12 使用 c# 获取额外保证金时出错

Visual studio 2015 community report viewer version 12 Error getting extra margin using c#

我正在使用 Visual studio 2015 社区报告查看器版本 12 在我的 C# 项目中显示 rdlc 报告。 这是正常的 A4 页面报告

它在客户端 PC 上的 windows xp、vista、win 7 上工作正常,但是当在 Windows 10 64 位上安装相同的应用程序时,我会遇到如下问题

正如您在上图中看到的那样,右侧和底部出现了不必要的边距,字体大小也减小了。但是当我将报告导出为 PDF 时,生成的 PDF 没有问题,它与我设计的报告相同。

我尝试了什么:

  1. 我安装了 MICROSOFT® REPORT VIEWER 2015 RUNTIME https://www.microsoft.com/en-us/download/details.aspx?id=45496
  2. 已安装 Microsoft® SQL Server® 2014 功能包(SQL 的系统 CLR 类型 服务器 2014)
  3. 尝试使用以下代码将 RDLC 直接导出到打印机

打印代码Class

public static class _cWainfoPrintReport
    {
        private static int m_currentPageIndex;
        private static IList<Stream> m_streams;
        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 _mExport(LocalReport report, bool print = true, double _pageWightInches = 8.27, double _pageHeightInches = 11.69, double _MarginTopInches = 0.025, double _MarginLeftInches = 0.025, double _MarginRightInches = 0.025, double _MarginBottomInches = 0.025)
        {
            string deviceInfo =
            @"<DeviceInfo> <OutputFormat>EMF</OutputFormat> <PageWidth>" + _pageWightInches + "in</PageWidth> <PageHeight>" + _pageHeightInches + "in</PageHeight> <MarginTop>" + _MarginTopInches + "in</MarginTop> <MarginLeft>" + _MarginLeftInches + "in</MarginLeft> <MarginRight>" + _MarginRightInches + "in</MarginRight> <MarginBottom>" + _MarginBottomInches + "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)
            {
                _mPrint(_pageWightInches, _pageHeightInches, _MarginTopInches, _MarginLeftInches, _MarginRightInches, _MarginBottomInches);
            }
            report.ReleaseSandboxAppDomain();
        }
        // Handler for PrintPageEvents
        public static void _mPrintPage(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 PaperSize CalculatePaperSize(double WidthInCentimeters, double HeightInCentimetres)
        {
            int Width = int.Parse((Math.Round((WidthInCentimeters * 0.393701) * 100, 0, MidpointRounding.AwayFromZero)).ToString());
            int Height = int.Parse((Math.Round((HeightInCentimetres * 0.393701) * 100, 0, MidpointRounding.AwayFromZero)).ToString());

            PaperSize NewSize = new PaperSize();
            NewSize.RawKind = (int)PaperKind.Custom;
            NewSize.Width = Width;
            NewSize.Height = Height;
            NewSize.PaperName = "Letter";

            return NewSize;

        }
        public static void _mPrint(double _pageWightInches = 8.27, double _pageHeightInches = 11.69, double _MarginTopInches = 0.025, double _MarginLeftInches = 0.025, double _MarginRightInches = 0.025, double _MarginBottomInches = 0.025)
        {
            if (m_streams == null || m_streams.Count == 0)
                throw new Exception("Error: no stream to print.");
            PrintDocument printDoc = new PrintDocument();

            PaperSize RequiredPaperSize = CalculatePaperSize(_pageWightInches * 2.54, _pageHeightInches * 2.54);
            bool FoundMatchingPaperSize = false;
            for (int index = 0; index < printDoc.PrinterSettings.PaperSizes.Count; index++)
            {
                if (printDoc.PrinterSettings.PaperSizes[index].Height == RequiredPaperSize.Height && printDoc.PrinterSettings.PaperSizes[index].Width == RequiredPaperSize.Width)
                {
                    printDoc.PrinterSettings.DefaultPageSettings.PaperSize = printDoc.PrinterSettings.PaperSizes[index];
                    printDoc.DefaultPageSettings.PaperSize = printDoc.PrinterSettings.PaperSizes[index];
                    FoundMatchingPaperSize = true;
                    break;
                }
            }


            if (!printDoc.PrinterSettings.IsValid)
            {
                throw new Exception("Error: cannot find the default printer.");
            }
            else
            {

                printDoc.PrintPage += new PrintPageEventHandler(_mPrintPage);
                m_currentPageIndex = 0;
                printDoc.Print();
            }
        }
        public static void _mPrintToPrinter(this LocalReport report)
        {
            _mExport(report);
        }
        public static void _mDisposePrint()
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }
    }

打印按钮上的代码

PrintViewer _PJobEntry = new PrintViewer();
DataTable dt = new DataSet1.MainTableDataTable();
dt.Rows.Add('vales for dataset');
_PJobEntry._RptView.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", dt));
_PJobEntry._RptView.LocalReport.ReportEmbeddedResource = "WAINFOBUSSOLN.Printing.RptSaleInvoice02.rdlc";
_PJobEntry._RptView.SetDisplayMode(DisplayMode.PrintLayout);
_cWainfoPrintReport._mExport(_PJobEntry._RptView.LocalReport, true, 8.27, 11.69, 0.25, 0.25, 0.28, 0.25);

但它也像上面描述的那样打印

相同的应用程序在我的 Windows 10 64 位 PC 上 运行 但在部署到具有 Windows 10 64 位

的客户端 PC 后无法运行

在客户端 PC .Net 4.0 框架上,SQL Server 2008,Windows 安装 10 64 位

如何解决。

我认为此问题与安装的任何工具无关,或者仅与 Windows 10 64 位有关。

而是 jdweng 和 Reza Aghaei 提到的 DPI 问题。更具体地说,高 DPI 设备。

不知道你有没有注意到,你上传的两张图片像素不同,低像素的图片显示了报告的正确呈现。这可以说支持了由于高 DPI 而导致的缩放问题的观点。

现在, 有很多关于此的文章、帖子和问题。但是,非常接近于向受害者提供某种正确方向的是 Microsoft 支持门户网站上的那个,它似乎没有为此行为提供的可能的解决方案(是的,复数)和解决方法(再次,复数)。

您可以在这里找到这篇文章:https://support.microsoft.com/en-au/help/3025083/windows-scaling-issues-for-high-dpi-devices

我相信,我在下面引用的解决方法暂时可以帮助您。

Change application properties

In Explorer or on the Start menu, right-click the application name, select Properties, select the Compatibility tab, and then select the Disable display scaling on high DPI settings check box.

Note: In Windows 10 Version 1703 and later version of Windows, the text of the Disable display scaling on high DPI settings option is changed to Override high DPI scaling behavior, scaling performed by: Application.

您应该禁用 DPI unawareness 并将您的应用程序设置为 DPI 感知 - 即使它不是,以防止缩放。

在较新版本的 Windows 10 上,我找到了一个不同的解决方案:您可以让您的应用程序处于任何 DPI 感知状态,但在不同的 DPI 感知状态下打开特定的 windows .

不幸的是,我仍在寻找一种 100% 时间都在工作的状态,但有 2 个选项似乎是不错的选择。

更改 DPI 感知

            if (WindowsVersion.WindowsIs10_1809OrNewer) // this you can get yourself, need to look at build number
            {
                // https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/DPIAwarenessPerWindow/client/DpiAwarenessContext.cpp
                _prevHosting = WinAPI.SetThreadDpiHostingBehavior((IntPtr)WinAPI.DPI_HOSTING_BEHAVIOR.BEHAVIOR_MIXED);

                _prevDPIContext = WinAPI.SetThreadDpiAwarenessContext((IntPtr)win10DPIAwareness); // WinAPI.ContextDPIAwareness.Context_UnawareGdiScaled);
            }

然后您可以在此线程中打开您的新对话框,此对话框将包含 ReportViewer。

稍后改回来

                    if (WindowsVersion.WindowsIs10_1809OrNewer)
                    {
                        WinAPI.SetThreadDpiAwarenessContext(_prevDPIContext);
                        WinAPI.SetThreadDpiHostingBehavior(_prevHosting);
                    }

帮手

    public static bool WindowsIs10_1809OrNewer
    {
        get { return WindowsIs10OrNewer && Environment.OSVersion.Version.Build >= 17763; }
    }

    public static bool WindowsIs10OrNewer
    {
        get { return Environment.OSVersion.Version >= new Version(10, 0); }
    }

    public enum DPI_HOSTING_BEHAVIOR
    {
        BEHAVIOR_INVALID = -1,
        BEHAVIOR_DEFAULT = 0,
        BEHAVIOR_MIXED = 1
    }

    public enum ContextDPIAwareness
    {
        Context_Unaware = -1,
        Context_SystemAware = -2,
        Context_PerMonitorAware = -3,
        Context_PerMonitorAwareV2 = -4,
        Context_UnawareGdiScaled = -5,
    }

您可以尝试 Context_UnawareGdiScaled - 它实际上经常正确地缩放 ReportViewer - 或者 Context_PerMonitorAware 禁用缩放。

我在 RDP 会话中遇到了问题,如果你没有,可能你对这些选项没问题。

此外,遗憾的是,这仅适用于较新的 Windows 10 版本。由于这些更新不是可选的,可能大多数 Windows 10 用户将使用新版本,并且 Windows 8 不受欢迎且所有其他 Windows 版本不支持,很多用户应该是最近的 Windows 10 版本。

当然,还远远不够完美。

顺便说一句,对于旧版本的 Windows,我只是通过 SetProcessDpiAwareness 禁用缩放,没有找到更好的方法。