SP2を適用すると、GrapeCity.ActiveReports.Document.SectionDocument.Printerクラスに属する一部のイベントが発生しなくなる

文書番号 : 36963     文書種別 : 不具合     登録日 : 2014/01/14     最終更新日 : 2014/04/16
文書を印刷する
対象製品
ActiveReports for .NET 7.0J
発生環境
Service Pack 2(v7.2.8529.1)の場合に発生します。
状況
修正済み
詳細
※この現象はセクションレポートのみで発生します。

Service Pack 2(v7.2.8529.1)を適用すると、GrapeCity.ActiveReports.Document.SectionDocument.Printerクラスに属する一部のイベントが発生しなくなります。発生しなくなるイベントは以下の通りです。
  • BeginPrint
  • EndPrint
  • PrintPage
  • QueryPageSettings
例えば、以下のナレッジ文書や製品ヘルプで紹介しているような方法で EndPrintイベントを実装しても、SP2を適用した環境ではイベントが発生しません。

Windowsフォームアプリでレポートを印刷する際、印刷処理の終了を判断する方法は?

◆製品ヘルプ
PowerTools ActiveReports for .NET 7.0J
 - ActiveReportsユーザーガイド
  - よくある質問
   - 共通の項目(ページレポートとセクションレポート)
    - 印刷
     - Windowsフォームアプリでレポートを印刷する際、印刷処理の終了を判断する
回避方法
この問題はService Pack 3(v7.3.7964.1)で修正されました。
不具合を修正した最新のサービスパックをご使用ください。

SP3を使用しない場合の回避方法は以下のとおりです。

System.Reflection名前空間を利用してビューワのフィールド情報にアクセスし、実際に印刷を行うプリンターのフィールド情報を上書きする方法が考えられます。例えば、EndPrintイベントを関連付ける場合は以下のようなコードになります。

◆サンプルコード(VB.NET)
Imports System.Reflection
Imports GrapeCity.ActiveReports.Extensibility.Printing
Imports GrapeCity.ActiveReports.Viewer.Win
Imports GrapeCity.Viewer.Common.Model
Imports GrapeCity.Viewer.Common.ViewModel

Private Sub Form1_Load(...) Handles MyBase.Load
  ' セクションレポートをViewerに表示します。
  Dim sectionReport As New SectionReport1
  sectionReport.Run()
  Dim sectionDocument As GrapeCity.ActiveReports.Document.SectionDocument
  sectionDocument = sectionReport.Document
  Me.Viewer1.LoadDocument(sectionDocument)

  ' フィールド情報にアクセスして、プリンターを上書きします
  ResolvePrinter(Me.Viewer1)

  ' EndPrintイベントをイベントハンドラに関連付けます。
  AddHandler sectionDocument.Printer.EndPrint, AddressOf Me.onEndPrint
End Sub

' フィールド情報にアクセスして、プリンターを上書きします
Private Sub ResolvePrinter(viewer As GrapeCity.ActiveReports.Viewer.Win.Viewer)

  ' Viewer.ViewModelを取得します
  Dim propertyViewModel = GetProperty(GetType(GrapeCity.ActiveReports.Viewer.Win.Viewer), "ViewModel")
  If (propertyViewModel Is Nothing) Then
    Return
  End If

  Dim viewModel = CType(propertyViewModel.GetValue(viewer, Nothing), ViewerViewModel)
  If viewModel Is Nothing Then
    Return
  End If

  ' ViewerViewModel.Modelを取得します
  Dim propertyModel = GetProperty(GetType(ViewerViewModel), "Model")
  If (propertyModel Is Nothing) Then
    Return
  End If

  Dim model = CType(propertyModel.GetValue(viewModel, Nothing), ViewerModel)
  If model Is Nothing Then
    Return
  End If

  ' ViewerModel.Documentを取得します
  Dim documentModel = model.Document

  ' Printerのフィールド情報を取得します
  Dim printerField = GetPrinterField(documentModel)
  If (printerField Is Nothing) Then
    Return
  End If

  ' Printerのフィールド情報を上書きします
  printerField.SetValue(documentModel, Viewer1.Document.Printer)

End Sub

Private Function GetPrinterField(model As Object) As FieldInfo
  Dim flags As BindingFlags = BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic

  For Each field As FieldInfo In model.GetType().GetFields(flags)
    If field.FieldType Is GetType(Printer) Then
      Return field
    End If
  Next

  Return Nothing
End Function

Private Function GetProperty(t As Type, name As String) As PropertyInfo
  Dim flags As BindingFlags = BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.NonPublic
  Try
    Return t.GetProperty(name, flags)
  Catch
    Return Nothing
  End Try
End Function

' イベントハンドラ
Private Sub onEndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs)
  Console.WriteLine("印刷完了")
End Sub

◆サンプルコード(C#)
using System.Reflection;
using GrapeCity.ActiveReports.Extensibility.Printing;
using GrapeCity.ActiveReports.Viewer.Win;
using GrapeCity.Viewer.Common.Model;
using GrapeCity.Viewer.Common.ViewModel;

private void Form1_Load(object sender, EventArgs e)
{
  // セクションレポートをViewerに表示します。
  SectionReport1 sectionReport = new SectionReport1();
  sectionReport.Run();
  GrapeCity.ActiveReports.Document.SectionDocument sectionDocument
    = sectionReport.Document;
  this.viewer1.LoadDocument(sectionDocument);

  // フィールド情報にアクセスして、プリンターを上書きします
  ResolvePrinter(this.viewer1);

  // EndPrintイベントをイベントハンドラに関連付けます。
  sectionDocument.Printer.EndPrint += new System.Drawing.Printing.PrintEventHandler(onEndPrint);
}

// フィールド情報にアクセスして、プリンターを上書きします
private void ResolvePrinter(GrapeCity.ActiveReports.Viewer.Win.Viewer viewer)
{
  // Viewer.ViewModelを取得します
  var propertyViewModel = GetProperty(typeof(Viewer), "ViewModel");
  if (propertyViewModel == null)
    return;

  var viewModel = propertyViewModel.GetValue(viewer, null) as ViewerViewModel;
  if (viewModel == null)
    return;

  // ViewerViewModel.Modelを取得します
  var propertyModel = GetProperty(typeof(ViewerViewModel), "Model");
  if (propertyModel == null)
    return;

  var model = propertyModel.GetValue(viewModel, null) as ViewerModel;
  if (model == null)
    return;

  // ViewerModel.Documentを取得します
  var documentModel = model.Document;

  // Printerのフィールド情報を取得します
  var printerField = GetPrinterField(documentModel);
  if ((printerField == null))
  {
    return;
  }

  // Printerのフィールド情報を上書きします
  printerField.SetValue(documentModel, viewer1.Document.Printer);
}

private FieldInfo GetPrinterField(object model)
{
  BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

  foreach (FieldInfo field in model.GetType().GetFields(flags))
  {
    if (field.FieldType == typeof(Printer))
    {
      return field;
    }
  }
  return null;
}

private PropertyInfo GetProperty(Type t, string name)
{
  BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
  try
  {
    return t.GetProperty(name, flags);
  }
  catch
  {
    return null;
  }
}

// イベントハンドラ
private void onEndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
  Console.WriteLine("印刷完了");
}
キーワード
10145