« 2007年12月 | トップページ | 2008年3月 »

[P16] PowerShell:関数の引数および関数の戻り値が正しく受け取れず、おかしくなってしまう場合の対処法

PowerShell 関数における引数と戻り値については、その渡し方と受け取り方が C# などの通常の言語感覚とは多少異なります。
私のように、単なるクライアント環境下で、コマンドラインからではなく通常の言語感覚で Script ファイルから、それなりの規模の自分のライブラリを作成・利用しながら PowerShell を使おうとすると、おそらく一度は、関数の引数およひ戻り値が正しく受け取れない、おかしくなってしまうという問題に直面することがあるのではないかと思います。

私は、この問題でだいぶ苦労致しましたので、以下に『常に関数はこうして扱っておけば、絶対に大丈夫だ』という自分なりに見いだした結論を同じ問題に直面している方の御参考のために紹介しておきます。
理由・根拠等を書いていると長くなりますので、結論のみを記します。あとは、いかなる場面でも常にこの『鉄則)』に沿ってコーディングするだけです。

なお、引数問題と戻り値問題は、一応別個の事柄ですが、関数の使用という実際上の観点から、ここでひとまとめにして書いておきます。

   ----------------------------------------------------

【関数の引数渡し】

関数の引数渡しに問題が生ずるのは、渡す側と受け取る側で異なった形式を使ってしまうことに起因します。これには、ある形式では引数渡しに限界があり、不自由だという事情も絡んでいます。
関数の引数渡しに関しての鉄則は、引数渡しをすべて配列で行う(以下、配列型という)と決めて、それに徹するということです。それ以外は使わないことです。とにかく、いろいろ試してみた最終結論です。

① 関数側(引数を受け取る側)

  function MyFunc()
  {
     PARAM($para)
     $MyStringParameter = [String] $para[0]
     $MyIntParameter    = [int]$para[1]
        ・・・
     #------------
      ・・・関数本体の内容 
  }
 
引数並びは、配列 $para として渡されてくるものとして、すべて対処しておきます。

C# などなら、

  MyFunc(string $MyStringParameter, int $MyIntParameter)

とするところを、必ず以上のように記します。
   配列の要素を型変換(キャスト)して、受け取ります。

引数が、1個の場合でもこの配列型に徹します。すなわち、   

  PARAM($para)
  $MyStringParameter = [String] $para[0]

とします。

引数がない関数の場合は、引数の受け取りの記載は一切不要です。

配列型で処理しますから、上記引数の受け取りは、以下のようにも記述できます。

  function MyFunc()
  {
     PARAM ( $para)
     $i=0
     foreach($e in $para) {
       switch($i) {
         0 {$MyStringParameter  = [String]$e; break}
         1 {$MyIntParameter = [int]$e; break}
       }
       $i++
    }
      #------------
        ・・・関数本体の内容
  }

私は、引数並びによっては、この後者を使う場合もありますが、$para が配列として渡されているということをはずしさえしなければよいので、実質的に同じです。

② 関数の使用[引数を渡す側]

    こちらは、必ず配列として $para が渡されるように以下の型に徹します。 

   $retValue = MyFunc @($MyStringParameter, $MyIntParameter, ・・・)

  引数が、一つの場合もこの鉄則を維持します。

   &retValue = MyFunc @($MyStringParameter)

  但し、全く引数がない場合は、

   &retValue = MyFunc

  のみです。

【関数の戻り値】

戻り値の問題は、それ以前に使用した関数の戻り値がクリアされずにそのまま戻ってきてしまうことから起こります。
そこで、あらゆる関数使用に際して必ず戻り値を受け取るように使用します。
『戻り値を受け取る必要がなくても』、また『戻り値を返さない関数であっても』戻り値を受け取っておく、ということに徹します。
『戻り値を返さない関数であっても』戻り値を受け取って、エラーにはなりません。

  $dummy = MyFunc @(MyPara_1, MyPara_2, ・・・・)
  $dummy = MyFunc

以上、あらゆる場合を上記原則通りに押し通して例外を作らなければ、引数・戻り値問題で悩まされる必要は一切解消致します。これで安心して、ライブラリを構築し、安定した使用ができます。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
目次に戻る ・・・・ 左欄のカテゴリー 【パソコンの窓】 をクリック
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

| | コメント (0)

[P15]WPF:ItemsSource が使用中で、ListBox.Items.Add メソッドが無効の場合

ListBox.Items.Add メソッドが下記の実行時エラーを出す場合がある。

『 ItemsSource が使用中の場合、Items.Add()操作は無効です。
   代わりに ItemsControl.ItemsSource を使用して要素にアクセスし、変更してください。』

正しくは、どういうコードを書くべきかよくわからず、調べても見あたりません。

[注]
    正しい書き方は、ItemsControl.ItemsSource を使用して、Add 操作をするという
 方向だと思うのですが、成功しません。(正しいコードがわかる方は、
  お教え下さい。) そこで、以下は苦肉の策です。

とりあえず、この場合には、以下のようなメソッドを作り、
ListBox.Items.Add() のコード部分を、下記のメソッド呼び出しに換えてやれば
まにあいます。

[String データを扱っている場合の例]

    public void AddFromItemsSource(ref ListBox lstBx, string addItem)
    {
        string[] ItemsArray = new string[lstBx.Items.Count+1];
        //現在のデータを全部保存する
        for (int i = 0; i < lstBx.Items.Count;i++ )
        {
            ItemsArray[i] = lstBx.Items[i] as string;
        }
        ItemsArray[lstBx.Items.Count] = addItem;
         //追加データを加えておく
        //-----------------
    //いったん、ItemsSource を null にする。
        lstBx.ItemsSource = null;
        lstBx.Items.Clear();
        //----------------
        lstBx.ItemsSource = ItemsArray;
    //データをセットする
    }

なお、ListBox.Items.Clear メソッドでも同様の事態が生じた場合には、
上記メソッド中にもあるように、その部分(ListBox.Items.Clear メソッド部分)を
以下のようにします。

        lstBx.ItemsSource = null;
        lstBx.Items.Clear();
    (結論的には、前に lstBx.ItemsSource = null; を付け加えるだけ)

以上

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
目次に戻る ・・・・ 左欄のカテゴリー 【パソコンの窓】 をクリック
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

| | コメント (0)

[P14] WPF: プリンター印刷(XPS)

[はじめに]

  WPF では、印刷の仕組みが従来のGDIのEMF形式ではなく、次世代のXPS形式標準に変更されています(但し、互換ドライバーにより、従来プリンターも動作するので、一応心配はない)。

しかし、Visual Studio 2008 の日本語版は、まだ発売されておらず、Express 版が手にはいるようになってから間もない現時点では、私のような末端にいる者がわかるような印刷のコーディングについての情報がほとんど得られません。

  そこで、私がMSDN フォーラム に質問した(下記URL)ところ、たいへん詳しい方から丁寧な解説を戴き、併せて MSDN ライブラリをたよりに格闘(?)の末、何とか Printer が動くところまでこぎ着けました。まだ、情報がない段階なので、できる限りの情報提供をしておきたいと思います。

   [注] 以上のような事情下でのことなので、後日誤りの記載であると判明する
       ものが含まれていた場合には、御容赦下さい。

[情報 1] MSDN フォーラム WPF 関連の話題の中の以下のスレッド

『 従来のPrintPageEventArgs.DrawString メソッド等を使った印刷相当のことを、
  WPF下で実現する方法』

http://social.msdn.microsoft.com/forums/ja-JP/wpfja/thread/d69419d3-e1f0-4bc3-a99d-afca7330d3de/

 

また、現時点では、やっとたどりついた私の最初の成功例コードは、なにがしかのお役に立つと思われますので、基本的には何も手を加えずに公表しておきます。
但し、自分以外の方が見てわかりやすいようにすると言う意味で手を加えてありますが、それはあくまでも、中心部分ではありません。

成功例コードは、以下のリンクから入って御覧下さい。

以下に書き続けます簡単な解説とともに御覧いただけるとわかりやすいようになって
おります。

[情報 2]

私の最初の成功例コード(C#)

成功例コード
http://hokkai53.cocolog-nifty.com/blog/2008/01/wpf_3199.html


-----------------------------------------------------------------

[2] 最初の成功例コード解説と MSDN ライブラリの関連 URL 情報

(1) WPF プログラミングにおける印刷のアウトライン

従来は、PrintPageEventArgs.DrawString メソッド等を使って、印刷のコードを書いてまいりましたが、WPF においては、唯一の絶対座標を使うことができる Canvas に、何らかの描画コントロールを配置して、その Canvas 全体が用紙1ページ分の印刷平面に相当する、という考え方をし、これが基本になります。

そして、従来の複数ページに渡る印刷過程をまともに操作しようとすると、この Canvas 情報を FixedDocument という固定文書形式に変換することになります。

  [注] そこまで求めなければ、他にも簡単な便法もあるようです。

その上で、最後に従来の感覚でいう印刷に関するコードらしき部分に入ります。
しかし、最後の部分は決まりきった短いコードで済んでしまいます。

すなわち、その前の二つの作業が今後印刷に関するコードの中心部分になってきます。

このうちの、最初にキャンバスに描く部分は WPF プログラミング一般の問題に属することになりますので、基本的にはここでは取り上げません。ただ、ここでの実験のための前提とする、最低限のシンプルなもののみを扱うだけです。

従って、ここでの中心問題は、Canvas 情報を FixedDocument に変換することであり、それを理解するのだという覚悟でとりかかる必要があります。

先にも述べましたように、本命のいき方は以上のようなことなので、ここではその本丸を攻めてマスターすることを目指します。

なお、私たちの持っているプリンターは、まだ XPS 対応ではない(デバイス・ドライバーで対応することになると思われる)のが普通ですが、最後のプリンターへの書き込み段階で『 XpsDocumentWriter クラスの Write メソッド 』というのを使いますから、プリンターが XPS 対応か否かの問題はシステムが自動的に判断して対応してくれます。したがって、そうなっているのだ、ということを承知しておくだけで足り、何の心配もいりません。コードの書き換えも不要で、どちらでも通用致します。

今、我々が取り組んでいる入り口のところが、一番険しい山場であり、ここを乗り越えれば楽になるはずですから、何から何まで新しく、わからないことだらけですが、がんばってください。

MSDN『印刷の概要』

  http://msdn2.microsoft.com/ja-jp/library/ms742418.aspx

MSDN『Windows Presentation Foundation のドキュメント』(FixedDocument 関連)

  http://msdn2.microsoft.com/ja-jp/library/ms748388.aspx

-------------------------------------------

(2) 成功例コードの具体的な説明、および、関係事項の MSDN の URL 情報

     ----------------------------

[第1段階] Canvas とその内容の用意    《コード:1》
 
本格的な複数ページ印刷が可能なコードをめざしますが、始めて未知の領域に踏み込むのですから、最低限のものにします。
すなわち、

Canvas 上に Label が1個あって、Content = "Hello World !" と表示されている。
この Hello World ! だけを印刷する1ページだけのコードを作り、その印刷が成功することが最終目標です。(但し、複数ページの場合、どこがどうなるのかは、該当箇所に記載があります。 )

ここでの最重要事項は、印刷用に用いる土台のコンテナとなる Canvas は、親要素(例えば、Window)を持っていてはならない、ということです。
 親要素を持っている Canvas で作業を始めると、ビルドをする時点でエラーになってしまい、もう一度作業を始めからやり直さなければならなくなります。

[後記注]
     コードを見るとわかるように、Canvas は、FixedPage の子要素に組み込まれること
  になります。
   そこで、複数ページ印刷の場合、各ページごとに異なる Canvas インスタンスを
  用意しなければなりません。 例えば1ページ目に "Hello World !" を打ち出し、
  同じ Canvas を利用し、Label の Content の内容のみを入れ替えて、2ページ目を
  打ち出そうとしても、エラーになってしまいます。
 
    
   従って、アプリケーションを作るプロジェクト中のXAML は、そのままにして一切いじりません。それを使うと、親要素を持たざるをえませんから、最終的に失敗します。
では、XAML を使う場合どうしたらよいかは、現在の私にはわかりません。
今後の課題として各自研究して下さい。

 [注] 私は、XAMLを使わない方針([P13]の記事参照)なので追求していませんが、
    XAMLの中に FixedPage を組み込み、その子要素として Canvas を配置する
         のかもしれません。


ここでは、言語コードのみでまいります。

     ----------------------------

[第2段階] Canvas の内容を FixedPage(=>そして 最後に PageContent) にする
                 《コード:2》

Canvas に描かれた内容が、1ページの内容になります。
そして、全体として、3ページであれば、その全体が1個の FixedDocument に
なります。
 
しかし、一気に FixedDocument を作り上げることはできません。
まず、1ページずつです。
実際には、Canvas を FixedDocument にするのではなく、Canvas(1ページ)を FixedPage の形に変換していきます。
ここでは、土台のコンテナ Canvas だけを問題にすればよく、その中にどんな描画コントロールがどれだけ含まれていようと、それに関わる必要はありません。 
そして、FixedPage への変換ができれば、最後にそれをただ ContentPage の中にひょいと入れるだけです。

関係するクラスのライブラリを開き、サンプルを眺めて繋いでいっただけのものです。
私は、MSDN ライブラリと上記 MSDN フォーラムでの稍丼さんの回答以外何も参照するものがなく(WPFの本も持っていない)、それらをつなぎあわせていったのであり、成功例コード中には丸写しで意味のわかっていないところがあります。それでも動いたのです。

コード中、一番のがんばりどころは、この[第2段階]です。

FixedDocument クラス
   こちらも見ておく必要があるでしょうが、次の[第3段階]の情報として載せてあります。

FixedPage クラス
http://msdn2.microsoft.com/ja-jp/library/system.windows.documents.fixedpage.aspx

PageContent クラス
http://msdn2.microsoft.com/ja-jp/library/system.windows.documents.pagecontent.aspx

     ---------------------------- 

[第3段階]FixedPage から FixedDocument を作る  《コード:3》

ここで、いよいよ FixedDocument を作り上げることになります。

FixedDocument は、[第2段階] で最終的に作り上げた PageContent と DocumentPaginator の二つから作り上げます。
PageContent は既にできているので、ここでは DocumentPaginator を作成します。

       
FixedDocument クラス
http://msdn2.microsoft.com/ja-jp/library/system.windows.documents.fixeddocument.fixeddocument.aspx

DocumentPaginator クラス
http://msdn2.microsoft.com/ja-jp/library/system.windows.documents.documentpaginator.aspx

     ----------------------------

[第4段階] Printer(Queue)への書き出し 《コード:4》

最終段階です。ここが、従来の感覚からすると、普通に想像される印刷コードです。

XpsDocumentWriter クラスの Write メソッドを使ってプリンター(Queue)に書き出します。
ここが、プログラミング上の、現実の印刷部分です。

なお、XpsDocumentWriter クラスの Write メソッドに関しては、私から見ますと初めはたいへんわかりにくい部分があります。
それは、他の関係クラスとの全体構造の中で、このクラスと Write メソッドが置かれている位置づけのわかりにくさに関係します。
そして、MSDNライブラリの記述自体が、はっきりいうと、そこがよくわかるように書かれておりません。
わかってしまえば、使い方にどうということはないのですが、始めての場合は私が陥ってしまったような理解(実は誤解)に陥る方もいらっしゃるのではないかと思われます。
私のように無駄な時間と労力を費やさないためにも、冒頭に示しましたMSDNフォーラムのスレッド中の、上から8番目の私のメッセージと次の9番目の稍丼さん(yayadon と同一人)のメッセージを御覧になって下さい。そこにすべてが尽くされております。

結論だけ、ここで整理しておきます(上記問題とは、初めは以下のようにすっきりわからない、ということにあります)。

XpsDocumentWriter クラスには、コンストラクタがありません。
そのオブジェクトは、
① PrintQueue.CreateXpsDocumentWriter メソッドから取得する方法と 
② XpsDocument.CreateXpsDocumentWriter メソッドから取得する方法の二通りがあります。

①のルートで取得したXpsDocumentWriter オブジェクトは、XpsDocument.xps ファイル
の書き出しをする場合に使います。
プリンターでの印刷をする場合には、②のルートで取得したXpsDocumentWriter オブジェクトを使わなくてはなりません。

なお、PrintQueue.CreateXpsDocumentWriter(); の引数にはいくつかの指定方法が
あり、それによって内容の異なる印刷ダイアログボックスが表示されるようになっております。

そして、XpsDocumentWriter.Write  メソッドに、[第3段階]で作成した FixedDocument オブジェクトを引数としてセットすれば、プリンターが動き出します。 

XpsDocumentWriter クラス
http://msdn2.microsoft.com/ja-jp/library/system.windows.xps.xpsdocumentwriter.aspx

XpsDocumentWriter.Write メソッド
http://msdn2.microsoft.com/ja-jp/library/system.windows.xps.xpsdocumentwriter.write.aspx

LocalPrintServer クラス
http://msdn2.microsoft.com/ja-jp/library/system.printing.localprintserver.aspx

PrintQueue クラス
http://msdn2.microsoft.com/ja-jp/library/system.printing.printqueue.aspx

以上です。

最初の成功例コードへのリンク
    このドキュメントの初めの部分にあります。
念のため。

では、御健闘を祈ります。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
目次に戻る ・・・・ 左欄のカテゴリー 【パソコンの窓】 をクリック
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

| | コメント (0)

WPF:印刷の初めての成功例コード

------------------------------------------------- 

左の欄の、カテゴリー『パソコンの窓』内の [P14] の記事(WPF: プリンター印刷)
の付属資料コードです。そちらの本文とあわせて御覧下さい。
(本文のウィンドウとコードのウィンドウの二つを開いたほうが、見やすいです。)

本文
http://hokkai53.cocolog-nifty.com/blog/2008/01/p14wpf_xps_9e5d.html

なお、さらにこの成功例コードを解体して、実際の複数ページデータ読み出しに適合させた、第二付属コードへのリンク が、このページの最下段にある [後記] の末尾にあります。
-------------------------------------------------
コードの内容

WPFプログラミングの、本格的な複数ページ印刷が可能なコードをめざしますが、
始めて未知の領域に踏み込むのですから、
Canvas 上に Label が1個あって、Content = "Hello World !" と表示されている。
この Hello World ! だけを印刷する1ページだけのコードです。
複数ページの場合、どこがどうなるのかは、該当箇所に記載してあります。

中心部分以外のコードは、できるだけ省いています。

これ以外は、ブログ本文の解説を御覧下さい。以下、コードです。

XAML

<Window x:Class="MyFirstPrinting.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" >
    <Grid>
       
    </Grid>
</Window>

WPF アプリケーション・プロジェクトを新規作成したときのまま、何もしていない状態です。

MyFirstPrinting のところは、各自のもので差し支えありません。
逆にここを無理に変えようとすると、面倒な作業が必要になるので、そのことがわかっている方以外はそのまま。

以下の言語コード中で、XAML で処理して差し支えないものは、たった一行です。
ですから、一切使わないでまいります。

//-----------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;//実際は不要
using System.Windows.Navigation;//実際は不要
using System.Windows.Shapes;//実際は不要
//(以上)WPF アプリケーションとして、プロジェクトを新規作成した状態
//----------------------------------------
//アセンブリ参照設定で以下の二つを追加する
// ReachFramework
// System.Printing
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using System.IO;
using System.Printing;
using System.Windows.Markup;//IAddChild
//----------------------------------------
namespace MyFirstPrinting  //各自バラバラでよい
{
    public partial class Window1 : Window
    {
        Canvas printCanvas;
        Label lblHello;         
    //-----------------------------------   
        public Window1()
        {
            InitializeComponent();
            //--------------------------------------------
            MakeCanvasForPrint();
                //《コード:1》

            FixedDocument fixedDocument
                                 = CreateFixedDocumentFromFixedPages();
                //《コード:3》
                //《コード:3》は《コード:2》の結果を吸収しているので、
                //《コード:3》の実質は、《コード:2》を含み、
                //CreateFixedDocumentFrom"Canvaces"(); ともいうべき
                //内容になっている。

            SendFixedDocumentToPrinter(fixedDocument); 
                //《コード:4》
        }
 
       //-------------------------------------------------
        //《コード:4》 [第4段階] Printer(Queue)への書き出し
        //-------------------------------------------------   

        void SendFixedDocumentToPrinter(FixedDocument fixedDocument)
        {

            LocalPrintServer ps = new LocalPrintServer();
            PrintQueue pq = ps.DefaultPrintQueue;
            
            PrintDocumentImageableArea imgArea = null;
            XpsDocumentWriter xpsdw
                         = PrintQueue.CreateXpsDocumentWriter(ref imgArea);
       //上記メソッドの引数並びは、いろいろな種類があり、
              //それによって、印刷ダイアログを表示する。
              //PrintDialog クラスがあることとの関係は、まだよくわかりません。
            xpsdw.Write(fixedDocument);

        }
       
        //-------------------------------------------------
        //《コード:3》[第3段階]FixedPage から FixedDocument を作る
        //-------------------------------------------------   

        private FixedDocument CreateFixedDocumentFromFixedPages()
        {
            FixedDocument fixedDocument = new FixedDocument();
            fixedDocument.DocumentPaginator.PageSize
                                                      = new Size(96 * 8.5, 96 * 11);
            //---------------------------------------------
            PageContent pageContent = CreateFixedPageFromCanvas();
       //ここで《コード:2》が使われる
            fixedDocument.Pages.Add(pageContent);
            //複数ページの場合は、ここで複数回 Add()を繰り返す。
            //このプログラムでは、1ページのみを作る。
            return fixedDocument;
        }//CreateFixedDocumentFromFixedPages()
       

        //-------------------------------------------------
        //《コード:2》    [第2段階]Canvas の内容を
        //                    FixedPage(=>そして 最後に PageContent) にする
        //-------------------------------------------------   

        PageContent CreateFixedPageFromCanvas()
        {
            //作られた FixedPage は、最後に PageContent の子要素とされて、
            //次の FixedDocument 作成の準備が整う
            PageContent pageContent = new PageContent();
            FixedPage fixedPage = new FixedPage();

            //Canvas がFixedPage(=印刷用紙) 中のどこに位置づけられるか。
            FixedPage.SetLeft(printCanvas, 0);
            FixedPage.SetTop(printCanvas, 0);

      //この近辺に、Canvas サイズを用紙サイズに合わせる
            //調整用のコードが加わってくるものと考えられる。

            double pageWidth = 96 * 8.5;
            double pageHeight = 96 * 11;

            fixedPage.Width = pageWidth;
            fixedPage.Height = pageHeight;

            fixedPage.Children.Add((UIElement)printCanvas);
            //printCanvas=親(例えばWindow)があるとエラーになる
            //これが、Canvas は親要素を持ってはならない、という根拠

            Size sz = new Size(8.5 * 96, 11 * 96);
            fixedPage.Measure(sz);
            fixedPage.Arrange(new Rect(new Point(), sz));
            fixedPage.UpdateLayout();

            ((IAddChild)pageContent).AddChild(fixedPage);
            return pageContent;
        }//CreateFixedPageFromCanvas()
       
        //-------------------------------------------------
        //《コード:1》[第1段階]Canvas とその内容の用意
        //-------------------------------------------------

        void MakeCanvasForPrint()
        {//Canvas 全体が、1ページになる
            this.WindowState = WindowState.Maximized;//Window
            //---------------  Canvas  --------------------
            printCanvas = new Canvas();
                  // ここで this.Content = printCanvas; を
        // 絶対入れてはならない(親要素を持たない)
            printCanvas.Background = Brushes.Transparent;
            printCanvas.Width = 800;//数値はともに適当
            printCanvas.Height = 600;
        //後述の数値(8.5 * 96, 11 * 96)と不整合
                 //とりあえず、御勘弁を!
            //--------------  Label  ------------------------
            lblHello = new Label();
            printCanvas.Children.Add(lblHello);
            lblHello.Background = Brushes.Transparent;
            lblHello.Width = 160;
            lblHello.Height = 30;
            Canvas.SetTop(lblHello, 100);
            Canvas.SetLeft(lblHello, 50);
            lblHello.Content = "Hello World !";//これを印刷するのが最終目標          
        }//MakeCanvasForPrint()

    }//class Window1

}//namespace

[後記]
   このコードを実用に供することができるように組み換えた上で、実際に複数ページ
  印刷をしてみました(ある程度複雑な表の複数ページ印刷)。
   基本的な枠組みができあがって一通りのことが見通せた段階に立ってみると、
  GDI時代より、WPF下の方が印刷のコーディングは、いろいろな意味でわかりやすく
  可読性が高いものになった、という印象です。
      コーディング上では、あたかもラインプリンターからページプリンターになったような
  ものなのですから。


  なお、私はまだ最終的な最適解にまで到達しておりませんが、
実用化のためには上記コードを解体し、実際に複数ページ印刷ができるように
組み換える必要があります。 その際には、GDI当時とは異なる、WPFに対応した感覚が求められるように思われます。
ご参考までに、第二付属コードとして、下記のリンクから見られるようにしておきます。

 
[実際の複数ページ印刷対応の実用コード例(第二付属コード)]

    下記リンクをクリックして下さい。

http://hokkai53.cocolog-nifty.com/blog/2008/07/post_9b2d.html

以上。

| | コメント (0)

« 2007年12月 | トップページ | 2008年3月 »