hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
MakeHPI/cpp/chapter5 - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

オブジェクトの削除に伴うデータリンクの削除

ここでは拡張プラグインを使ってオブジェクトに何らかのデータを関連付けた際に、clsやclrobjなど、オブジェクトの削除に伴って、リンクされたデータの削除方法を解説していきます。



  • スクリプトに
      1
    
     
    
        set_delmsg 0, "Good bye !"
    と書くとp1で指定したIDのオブジェクトが削除される際、p2で指定したメッセージをメッセージボックスに表示し、[ OK ]ボタンを押したあとは通常通りオブジェクトを削除するプラグインを作る。
  • HSPOBJINFO 構造体を使って、オブジェクトとデータ、両方の削除を同期する方法を学ぶ。

ソースファイル bcc551.png

+  step5Main.cpp
+  delmsg.h
+  delmsg.cpp
作成関数

今回新たに作った関数は以下の4つです。

  • set_delmsg
    オブジェクトのHSPOBJINFO構造体へのポインタと文字列へのポインタを受け取り、リストに登録する関数。
    該当するオブジェクトが既にリストに登録されている場合は、文字列を変更する。
  • find_delmsg
    リストを探索して指定されたオブジェクトに一致するセルへのポインタを返す関数。
    見つからない場合はNULLを返す。
  • put_delmsg
    オブジェクトが削除されようとした時にHSPから呼ばれる関数。
    与えられたHSPOBJINFO構造体へのポインタを元に、リストを探索し登録されている文字列を表示する。
    ユーザーが[OK]ボタンを押した後、該当セルをリストから削除し、既存の削除関数を呼び出してオブジェクトを削除する。
  • enum_delmsg
    リストに登録されている文字列を順次参照し、ファイルに書き出す関数。( おまけ )
データ管理

ヘッダを見てもらうと分かる通り、delmsgプラグインではデータの管理法に片方向リンクリスト( 以下、リスト )を使っています。

ここでのデータとはオブジェクトと対の表示する文字列になります。
オブジェクトと文字列を関連付けることは簡単ですがオブジェクトがプラグインの知らないところで削除されたのを放っておくと無駄なメモリを使い続けることになるので、オブジェクトの削除と同時にデータをメモリから解放させることが目的です。

リストの要素( セル )はオブジェクトのハンドルとメッセージを対で管理します。
このハンドルは削除関数の引数で渡される削除される、オブジェクトのHSPOBJINFO構造体との比較用のキーになります。
また、メッセージを表示しただけではオブジェクトは削除されないので既存の削除関数へのポインタを保持しておきます。
こうしておけば既存の削除関数の具体的な処理を知らなくても関数ポインタを通して関数を呼べば適切な処理をし、オブジェクトが削除されるはずです。( 断言しない理由はすぐ下 )

場合によっては既存の削除関数はHSPオリジナルの削除関数ではなく、他のプラグインの削除関数かも知れませんが、他のプラグインが独自の処理をした後でキチンと既存の削除関数を呼び出していれば問題はないと思います。

でももっとウィンドウとデータを一対一で管理する方法もありますがここでは詳しく説明しません。
簡単に説明すると1つのウィンドウには1つのウィンドウ作成データを持たせることができます。

  1
 
    SetWindowLong( hwnd, GWL_USERDATA, lpdata );

などとしてデータへのポインタをウィンドウに関連付けることができます。

ただ今回のプラグインもそうですがこのテの手法は複数のプラグインを同時に使った時に競合する恐れがあります。

オブジェクト削除関数へのポインタ

clsやclrobjなどオブジェクトを削除しようとした時、HSPはそのオブジェクトのHSPOBJINFO構造体のオブジェクト削除関数へのポインタfunc_deleteメンバを通して削除関数を呼び出し、オブジェクトを削除します。

func_deleteメンバはHSPOBJINFO構造体の中で次のように定義されています。

  1
 
    void    (*func_delete)( struct HSPOBJINFO * );

ドキュメントではプラグイン独自のコントロールを配置する際にHSPOBJINFO構造体を設定する、というような記述がありますがオブジェクトの配置後でもHSPOBJINFO構造体の内容を変更することが可能です。

delmsgプラグインではオブジェクトの削除に合わせて、リストから削除するオブジェクトに該当するセルも削除したいため、既存の削除関数をラップさせた独自の削除関数put_delmsgを定義しています。

独自に定義する削除関数の戻り値・仮引数は次のように関数ポインタの戻り値・仮引数の型に合わせなければなりません。

  1
  2
  3
  4
 
-
|
!
    void myDeleteFunction( HSPOBJINFO *objinf )
    {
        /* 具体的な処理 */
    }
HSPOBJINFO構造体へのポインタを取得

ソースを良く見てみると今回はHSPOBJINFO構造体を取得するgetobj関数を使っていません。
HSPOBJINFO構造体を取得し、set_delmsg関数にHSPOBJINFO構造体へのポインタと、テキストへのポインタを渡してリストにメッセージを登録する部分を抜粋すると・・・

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 
 
 
 
 
 
 
 
 
 
 
 
      // BMSCR 構造体を取得
      bm = (BMSCR *)getbmscr( active_window );
      
      // オブジェクトIDの範囲をチェック
      if (( id < 0 ) || ( bm->objmax <= id ))
        puterror( HSPERR_ILLEGAL_FUNCTION );
 
      objinf = bm->mem_obj;
 
      // オブジェクトとメッセージを関連付ける
      if( objinf[id].hCld != NULL )
        set_delmsg( &objinf[id], text );

としています。

getobj関数の場合はHSPOBJINFO構造体の内容をコピーしますが、HSPはオブジェクトの情報を必要としたときBMSCR構造体のHSPOBJINFO構造体へのポインタmem_objメンバの指す構造体配列を参照するので、そちらを書き換えなければなりません。

よってgetobj関数は使わずにBMSCR構造体へのポインタを取得し、ポインタを辿って目的のHSPOBJINFO構造体へのポインタをset_delmsg関数に渡しています。

サンプル

+  プラグインを使わないサンプル
+  プラグインを使ったサンプル

コメント

  • というわけで大筋だけ書いて一休み´ー` -- kz3 2006-03-09 (木) 12:30:20
  • 「既存の削除関数〜」のところで一言。delmsgプラグインではリストに該当オブジェクトが登録済みの場合は表示文字列の変更するだけで削除関数へのポインタは更新しません。ということはあっちで張替え、こっちで張替えを繰り返すとマズいです。 -- kz3 2006-03-09 (木) 13:18:58
  • リストからちゃんとテキストが削除されているかどうか・・・ということで出力関数追加しました( enum_delmsg )。report.txtというファイルにリストの先頭セルから順番にメッセージを書き出していきます。「再読込」などのあるエディタで確認してみてください。 -- kz3 2006-03-09 (木) 18:08:24
    URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

添付ファイル:
filestep5Main.cpp
226件 [詳細]
filemakefile
83件 [詳細]
filedelmsg.h
253件 [詳細]
filedelmsg.cpp
206件 [詳細]
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2007-04-08 (日) 02:31:05 (2436d)