SP2を適用し、.NET標準の印刷設定ダイアログ(System.Windows.Forms.PrintDialog)を実装すると、印刷設定ダイアログから設定した内容が実際の印刷動作・結果に反映されない

文書番号 : 36885     文書種別 : 不具合     登録日 : 2013/12/18     最終更新日 : 2014/04/16
文書を印刷する
対象製品
ActiveReports for .NET 7.0J
発生環境
Service Pack 2(v7.2.8529.1)の場合に発生します。
状況
修正済み
詳細
※この現象はセクションレポートのみで発生します。
※この現象はActiveReportsのビューワのデフォルトの印刷ダイアログを使用した場合は発生しません。

Service Pack 2(v7.2.8529.1)を適用し、以下のナレッジ文書の「2.」や製品ヘルプで紹介している.NET標準の印刷設定ダイアログを使用する方法を実装すると、印刷設定ダイアログから設定した内容が実際の印刷動作・結果に反映されなくなります。

例)印刷設定ダイアログで印刷先のプリンターを変更しても、変更前のプリンターに印刷される。

Windowsフォームアプリでレポートを印刷する際、印刷ダイアログ上で押されたボタンを判断する方法は?

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

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

こちらのナレッジ文書で紹介しているサンプルコードを、以下のように System.Reflection名前空間を利用してビューワのフィールド情報にアクセスし、実際に印刷を行うプリンターのフィールド情報を上書きするように変更することで、本事象を回避することが可能です。

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

Private WithEvents pd As New System.Windows.Forms.PrintDialog ' 印刷設定ダイアログ
Private WithEvents myTimer As New System.Windows.Forms.Timer ' タイマー


' タイマーが経過した時に呼び出されるイベント。
Private Sub myTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
  ' タイマーを停止し、印刷設定ダイアログを表示します。
  myTimer.Stop()
  ' 実際に印刷を行う Printerのフィールド情報を上書きします
  ResolvePrinter(Me.Viewer1)

  If (pd.ShowDialog() = DialogResult.OK) Then


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

◆サンプルコード(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 PrintDialog pd = new System.Windows.Forms.PrintDialog(); // 印刷設定ダイアログ
private Timer myTimer = new System.Windows.Forms.Timer(); // タイマー


// タイマーが経過した時に呼び出されるイベント。
private void myTimer_Tick(Object myObject, EventArgs myEventArgs)
  {
  // タイマーを停止し、印刷設定ダイアログを表示します。
  myTimer.Stop();
      
  // 実際に印刷を行う Printerのフィールド情報を上書きします
  ResolvePrinter(this.viewer1);
      
  if (pd.ShowDialog() == DialogResult.OK)


}

// フィールド情報にアクセスして、プリンターを上書きします
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;
  }
}
キーワード
10096