2007.4.30.
石立 喬
Visual C++ 2005 Express Edition の易しい使い方(5)
――― プリンタに出力したり、ファイルに出力したりする ―――
ここでは、計算結果を画面に表示し、プリンタへも出力する方法を説明する。さらに、別の場所で使用したり、ワープロなどで取り込んだりするために、内容をテキストファイルとして保存する。
概要
なんらかの表を作成し、印刷プレビューを実行し、印刷する方法を紹介する。フォーム上のテキストボックスに計算結果を出力し、印刷は、テキストボックスの内容を印刷する。
「易しい使い方(2)」では、計算結果を出力するのに、C言語で使い慣れたprintfに似たsprintf_sを用いたが、ここでは.NET FrameworkによるString::Formatクラスを用いる。
また、文字を画像としてではなく、文字列として表示したので、テキストとして容易にファイルに書き出すことができる。
テキストボックスの設定
テキストボックスの使い方は、すでに「易しい使い方(3)」で紹介しているが、ここではさらに細かい設定をしているので、一部重複するが、最初から解説する。
1) 統合開発環境のメニューから、「表示」→「ツールボックス」を選択する。
2) ツールボックスが現れるので、「TextBox」をクリックする。次に、「Form1.h[デザイン]」ウインドウのフォーム上で、左上方から右下方に向けてマウスをドラッグする。斜めにドラッグしたにもかかわらず、細い1行分のテキストボックスしか生じない(デフォルトでは、Multilineプロパティがfalseのため)が、気にしない。Multilineプロパティをtrueに設定してから再度詳細に調整する。DockプロパティをFillに変更することなく、適度に小さめに設定する方が良い。
3) テキストボックスを右クリックし、「プロパティ」をクリックする。
4) プロパティ・ウインドウで、以下のように設定する。各欄の左をクリックすると右に下向き三角が現れ、リストから選択できる。
「動作」欄で、
Multiline -------- True (Falseから) テキストボックスを縦方向に広げる。
ReadOnly ------- True (Falseから) テキストボックスに書き込めなくする。
TabStop -------- False (Trueから) 文字を反転(選択)状態にさせない。
「表示」欄で
BackColor ------ Window (Controlから変更) フォームに合わせる(BorderStyleと関連)。
BorderStyle ----- None (Fixed3Dから変更) テキストボックスの存在を隠す。
Font ----------- MS ゴシック,12pt (MS UI Gothic,9ptから変更) 大き目の等幅フォントにする。
テキストボックスへの文字列の出力方法
テキストボックスの名称をtextBox1とし、書き込みたい文字列をstring1とすると、
textBox1->Text=string1;
で容易に書き込める。複数行の書き込みは、文字列の最後に "\r\n" を付けておき、
textBox1->AppendText(string1);
を繰り返せばよい。
String::Formatによる書式設定の方法
「易しい使い方(2)」で、
string1=String::Format(“ A={0} B={1} C={2} ”,a,b,c);
のような使い方を紹介した。この方法は、変数が整数であるか実数であるかにより、自動的に最適の書式で文字列化される便利なものである。
しかし、上記のような単純な使い方では作表には不適なので、C言語のprintfに相当した使い方の一部を紹介する。ただし、nは変数の並び順、pは表示のための占有桁数(フィールド幅)である。
{n,p:D} ------ 整数を右詰で表示する( {n,5:D} は %5d と同等)
{n,p:Dq} ----- 同上だが、q桁に満たない部分を頭から0で埋める
{n,p:F} ------ 小数点以下を2桁にして、実数を右詰で表示する
{n,p:Fq} ----- 小数点以下をq桁にして、実数を右詰で表示する ( {n,12:F8} は %12.8f と同等)
印刷のための準備
ツールボックスから、下記左の部品をクリックし、フォーム上をクリックすると、下記右に示したようなインスタンスが生成され、フォーム下部のコンポーネント・トレイに表示される。
PrintDialog ----------- printDialog1
PrintPreviewDialog ---- printPreviewDialog1
PrintDocument ------- printDocument1
プログラムの概要
ここでは、文字列を画像として出力することなく、メニュー操作の結果として画面を書き換えることもしないので、Form1_Printは使用しない。代わりに主要部分をForm1_Loadに記述する。
Form1_Loadでは、1から10までの数の平方根と立方根を求め、String::Formatメソッドを用いて書式設定する。1から10までの数は、右詰め2桁の整数として表示するので
{0,2:D}を用い、平方根と立方根は、小数点を含めて11桁、小数点以下9桁の実数として表示するので
{1,11:F9} と {2,11:F9} を用いる。
各行の最後には、復帰改行を意味する \r\n をつけ、textBox1->AppendTextで追加してゆく。
印刷するには、印刷対象のprintDocument1を用意する。コンポーネント・トレイの「printDocument1」をダブルクリックすると、printDocument1_PrintPage
のスケルトンができているので、そこに、あらためて、textBox1の内容を書き出すコードを記述する。
for each という見慣れない文があるが、これは、コレクションまたは配列の処理したいオブジェクトを最初から順次実行するのに便利である。
プログラム中の
int i=0;
for each (String^ string1 in textBox1->Lines){
g->DrawString(string1,font1,Brushes::Black,X0,Y0+i*15);
i++;
}
の意味は、
String^ string1;
for(int i=0;i<textBox1->Lines->Length;i++){
string1=textBox1->Lines[i];
g->DrawString(string1,font1,Brushes::Black,X0,Y0+i*15);
}
と同等である。すなわち、for each 文を用いると、テキストボックス中の行が何行あるか分からなくても、行が存在する限り、上から順次に書き出してくれる。
印刷時の用紙に対する配置と文字のフォントはprintDocument1_PrintPageで決まる。作表には、可変幅フォント(Proportional
Font)ではなく、等幅フォント(Fixed-width Font、Monospaced Font)を使用する必要がある。
プログラム
//起動時に呼び出される
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
String^ string1;
double sqroot,cbroot;
textBox1->Text= " 数 平方根 立方根 \r\n";
textBox1->AppendText(" ---- ------------- ------------- \r\n");
for(int i=1;i<=10;i++){
sqroot=Math::Sqrt(i);
cbroot=Math::Pow(i,1.0/3.0);
string1=String::Format(" {0,2:D} {1,11:F9} {2,11:F9} \r\n",i,sqroot,cbroot);
textBox1->AppendText(string1);
}
}
//メニュー「印刷プレビュー」
private: System::Void buttonPreview_Click(System::Object^ sender, System::EventArgs^
e) {
printPreviewDialog1->Document=printDocument1;
printPreviewDialog1->ShowDialog();
}
//メニュー「印刷」
private: System::Void buttonPrint_Click(System::Object^ sender, System::EventArgs^
e) {
if(printDialog1->ShowDialog()==System::Windows::Forms::DialogResult::OK)
printDocument1->Print();
}
//printDocument1->Print(); で呼び出される
private: System::Void printDocument1_PrintPage(System::Object^sender, System::Drawing::Printing::PrintPageEventArgs^
e) {
Graphics^ g=e->Graphics;
float X0=50,Y0=50;
Drawing::Font^ font1=gcnew Drawing::Font("MS ゴシック",12);
int i=0;
for each (String^ string1 in textBox1->Lines){
g->DrawString(string1,font1,Brushes::Black,X0,Y0+i*15);
i++;
}
}
//メニュー「保存」
private: System::Void menuSaveFile_Click(System::Object^ sender, System::EventArgs^
e) {
SaveFileDialog^ sfdlg=gcnew SaveFileDialog();
sfdlg->Filter="テキストファイル(*.txt)|*.txt";
if(sfdlg->ShowDialog()!=System::Windows::Forms::DialogResult::OK) return;
System::IO::StreamWriter^ swriter=gcnew System::IO::StreamWriter(sfdlg->FileName);
swriter->Write(textBox1->Text);
swriter->Close();
}
プログラムの実行結果
図1は実行結果である。テキストボックスを使っているが、境界を消してあり、背景をフォームと同色にしてあるので、テキストボックスの存在が気にならない。
図1 実行結果
念のために、印刷プレビューと印刷のためのメニューを図2に示す。
図2 「印刷」メニューを表示したところ