RTF)のファイルで保存してみましょう。この操作にはコールバック関数が必要となるので、通常の方法では実現することができません。そこで、このコールバック関数のマシン語コードを変数に格納して、その変数のアドレスをコールバック関数のアドレスとして指定することにします。サイズが64Kバイト以上のテキストファイルを扱う場合も今回の方法を用いる必要があります。今回は、これについても扱うことにしましょう。リッチエディットコントロールのストリーム処理ストリームとはリッチエディットコントロールへの読み込みや内容の保存は、『ストリーム(stream)』と呼ばれる機能によって行なわれます。これは、アプリケーションとリッチエディットコントロールとの間のデータの入出力を、連続したバイトデータの流れ(stream)であるとみなすという考え方に基づくものです。川の上流から下流に向かって水が流れていくように、リッチエディットコントロールからアプリケーションに向かって、あるいはアプリケーションからリッチエディットコントロールに向かってデータが流れていくような感じです。リッチエディットからアプリケーションに向かう川(ストリーム)に水(データ)を流し込むと、それはリッチエディットコントロールがデータをストリームに出力したということになります。下流にあたるアプリケーション側ではこの水(データ)を受け取ることができます。逆に、アプリケーション側を上流として、ここからリッチエディットに向かう川(ストリーム)に水(データ)を流し込むと、下流に位置するリッチエディットではこの流れから水(データ)を取り出します。リッチエディットコントロールはデータをストリームから入力したということになります。川の水の場合は、上流から下流に向かって途切れることなく連続的に流れていきますが、リッチエディットコントロールとやり取りするデータはデジタルデータなのですから、水とまったく同じように連続的に流れていくというわけにはいきません。そこで、リッチエディットコントロールでは、データ全体を小分けにして、小さなデータのかたまりを先頭から順に送る、という方法が取られます。受け取る側では、送り側で送られた順にそれらのデータを受け取ることになります。ストリーム出力とファイル保存リッチエディットコントロールからアプリケーションにデータを送る必要がある場合、まずはリッチエディットコントロールがデータをストリームに出力し、アプリケーション側がそれをストリームから受け取る必要があります。メッセージ)を送ります。この指令を受け取ったリッチエディットコントロールは、データを小分けにし、先頭から順番にデータを送り出して行くのです。アプリケーション側では、このストリームからデータを受け取らなければなりません。リッチエディットコントロールの場合、ストリームによるのデータ転送が行なわれるときに、アプリケーション側が準備したコールバック関数が呼び出されることになっています。このコールバック関数は、小分けにされたデータのかたまり1つ1つが送られるたびに呼び出されます。このコールバック関数には、小分けにされた1つのデータのかたまりとそのサイズなどの情報が引数として渡されてきます。コールバック関数側では、このデータを処理して行きます。小分けにされたデータは先頭から順番に送られてくるので、コールバック関数内でシーケンシャルファイル処理によって保存していけば、すべてのデータを1つのファイルに保存することができるということが分かりますね。メッセージ)を送るとき、アプリケーションは任意の32ビット値をセットすることができます。この32ビット値は、コールバック関数が呼ばれるときにその引数の1つとして渡されます。一般的には、ファイルを書き込みアクセスでオープンしておき、そのファイルハンドル(あるいはメンバとしてハンドルを含む構造体のアドレス)が32ビット値として指定されます。コールバック関数内でこのファイルハンドルが指すファイルに書き込んでいくようにすれば、コントロールの内容をファイルに保存することができるのです。ストリーム入力とファイル読み込みアプリケーションからリッチエディットコントロールにデータを送る必要がある場合、アプリケーションがデータをストリームに出力して、リッチエディットコントロールがそれをストリームから入力する必要があります。メッセージ)を送ります。すると、リッチエディットコントロールは、アプリケーションに「○○バイト分だけデータを受け取りたいから、その分だけのデータを出力してくれ」という指令を出します。この指令は、アプリケーション側が準備したコールバック関数を呼び出すという形で行なわれます。アプリケーション側は、コールバック関数の中で、送りたいデータの先頭から指定されたバイトぶんだけ順番に送らなくてはなりません。この指令(コールバック関数の呼び出し)は、すべてのデータが送られるまで繰り返し行なわれるので、アプリケーションはそのたびにデータを送り出していくのです。ファイルからデータを読み込んでそれを送る場合は、シーケンシャル処理によって読み込んでいけば、先頭から順番にデータを取り出してリッチエディットコントロールに送り出していくことができますね。メッセージを送る場合もアプリケーションは任意の32ビット値をセットすることができて、この値がコールバック関数の引数として渡されてきます。したがって、ファイルを読み取り属性でオープンしておいて、そのファイルハンドル(あるいはメンバとしてハンドルを含む構造体のアドレス)をこの値として指定しておき、コールバック関数内でこのハンドルが指すファイルを先頭から順に読み込んでいくようにすれば、ファイルのデータをリッチエディットコントロールに読み込ませることができます。ファイルへの保存まずはリッチエディットコントロールの内容をファイルに保存する方法からです。その手順は以下のようになります。コールバック関数のコードを変数に格納する。関数を呼び出して、書き込みアクセス指定でファイルをオープンする。関数のアドレスを構造体(事実上は配列変数)に格納する。メッセージを送信する。関数でファイルハンドルをクローズする。コールバック関数のマシン語コードを変数に格納します。コールバック関数)の形で定義されたものでなければなりません。サンプルコード)を筆者が準備したので、これを使用することにします。命令を使って確保しなければいけないということです。この命令は、次のファイルをダウンロードしてインクルードすることで使用できるようになります。関数を呼び出して、保存するファイルをオープン(新しく作成)しておきます。このときにファイルハンドルが返されますが、このファイルハンドルは情報としてコールバック関数に渡されることになります。メッセージを送信します。構造体は以下のように定義されています。メンバは、コールバック関数に渡される任意の32ビット値です。このメンバに指定された値が、必要な情報としてそのままコールバック関数に渡されることになります。メッセージ送信後にエラーコードが格納されます。メンバには、コールバック関数のアドレスを指定します。このメンバには、コールバック関数のマシン語コードを入れた変数のアドレスを指定しておきます。メンバに格納することができるわけですが、今回コールバック関数に渡したい情報には、まず、保存するためのファイルハンドルがありますね。渡さなければならない情報は実はこれだけではありません。いうのも、今回使用されるコールバック関数のマシン語コードには、コールバック関数の中で使用されているAPI関数アドレスの情報が含まれていないのです。API関数アドレスは、その関数を提供するDLLがメモリ上にロードされて初めて決定されるため、実行されるまではそのアドレスはわからないからです。したがって、API関数のアドレスの情報を、ファイルハンドルといっしょにコールバック関数に渡してやる必要があるのです。関数を呼び出しているので、この関数のアドレスを渡す必要があります。今回のように、コールバック関数に2つ以上の情報を渡すためには、それらの情報をすべて格納できるだけの構造体を定義して、その構造体に情報を格納し、構造体のアドレス1つだけをコールバック関数に渡す、という方法をとります。関数のアドレスの2つの情報を格納するために、以下のような構造体を新たに定義することにしました。関数のアドレスをそれぞれ格納します。