次のチュートリアルでは、DotNet を使用してテキスト ファイルを表示、印刷するときの基本事項を示します。
関連トピック:
全体の流れ:
テキスト ボックスおよび 2 つのボタンを含む MaxCustomControls アセンブリを使用して MaxForm を定義します。
[印刷] (Print)ボタンのイベント ハンドラによって呼び出されるテキスト ファイルを印刷する関数を実装します。
[ファイルを開く](Open File)ボタンのイベント ハンドラの呼び出し時にテキスト ファイルを開く関数を実装します。
イベント ハンドラを登録します。
イベント ハンドラにガベージ コレクションが実行されないようにします。
例
--Example code provided by Artur Leão ( dotNet.loadAssembly "MaxCustomControls.dll" local filetoprint = "" local printFont = dotnetobject "System.Drawing.Font" "Arial" 10 local streamReader hForm = dotNetObject "MaxCustomControls.MaxForm" hForm.Size = dotNetObject "System.Drawing.Size" 640 480 hForm.FormBorderStyle = (dotnetclass "System.Windows.Forms.FormBorderStyle").FixedToolWindow hForm.Text = "Printing with dotNet" hForm.ShowInTaskbar = False txtTextBox = dotNetObject "System.Windows.Forms.TextBox" txtTextBox.MultiLine = True txtTextBox.WordWrap = False txtTextBox.Size = dotNetObject "System.Drawing.Size" 500 430 txtTextBox.Location = dotNetObject "System.Drawing.Point" 10 10 txtTextBox.ScrollBars = txtTextBox.ScrollBars.Both btnOpenFile = dotNetObject "System.Windows.Forms.Button" btnOpenFile.Location = dotNetObject "System.Drawing.Point" 520 10 btnOpenFile.Text = "Open File" btnPrint = dotNetObject "System.Windows.Forms.Button" btnPrint.Location = dotNetObject "System.Drawing.Point" 520 40 btnPrint.Text = "Print" frmOpenFileDialog = dotNetObject "System.Windows.Forms.OpenFileDialog" frmOpenFileDialog.Filter = "txt files (*.txt)|*.txt|Script Files (*.ms)|*.ms|ini files (*.ini)|*.ini|XML files (*.xml)|*.xml|All files (*.*)|*.*" fn btnOpenFile_Click = ( dlgResult = dotNetClass "System.Windows.Forms.DialogResult" if frmOpenFileDialog.ShowDialog() == dlgResult.OK do ( IOFile = dotNetClass "System.IO.File" txtTextBox.Text = IOFile.ReadAllText frmOpenFileDialog.Filename filetoprint = frmOpenFileDialog.Filename )--end if )--end fn fn pd_PrintPage sender ev = ( count = 0 linesperpage = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics) yPos = 0 leftMargin = ev.MarginBounds.Left topMargin = ev.MarginBounds.Top currentline = "" brush = dotnetobject "System.Drawing.Solidbrush" (dotnetclass "System.Drawing.Color").black stringformat = dotnetobject "System.Drawing.StringFormat" while count < linesperpage do( currentline = streamReader.ReadLine() if currentline == undefined do exit yPos = topMargin + count * printFont.GetHeight(ev.Graphics) ev.Graphics.DrawString currentline printFont brush leftMargin yPos stringformat count += 1 )--end while loop if currentline != undefined then ev.HasMorePages = true else ev.HasMorePages = false )--end fn fn btnPrint_Click = ( if filetoprint != "" then ( try ( streamReader = dotnetobject "System.IO.Streamreader" filetoprint pd = dotnetobject "System.Drawing.Printing.PrintDocument" dotnet.addeventhandler pd "PrintPage" pd_PrintPage pd.Print() streamReader.Close() )catch print (getCurrentException()) )--end if )--end fn dotNet.AddEventHandler btnOpenFile "Click" btnOpenFile_Click dotNet.AddEventHandler btnPrint "Click" btnPrint_Click hForm.Controls.Add(txtTextBox) hForm.Controls.Add(btnOpenFile) hForm.Controls.Add(btnPrint) dotnet.setLifetimeControl btnOpenFile #dotnet dotnet.setLifetimeControl btnPrint #dotnet hForm.ShowModeless() )
(
dotNet.loadAssembly "MaxCustomControls.dll"
3ds Max 固有のコントロールを含むカスタム アセンブリをロードします。
local filetoprint = ""
この変数には印刷するファイル名が格納されます。
local printFont = dotnetobject "System.Drawing.Font" "Arial" 10
フォント名 Arial、フォント サイズ 10 で System.Drawing.Font クラスのオブジェクト インスタンスを作成して、このオブジェクトを後で使用するためにユーザ変数に格納します。
local streamReader
このユーザ変数にはストリーム リーダが保持されます。
hForm = dotNetObject "MaxCustomControls.MaxForm"
メイン フォームを作成します。
hForm.Size = dotNetObject "System.Drawing.Size" 640 480
System.Drawing.Size オブジェクトを使用して、フォームのサイズを 640 x 480 に設定します。
hForm.FormBorderStyle = (dotnetclass "System.Windows.Forms.FormBorderStyle").FixedToolWindow
また、フォームの境界スタイルを、System.Windows.Forms.FormBorderStyle クラスによって公開される定義済みの FixedToolWindow に設定します。
あるいは、左側の hForm.FormBorderStyle 値は右側で割り当て元とするクラスと同一となることを利用して、次のようにできます。
hForm.FormBorderStyle = hForm.FormBorderStyle.FixedToolWindow
hForm.Text = "Printing with dotNet"
フォームのタイトルを次の文字列に設定します。
hForm.ShowInTaskbar = False
...新しいフォームが Windows のタスクバーに表示されないことを確認します。
txtTextBox = dotNetObject "System.Windows.Forms.TextBox"
ここで、印刷するファイルの内容を表示するテキストボックスが必要になります。
txtTextBox.MultiLine = True
txtTextBox.WordWrap = False
このテキストボックスは複数行テキストには対応しますが、ワード ラップには対応しません。
txtTextBox.Size = dotNetObject "System.Drawing.Size" 500 430
txtTextBox.Location = dotNetObject "System.Drawing.Point" 10 10
このテキストボックスには 500x430 ピクセルが格納され、その左上隅はフォームの左上隅に対して相対的に、座標 10,10 に配置されます。
txtTextBox.ScrollBars = txtTextBox.ScrollBars.Both
水平および垂直スクロールバーの両方が許可されます。
btnOpenFile = dotNetObject "System.Windows.Forms.Button"
btnOpenFile.Location = dotNetObject "System.Drawing.Point" 520 10
btnOpenFile.Text = "Open File"
印刷するファイルを開くためのボタンが必要になります。
新しいボタン オブジェクトを作成して、その位置をフォーム内の座標 520,10 に設定します。キャプションは[ファイルを開く](Open File)となります。
btnPrint = dotNetObject "System.Windows.Forms.Button"
btnPrint.Location = dotNetObject "System.Drawing.Point" 520 40
btnPrint.Text = "Print"
もう 1 つ、印刷を開始するためのボタンが必要となります。
新しいボタン オブジェクトを作成して、その位置をフォーム内の座標 520,40 に設定します。キャプションは[印刷] (Print)となります。
frmOpenFileDialog = dotNetObject "System.Windows.Forms.OpenFileDialog"
frmOpenFileDialog.Filter = "txt files (*.txt)|*.txt|Script Files (*.ms)|*.ms|ini files (*.ini)|*.ini|XML files (*.xml)|*.xml|All files (*.*)|*.*"
印刷するファイルを選択するために、通常のファイル タイプをフィルタする OpenFileDialog オブジェクト セットが必要になります。
fn btnOpenFile_Click = (
[ファイルを開く](Open File)ボタンが押されたときに呼び出されるイベント ハンドラ関数が必要になります。
dlgResult = dotNetClass "System.Windows.Forms.DialogResult"
以前に定義済みの OpenFileDialog を使用します。このため、ダイアログの結果と定義済みの結果とを比較するための DialogResult クラスを含むユーザ変数が必要になります。
if frmOpenFileDialog.ShowDialog() == dlgResult.OK do (
ダイアログを表示してユーザにファイルを取得させる OpenFileDialog オブジェクトの ShowDialog() メソッドを呼び出します。値が戻されたら、ダイアログの戻り値と DialogResult クラスの OK 値とを比較して、(ユーザによるキャンセルではなく)処理が正常に終了したことを確認します。
IOFile = dotNetClass "System.IO.File"
txtTextBox.Text = IOFile.ReadAllText frmOpenFileDialog.Filename
有効なファイルが選択されたら、System.IO.File クラスを使用して、ファイルを読み込み、その内容をフォームのテキストボックスに割り当てます。System.IO.File クラスの ReadAllText メソッドを呼び出し、引数として OpenFileDialog により返されるファイル名を渡します。このメソッドの結果はテキストボックスのテキストに割り当てられます。
filetoprint = frmOpenFileDialog.Filename
ここで、ローカル変数の filetoprint に選択したファイル名を格納します。このファイル名はファイルの印刷時に使用できます。
)--end if
)--end fn
fn pd_PrintPage sender ev = (
[印刷] (Print)ボタンのイベント ハンドラ関数を定義する前に、印刷処理全体を実行する関数が必要です。これは 2 つの引数、つまり sender と event をとります。
local count = 0
テキストの処理時に行数を増加させるカウント変数が必要となります。
linesperpage = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics)
1 ページごとの行数を計算するには、マージン内にあるドキュメントの印刷ページの高さを、印刷フォントの高さで除算する必要があります。
yPos = 0
この変数は、印刷する垂直位置を計算、格納するために使用されます。
leftMargin = ev.MarginBounds.Left
topMargin = ev.MarginBounds.Top
左および上のマージンも、ユーザ変数に取り込みます。
currentline = ""
この変数は現在の行を保持します。
brush = dotnetobject "System.Drawing.Solidbrush" (dotnetclass "System.Drawing.Color").black
黒の塗り潰しブラシ オブジェクトを作成します。
stringformat = dotnetobject "System.Drawing.StringFormat"
この変数には、DrawString メソッドで以降に必要となるオブジェクトが含まれます。
while count < linesperpage do (
カウンタがページごとの行数よりも少ない間は、以下を繰り返します
currentline = streamReader.ReadLine()
ストリームリーダから行を読み込みます - 初めに変数が開始され、[印刷] (Print)ボタンのイベント ハンドラに割り当てられます。
if currentline == undefined do exit
currentline 変数に未定義のものが含まれている場合(つまり、ファイルの最後に達しても読み込みが続く場合)には、ループを終了します。
yPos = topMargin + count * printFont.GetHeight(ev.Graphics)
現在の行カウンタによるフォント強度の高さを上部のマージンに追加することによって、印刷する垂直位置を計算します。
ev.Graphics.DrawString currentline printFont brush leftMargin yPos stringformat
最後に、左マージンと同じ水平位置、および前のステップで計算された yPos 値と文字列形式オブジェクトに基づくフォーマットに従った垂直位置にある現在のフォントおよびブラシを使用して、現在の行の文字列を描画できます。
count += 1
カウンタに 1 が加算され、ページの最後またはファイルの最後に達するまでループが繰り返されます。
)--end while loop
if currentline != undefined then ev.HasMorePages = true else ev.HasMorePages = false
ループが終了した理由を確認します - 現在の行が定義されている場合、印刷するページ数が多いため、PrintDocument オブジェクトの対応するプロパティを設定して印刷を続ける必要があるかどうかを通知します。
同じことを次のように短く記載できます
ev.HasMorePages = currentline != undefined
)--end fn
fn btnPrint_Click = (
[印刷] (Print)ボタンのイベント ハンドラを定義できるようになりました。
if filetoprint != "" do (
try (
印刷用に選択したファイル名が空の文字列でない場合は、次の処理を試行します。
streamReader = dotnetobject "System.IO.Streamreader" filetoprint
スクリプトの先頭で初期化される streamReader 変数を System.IO.Streamreader クラスの dotNetObject インスタンスに設定します。これは、MAXScript の fileStream 値に類似しており、ディスク上のファイルに対する IO アクセスが可能になります。
pd = dotnetobject "System.Drawing.Printing.PrintDocument"
また、実際の印刷を行う PrintDocument オブジェクトを作成します。
dotnet.addeventhandler pd "PrintPage" pd_PrintPage
イベント ハンドラを、以前に定義した MAXScript 関数を呼び出す PrintDocument オブジェクトに追加します。
pd.Print()
PrintDocument オブジェクトの Print() メソッドを呼び出して、印刷を開始することができます。これによって、各ページにつき 1 回、PrintDocument の hasMorePages プロパティが、戻り値が返されるポイントで false に設定されるまで、印刷のイベント ハンドラ関数が呼び出されます。
streamReader.Close()
戻ったら、ストリームを閉じます。
) catch print (getCurrentException())
印刷コードに問題がある場合は、エラーを捕捉し、前回の例外を出力します。
)--end if
)--end fn
dotNet.AddEventHandler btnOpenFile "Click" btnOpenFile_Click
dotNet.AddEventHandler btnPrint "Click" btnPrint_Click
以前に定義した 2 つのイベント ハンドラ関数を 2 つのボタンに追加できるようになりました。
hForm.Controls.Add(txtTextBox)
hForm.Controls.Add(btnOpenFile)
hForm.Controls.Add(btnPrint)
テキストボックスと 2 つのボタンもフォームに追加できます。
dotnet.setLifetimeControl btnOpenFile #dotnet
dotnet.setLifetimeControl btnPrint #dotnet
スクリプト化されたイベント ハンドラを DotNet コントロールに追加し、コントロールをラップする MAXScript 値より長い寿命をもつフォームにこれらのコントロールを配置しているため、これらのボタンの寿命コントロールが DotNet により制御されるように設定します。
確認 :
イベント ハンドラの作成時に既定動作とならない理由は?
上記の方法は、その他の DotNet オブジェクトに配置される DotNet オブジェクトにのみ適用されるものです。
イベント ハンドラがあり、オブジェクトの寿命コントロールで変更が生じないようにする場合の例として、タイマ オブジェクトがあります。オブジェクトをラップしている MAXScript 値が削除されるときにタイマ オブジェクトを削除したい場合があります。タイマ オブジェクトの寿命コントロールを #dotnet に設定すると、DotNet オブジェクトではタイマ オブジェクトへの参照が維持されないため、以降のランダムなポイントで DotNet ガベージ コレクションによってタイマ オブジェクトが削除されます。
hForm.ShowModeless()
最後に、フォームを表示します。
)--end script