Silverlight 4の印刷機能:画像編

2010年8月2日(月)
PROJECT KySS

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ファイルは書き出されませんので、注意してください。

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています