今回は、リッチエディットコントロールの内容をファイルに保存したり、ファイルを読み込んでコントロールに表示したりということをしてみます。できることならば、RTF形式のファイルの保存・読み込みができるとよいのですが、それらを行なうにはコールバック関数を準備する必要があるため、関数という概念を持たないHSPでは、拡張DLLなしでは実現することができません。そこで今回はRTFファイルではなくテキストファイルの保存・読み込みを行ってみましょう。
しかし、残念なことに、今回の方法では 64K バイト未満のテキストしか扱うことができません。あらかじめ了承しておいてください。
テキストファイルの内容をリッチエディットコントロールに開くには、 bload 命令でファイルの内容をすべて読み込んでから、 WM_SETTEXT メッセージを送信します。
#define WM_SETTEXT 0x000C WM_SETTEXT wParam = 0; lParam = pszText;
このメッセージは、ウィンドウに関連付けられたテキストを設定するためのメッセージです。タイトルバーを持つウィンドウに対してこのメッセージを送信すると、タイトルバーの文字列が指定されたものに置き換えられます。また、標準エディットコントロールやリッチエディットコントロールに対して送信すると、コントロールのテキストの内容すべてを指定されたテキストに置き換えます。
pszText パラメータには、設定するテキストのアドレスを指定します。リッチエディットコントロールに送信する場合に、ここにファイルの内容を読み込んだバッファのアドレスを指定すれば、コントロールのテキストが置きかわります。
sdim filename, 260 dialog "txt", 16 if stat == 0 : stop exist filename if strsize != -1 { ; ファイルをバッファに読み込む sdim buf, strsize + 1 bload filename, buf, filesize ; WM_SETTEXT メッセージ送信 pm = hEdit, 0x000C, 0 getptr pm.3, buf sendmsg pm }
リッチエディットコントロールの内容をファイルに保存するには、コントロール中のテキストすべてをバッファにコピーして、これを bsave 命令で保存するという手段をとります。
コントロール中のテキストを取得するには、まずコントロールに WM_GETTEXTLENGTH メッセージを送信して、コントロール中のテキストサイズを取得します。そして、そのサイズのテキストを格納できるだけのバッファを確保し、 WM_GETTEXT メッセージを送信してこのバッファにテキストをコピーします。
#define WM_GETTEXTLENGTH 0x000E WM_GETTEXTLENGTH wParam = 0; lParam = 0;
WM_GETTEXTLENGTH メッセージは、ウィンドウに関連付けられたテキストの長さを取得します。リッチエディットコントロールに送信すると、戻り値としてコントロール中のテキストの長さがバイト単位で返ります。
#define WM_GETTEXT 0x000D WM_GETTEXT wParam = cchTextMax; lParam = pszText;
WM_GETTEXT メッセージは、ウィンドウに関連付けられたテキストを取得します。
pszText には取得したテキストを格納するためのバッファのアドレスを、 cchTextMax にはそのバッファのサイズを指定します。リッチエディットコントロールに送信すると、コントロール中のテキストが取得されます。戻り値として、バッファにコピーされたテキストのサイズが返ります。
これによってコントロール中のテキストがバッファに格納されるので、これを bsave 命令を使ってファイルに保存します。
sdim filename, 260 dialog "txt", 17 if stat == 0 : stop ; WM_GETTEXTSIZEメッセージ送信 pm = hEdit, 0x000E, 0, 0 sendmsg pm filesize = stat ; コントロール中のテキストのサイズ sdim buf, filesize + 1 ; WM_GETTEXTメッセージ送信 pm = hEdit, 0x000D, filesize + 1 getptr pm.3, buf ; バッファのアドレス sendmsg pm ; バッファの内容をファイルに保存 bsave filename, buf, filesize
保存・読み込みの手順に関しては以上ですが、もう1つ、新規作成やファイルを開くときに、現在編集中の内容が変更されていた場合にそれを保存するかどうかをユーザーに尋ねるようにしたいですね。それを実現する方法を説明します。
標準エディットコントロールやリッチエディットコントロールは、変更フラグ(modification flag)という、内容が変更されたかどうかの状態を入れておく変数を内部に持っています。このようなフラグは一般にダーティーフラグ(dirty flag)とも呼ばれています。
最初はこのフラグはセットされていない( 0 に設定されている)状態なのですが、ユーザーによって内容が変更された瞬間に、このフラグがセットされた( 1 に設定された)状態になるようになっているのです。そこで、新規作成やファイルを開くときにこのフラグを取得して、このフラグがセットされていれば現在の内容を保存するかどうかの確認を取ればよいことになります。現在の変更フラグを取得するには、リッチエディットコントロールに EM_GETMODIFY メッセージを送信します。
#define EM_GETMODIFY 0x00B8 EM_GETMODIFY wParam = 0; lParam = 0;
EM_GETMODIFY メッセージを送信すると、戻り値として現在の変更フラグが返ります。この値が 0 ならば、リッチエディットコントロールのテキストが変更されていないことを示しています。そうでない場合は、内容が変更されたことを示しています。
さて、リッチエディット中のテキストを保存しただけでは、変更フラグはまだセットされたままなので、テキストを保存した後にフラグをクリアする( 0 に設定する)必要があります。これには EM_SETMODIFY メッセージを使います。
#define EM_SETMODIFY 0x00B9 EM_SETMODIFY wParam = fModified; lParam = 0;
fModified パラメータには、新しく設定するフラグを指定します。ここではフラグをクリアする必要があるので、 0 を指定します。
今回は新しく背景色の設定を行っています。背景色の設定は EM_SETBKGNDCOLOR メッセージを送信して行ないます。
#define EM_SETBKGNDCOLOR 0x0443 EM_SETBKGNDCOLOR wParam = fUseSysColor; lParam = clr;
fUseSysColor パラメータには背景色にシステムカラーを使うかどうかを示すフラグ指定します。 0 以外の値を指定した場合は、背景色としてシステムカラーのウィンドウ背景色(GetSysColor 関数で引数に 5 (COLOR_WINDOW) を指定して得られる色)が設定されます。 fUseSysColor パラメータに 0 を指定した場合は、 clr パラメータで指定された色になります。このパラメータには背景色を表すRGB値を指定します。
それでは、スクリプトを書いてみましょう。
今回はモジュールを定義しています。リッチエディットコントロールの作成および、各メッセージの送信をモジュール命令で定義しました。戻り値を持つものは stat に格納されるようになっています。
#include "llmod.as" #module ;#### リッチエディットコントロール作成モジュール ######## ;=============================================================== ; リッチエディットコントロールの作成 ; CreateRichEdit n1, n2, n3, n4 ; n1 : x座標 ; n2 : y座標 ; n3 : 幅 ; n4 : 高さ ; stat : リッチエディットコントロールのハンドルが返る ;=============================================================== #deffunc CreateRichEdit int, int, int, int mref cx, 0 ; x位置 mref cy, 1 ; y位置 mref sx, 2 ; 幅 mref sy, 3 ; 高さ mref bmscr, 67 ; 描画中ウィンドウのBMSCR構造体 mref stt, 64 ; stat ; RICHEDIT.DLLのロード ll_libload@ hdllRichEd, "RICHED32.DLL" ; リッチエディットコントロールの作成 classname = "RichEdit" pm.0 = 0 getptr pm.1, classname pm.2 = 0 pm.3 = 0x50B020C4 ; WS_CHILD | WS_VISIBLE | WS_BORDER ; | WS_VSCROLL | WS_HSCROLL ; | ES_MULTILINE | ES_AUTOVSCROLL ; | ES_AUTOHSCROLL | ES_DISABLENOSCROLL pm.4 = cx, cy, sx, sy pm.8 = bmscr.13 ; 描画中HSPウィンドウのハンドル pm.9 = 0xFF00 ; コントロールID (大きめに指定) _get_instance pm.10 ; インスタンスハンドル取得 pm.11 = 0 dllproc "CreateWindowExA", pm, 12, D_USER@ hEdit = stat ; リッチエディットのハンドル ; テキストサイズの上限の設定 ; EM_EXLIMITTEXT メッセージ送信 pm = hEdit, 0x0435, 0, 0 ; 64Kバイトに設定 sendmsg pm stt = hEdit return ;=============================================================== ; フォント("FixedSys", 白)・背景色(黒)を設定 ; SetDefaultFormat n1 ; n1 : リッチエディットコントロールのハンドル ;=============================================================== #deffunc SetDefaultFormat int mref hEdit, 0 ; リッチエディットコントロールのハンドル ; CHARFORMAT 構造体 dim charfmt, 16 charfmt.0 = 60 ; 構造体サイズ charfmt.1 = 0x60000000 ; CFM_FACE | CFM_COLOR charfmt.5 = 0x00FFFFFF ; 文字色(白に設定) poke charfmt, 26, "FixedSys" ;フォント名"FixedSys" ; EM_SETCHARFORMAT メッセージ送信 pm = hEdit, 0x0444 pm.2 = 0x0000 ; SCF_DEFAULT getptr pm.3, charfmt ; CHARFORMAT 構造体のアドレス sendmsg pm ; EM_SETBKGNDCOLOR メッセージ送信 pm = hEdit, 0x0443, 0, 0 ; 背景色を黒に sendmsg pm return ;=============================================================== ; WM_SETTEXT メッセージの送信 ; SetText n1, v2 ; n1 : リッチエディットコントロールのハンドル ; v2 : テキストを格納した文字列型変数 ;=============================================================== #deffunc SetText int, val mref hEdit, 0 ; リッチエディットコントロールのハンドル mref textbuf, 25 ; テキストを格納した変数 ; WM_SETTEXT メッセージ送信 pm = hEdit, 0x000C, 0 getptr pm.3, textbuf sendmsg pm return ;=============================================================== ; WM_GETTEXTLENGTH メッセージの送信 ; GetTextLen n1 ; n1 : リッチエディットコントロールのハンドル ;=============================================================== #deffunc GetTextLen int mref hEdit, 0 ; リッチエディットコントロールのハンドル ; WM_GETTEXTLENGTH メッセージ送信 pm = hEdit, 0x000E, 0, 0 sendmsg pm return ;=============================================================== ; WM_GETTEXT メッセージの送信 ; GetText n1, v2, n3 ; n1 : リッチエディットコントロールのハンドル ; v2 : テキストを格納するための文字列型変数 ; n3 : 変数 v2 のサイズ ;=============================================================== #deffunc GetText int, val, int mref hEdit, 0 ; リッチエディットコントロールのハンドル mref textbuf, 25 ; テキストを受け取るバッファ mref maxsize, 2 ; バッファサイズ ; WM_GETTEXT メッセージ送信 pm = hEdit, 0x000D, maxsize getptr pm.3, textbuf sendmsg pm return ;=============================================================== ; EM_GETMODIFY メッセージの送信 ; GetModify n1 ; n1 : リッチエディットコントロールのハンドル ;=============================================================== #deffunc GetModify int mref hEdit, 0 ; リッチエディットコントロールのハンドル ; EM_GETMODIFY メッセージ送信 pm = hEdit, 0x00B8, 0, 0 sendmsg pm return ;=============================================================== ; EM_SETMODIFY メッセージの送信 ; SetModify n1, n2 ; n1 : リッチエディットコントロールのハンドル ; n2 : 変更フラグの設定値 ;=============================================================== #deffunc SetModify int, int mref hEdit, 0 ; リッチエディットコントロールのハンドル mref mode, 1 ; 変更フラグの設定値 ; EM_SETMODIFY メッセージ送信 pm = hEdit, 0x00B9, mode, 0 sendmsg pm return #global ;############# モジュール終わり ######################## objsize winx/4, 24 pos 0, 0 : button "New", *lb_push ; Object ID = 0 pos winx/4, 0 : button "Open", *lb_push ; Object ID = 1 pos winx/2, 0 : button "Save", *lb_push ; Object ID = 2 pos winx*3/4, 0 : button "SaveAs", *lb_push ; Object ID = 3 ; リッチエディットコントロールの作成 CreateRichEdit 0, 24, winx, winy-24 hEdit = stat ; フォント・背景色設定 SetDefaultFormat hEdit sdim filename, 260 ; ファイル名を格納する変数 title "(無題)" stop *lb_push ; ボタンが押された場合(statはボタンのオブジェクトID) if stat == 0 : gosub *lb_new : stop if stat == 1 : gosub *lb_open : stop if stat == 2 : gosub *lb_save : stop if stat == 3 : gosub *lb_saveas : stop stop *lb_new GetModify hEdit ; 内容が変更されているかどうか調べる if stat { dialog "内容が変更されています。保存しますか", 2 if stat == 6 : gosub *lb_save } buf = "" ; 空文字列を設定 SetText hEdit, buf title "(無題)" SetDefaultFormat hEdit ; デフォルトフォント・背景色設定 SetModify hEdit, 0 ; 変更フラグをクリアする filename = "" return *lb_open GetModify hEdit ; 内容が変更されているかどうか調べる if stat { dialog "内容が変更されています。保存しますか", 2 if stat == 6 : gosub *lb_save } dialog "txt", 16 if stat == 0 : return ; キャンセルされた場合はリターン filename = refstr exist filename if strsize == -1 : return len = strsize ; ファイルサイズ sdim buf, len+1 ; 必要なバッファを確保 ; テキストサイズ+1 (終端ヌル文字を考慮) bload filename, buf, len ; いったんバッファに読み込む SetDefaultFormat hEdit ; デフォルトフォント・背景色設定 SetText hEdit, buf ; テキストをセット title filename ; タイトルバーをファイル名に SetModify hEdit, 0 ; 変更フラグをクリアする return *lb_save if filename == "" { gosub *lb_saveas } else { gosub *lb_filesave } return *lb_saveas dialog "txt", 17 if stat == 0 : return ; キャンセルされた場合はリターン filename = refstr gosub *lb_filesave return *lb_filesave GetTextLen hEdit ; テキストサイズ取得 len = stat sdim buf, len+1 ; 必要なバッファを確保 ; テキストサイズ+1 (終端ヌル文字を考慮) GetText hEdit, buf, len+1 ; バッファにテキストを格納する bsave filename, buf, len title filename ; タイトルバーをファイル名に SetModify hEdit, 0 ; 変更フラグをクリアする return