Silverlight 4の印刷機能:画像編
ListBoxに表示する画像の取り込み
このListBoxコントロールに表示する画像をソリューションエクスプローラ内に取り込んでおきます。
ソリューションエクスプローラ内の「SL4_Print」を選択し、マウスの右クリックで表示されるメニューから、「追加(D) > 新しいフォルダー(D)」を選択し、新規フォルダを作成します。フォルダ名はデフォルトのNewFolder1ではなくImageに変更しておきましょう(図15)。 作成したフォルダ上を右クリックして表示されるメニューから「追加(D) > 既存の項目(G)」を選択して、ListBoxコントロールに表示する画像を追加します(図16)。
図15: ソリューションエクスプローラから新規フォルダを作成して名前を変更する |
図16: 作成したImageフォルダにListBoxに表示させる画像を追加した |
ソリューションエクスプローラからSL4_Printを選択し、マウスの右クリックで表示されるメニューから、「追加(D) > 既存の項目(G)」と選択して、XML文書ファイル(リスト1)を追加します。また、XMLデータはLINQ to XMLで処理するため、「プロジェクト(P) > 参照の追加(F)」からSystem.Xml.Linqを追加しておきます(図17)。
ダウンロード・ファイルには、XML文書ファイル、画像ファイルとも追加済みです。
リスト1: 画像ファイル名を記録したXML文書ファイル(photo_etc.xml)
図17: System.Xml.Linqを追加する |
書き出されるXAMLコードは省略します。
ロジックコードを記述する
次に処理を記述します。
ソリューションエクスプローラ内のMainPage.xamlを展開し、MainPage.xaml.vbをダブルクリックしてコード画面を開きます。
リスト2のようにロジックコードを記述します。
リスト2: ロジックコード(MainPage.xaml.vb)
LINQ to XMLでXMLを処理するクラスの含まれる、System.Xml.Linq名前空間をインポートします。Imageコントロールに画像を指定するクラスの含まれる、System.Windows.Media.Imaging名前空間をインポートします。印刷の機能を提供するクラスの含まれるSystem.Windows.Printing名前空間をインポートします。
Imageの新しいリストとして作成する_imageメンバ変数を宣言します。
■ページが読み込まれた時の処理
XElement.LoadメソッドでXML文書ファイル(photo_etc.xml)を読み込みます。
読み込んだXML文書ファイルから、要素のコレクションを選択するクエリ(query)を定義します。
queryを実行します。クエリコレクション内を変数resultで反復処理しながら以下の処理を実行します。
新しいImageのインスタンスmyImageオブジェクトを生成し、WidthとHeightプロパティの値を指定します。この値には、実寸画像の1/3の値を指定します。Sourceプロパティに、画像を読み込んでおいたImageフォルダを連結して、要素の値を、相対Uriで指定します。Width、Height、Sourceプロパティの設定された、myImageオブジェクトを、Addメソッドで、Imageのリストである_imageオブジェクトに追加していきます。
ListBox(ImageListBox)コントロールのItemsSourceに、Imageのリストである_imageオブジェクトを指定します。これで、ListBoxコントロール内に画像の一覧が表示されます。
■[印刷]ボタンがクリックされた時の処理
新しいPrintDocumentのインスタンスmyPrintオブジェクトを生成します。PrintDocumentクラスはSilverlightアプリケーションの印刷機能を提供するクラスです。
ページの印刷中に発生するPrintPageイベントでImagePrintプロシージャを実行します。印刷が完了したときに発生する、EndPrintイベントでは、Image_EndPrintプロシージャを実行します。
Printメソッドで印刷キューに指定するドキュメントの名前を指定して、印刷を開始します。
■画像を複数ページに渡って印刷する処理
新しいWrapPanelのインスタンスmyWrapPanelオブジェクトを生成します。
WrapPanelのWidthプロパティに750を指定します。画像が10ピクセル間隔で、横に4枚並ぶ程度の幅を指定します。
加算されるメンバ変数pageNumberが、Imageのリストである_imageオブジェクトに追加された画像の個数より小さい間、Whileステートメントで以下の処理を繰り返します。
新しい、ImageのインスタンスmyImageオブジェクトを生成し、WidthとHeightプロパティを指定します。
Marginプロパティには10を指定し、画像の余白が10ピクセルになるよう指定します。SourceプロパティにはImageのリストである_imageオブジェクトのSourceプロパティを指定します。この際、_imageオブジェクトの添え字に、加算される変数pageNumberを指定します。Width、Height、Margin、Sourceプロパティの指定されたmyImageオブジェクトをWrapPanelコントロールに追加します。
WrapPanelに対して、SizeにWidthとHeightを指定して、Measureメソッドを呼び出します。Widthには印刷可能なWidth(e.PrintableArea.Width)を指定し、Heightには正の無限大を表すDouble.PositiveInfinityを指定します。
Measureメソッドは、レイアウト処理の測定パスの実行中に、UIElementが計算したサイズを更新します。
WrapPanelのDesiredSize.Heightが、印刷可能なHeight(e.PrintableArea.Height)より大きく、かつ、WrapPanelコントロールに追加されたImageの個数が1より大きかった場合は、WrapPanelコントロールから、RemoveメソッドでImageオブジェクトを削除し、HasMorePagesプロパティにTrueを指定して、まだ印刷するページがあることを明示します。次にWhileステートメントから抜けます。
HasMorePagesプロパティにTrueを指定すると、印刷するページがある限り、PrintPageイベントで、ImagePrintプロシージャが呼び出されます。ImagePrintプロシージャが呼び出され、新しいWrapPanelが生成されImageオブジェクトが追加される前に、すでにImageオブジェクトが追加されている場合は、一度RemoveメソッドでWrapPanelオブジェクトからImageオブジェクトを削除しておきます。この処理をしなければ、ごみが入る場合があります。Imageのリストとして作成した_imageオブジェクトの添え字に指定した、pageNumber変数を加算します。印刷する要素を指定するPageVisualプロパティにWrapPanelのオブジェクトであるmyWrapPanelを指定します。これで、ListBoxコントロールに縦一列で表示されていた画像の一覧が、横4列で複数ページに渡って印刷されます。
■印刷が完了したときの処理
「完了」というメッセージボックスを表示します。
この「完了」というメッセージが表示されない限り、XPSファイルは書き出されませんので、注意してください。