DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(3)

これまでの経緯
DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(1)
DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(2)

去年やってたoptclによるDataGridView埋め込みが、ようやく役に立つときが来た。
しかし、イベントを追加しようとしたところ、いきなり壁にぶち当たってしまった。

新たに定義したイベントにコールバックを登録できない。

やろうとしたことは、DataGridView.CellValueChangedイベントが起こったときにTclの関数に列、行とともにセルのテキストを渡してもらおうということだった。

public delegate void CellValueChangedDelegate(int col, int row, string val);
public event CellValueChangedDelegate CellValueChanged;
proc CellValueChanged {obj col row val} {
  puts "$col,$row,$val"
}
optcl::bind $dgvObj CellValueChanged CellValueChanged

だけど、なにも呼ばれない。ためしにC#側でデリゲートが登録されたかをチェックしてみたが、nullのままだった。

第4引数valはC#側では第3引数になるわけだけど、valはstringで、それがいけなかったのだろうか?

それとも引数は2つまでしか渡せないとか?optclのドキュメントではTcl側の関数の最初の引数はoptclのオブジェクトで、以降は関数の引数と書いてあるだけで、2個までとは書いてない。

よく分からないが、結局最後の引数をなくし、場所だけ教えてもらって値は自分でとりに行くことにしたらすんなりできた。

public delegate void CellValueChangedDelegate(int col, int row);
public event CellValueChangedDelegate CellValueChanged;
proc CellValueChanged {obj col row} {
  set s [$obj GetCell $col $row]
  puts "$col,$row,[dec $s]"
}
optcl::bind $dgvObj CellValueChanged CellValueChanged

コントロールのイベントは基本的に2つしか引数を持たないので、そういうことになってるんだろうか。

delegate void SomeDelegate(object sender, EventArgs e);

しかし、EventArgsはオブジェクトだから拡張して複数の属性を入れられるけど、Tclに構造を持った引数を渡すことはできるのだろうか?

構造体?optclオブジェクト?まだまだ奥が深いな。

追記

これまた、なぜかは分からないけど、3つ変数でもできるようになった。たぶん、Tcl側が認識していたアセンブリが古いものだったのかもしれない。それについてはまた書きたいと思います。

コメントを残す