2008年12月16日火曜日

はっちゅう君プラスのAddInFormの使い方

昨日のだと、昨日も今日の午前も怒られなかったのに、午後になって急にWeifenLuo.WinFormsUI.Dockingが怒り出した。MDIにドッキングする前にドッキング状態をいじったらいけないとかそんな感じらしい。

改めてAddInFormに関する一番基本事項(しかしろくにドキュメント化されていない)の覚書き。これらを実行すると
  • フロート状態のウィンドウのサイズがちゃんと復元される。
  • フロート状態のウィンドウははっちゅう君プラスにつられて最小化されたりせず独立している
  • フロート状態のウィンドウは何も設定していないとはっちゅう君が最小化していても上下左右へのドッキングアイコンが現れてうざいのだがそれが出なくなる
というご利益がある。

結局

public class MimohutaForm : AddInForm
{
#region メソッド
private void decideAllowEndUserDocking()
{
if (ClickSec.Trading.Core.Main.ApplicationHost.Instance == null) {
this.AllowEndUserDocking = false;
} else {
if (ClickSec.Trading.Core.Main.ApplicationHost.Instance.Workbench.WindowState
== System.Windows.Forms.FormWindowState.Minimized) {
this.AllowEndUserDocking = false;
} else {
this.AllowEndUserDocking = true;
}
}
}
private void setIndependentWindow()
{
decideAllowEndUserDocking();
this.TopMost = true;
this.TopLevel = true;
this.ShowInTaskbar = true;
}
private void setDependentWindow()
{
decideAllowEndUserDocking();
this.TopMost = false;
this.TopLevel = false;
this.ShowInTaskbar = false;
}
#endregion

#region カスタムしたメソッド
protected override void OnDockStateChanged(EventArgs e)
{
if (this.DockState == DockState.Float) {
setIndependentWindow();
} else {
setDependentWindow();
}
base.OnDockStateChanged(e);
}
protected override void OnSizeChanged(EventArgs e)
{
if (this.DockState == DockState.Float) {
this.ClientSize = this.ClientSize;
}
base.OnSizeChanged(e);
}
protected override void OnLoad(EventArgs e)
{
if (ClickSec.Trading.Core.Main.ApplicationHost.Instance == null) {
setIndependentWindow();
} else {
if (this.DockState == DockState.Float) {
setIndependentWindow();
} else {
setDependentWindow();
}
ClickSec.Trading.Core.Main.ApplicationHost.Instance.Workbench.Resize += delegate {
decideAllowEndUserDocking();
};
}
base.OnLoad(e);
}
#endregion
}

こんな感じにAddInFormを拡張して、例えばMimohutaMainクラスのインナークラスとして定義、コンストラクタでmimohutaFormとして生成し、パブリックなFormプロパティから参照できるようにしてビルダークラスはサンプルどおりに

class MimohutaBuilder : IAddInFormBuilder
{
public IAddInForm AddInForm
{
get
{
return (new MimohutaMain()).Form;
}
}
public string Value { get; set; }
public void Dispose() { }
}

としてやるべきらしい。ビルダークラスにおいてFormを返す前に勝手にShow()などをしてはいけないみたい。

なお、上の例でClickSec.Trading.Core.Main.ApplicationHost.Instanceの実体があるかどうかをチェックしているのかは私のアドインはデバッグの利便性のためにスタンドアロンでも動けるようにしているから。ただのアドインでよければ削れる。

さて、その上で.Addinファイルの中で<AddIn>要素の中に

<Path name="/AddIn/Forms">
<Form id="Tomorrowplusplus.Mimohuta.MimohutaMain+MimohutaForm"
builder="Tomorrowplusplus.Mimohuta.MimohutaBuilder" />
</Path>

とフォームの型のフルネームとビルダークラスを紐付けする。これではっちゅう君プラス起動時にフォームが復元される。

それから、AddInFormの拡張でGetPersistStringを拡張したければ

protected override string GetPersistString()
{
return base.GetPersistString() + "," + ほにゃらら.ToString();
}

みたいにすると、ビルダークラスのAddInFormのget時にはValueプロパティに","以降の文字列が入っているのでにゃんにゃんすればフォーム毎の設定の保存・復元ができる。

以上。これでフロート状態では独立して振舞うなど、フロート注文ウィンドウと同じような動作になるし、フロート状態でサイズが復元されない問題も対処できる。

あと、本日前場の動画をまた作ってしまった。貼り付ける必要はないだろう。サイドバーのリストから見てね。ニコニコ動画ならmp4で綺麗。youtubeなら&fmt=18オプションを付けると綺麗になる。

ペイパル

手数料の事があるので、Paypalは第二の銀行口座のつもりでお金をためておいてまとまった額を必要に応じて引き出すつもりではあるのだが、一応私という個人にとってはPaypalはどこの馬の骨とも知れない企業で、そこにお金を預けているわけだから、Paypalからお金を返してもらえるという事は確認しておかないといけない。そういうわけで銀行口座への振替処理を行った。

で、来たメールの最後に律儀に「敬具」って書いてあって吹いた。外国企業が日本に上陸する時って苦労するんだなあ。

はっちゅう君プラスのアドインフォームのまとめ

この内容は後で修正しました。このエントリを参照してください。
はっちゅう君プラスのアドインを作るさいにドキュメントに書いてあるように素直にAddInFormを使うと色々問題が生じる。

もろもろの問題を解決するためには(using WeifenLuo.WinFormsUI.Docking;した上で)
public class MimohutaForm : AddInForm
{
public MimohutaForm()
{
if (this.DockState == DockState.Float) {
setIndependentWindow();
} else {
setDependentWindow();
}
ClickSec.Trading.Core.Main.ApplicationHost.Instance.Workbench.Resize += delegate {
decideAllowEndUserDocking();
};
}
private void decideAllowEndUserDocking()
{
if (ClickSec.Trading.Core.Main.ApplicationHost.Instance.Workbench.WindowState
== System.Windows.Forms.FormWindowState.Minimized) {
this.AllowEndUserDocking = false;
} else {
this.AllowEndUserDocking = true;
}
}
private void setIndependentWindow()
{
decideAllowEndUserDocking();
this.TopMost = true;
this.TopLevel = true;
}
private void setDependentWindow()
{
decideAllowEndUserDocking();
this.TopMost = false;
this.TopLevel = false;
}

protected override void OnDockStateChanged(EventArgs e)
{
if (this.DockState == DockState.Float) {
setIndependentWindow();
} else {
setDependentWindow();
}
base.OnDockStateChanged(e);
}
protected override void OnSizeChanged(EventArgs e)
{
this.ClientSize = this.ClientSize;
base.OnSizeChanged(e);
}
}
と拡張して使う。どの道フォームの自動復元をするためにはAddInFormを拡張したクラスを作ってその名前を指定しなければならないんだからついでにいつも上のようにすれば良いだろう。


それで、初期化時に、TopMostやTopLevelの設定が確実に行われるようにフォームビルダーは
class MimohutaBuilder : IAddInFormBuilder
{
public IAddInForm AddInForm
{
get
{
MimohutaMain mimohutaMain= new MimohutaMain();
mimohutaMain.Form.Show();
mimohutaMain.Form.DockState = mimohutaMain.Form.DockState;
return mimohutaMain.Form;
}
}
public string Value { get; set; }
public void Dispose() { }
}
}
とする。ただしここでは、MimohutaMainクラスのインナークラスとしてMimohutaFormクラスが定義されていて、MimohutaMainクラスのコンストラクタでMimohutaFormのプライベートなインスタンスが作られ、それがパブリックなFormから読み取れるようになっているのでこういう実装になっている。実際にはケースバイケースだろう。


これらの方針に従うと、

  • フロート状態のウィンドウのサイズがちゃんと復元される。

  • フロート状態のウィンドウははっちゅう君プラスにつられて最小化されたりせず独立している

  • フロート状態のウィンドウは何も設定していないとはっちゅう君が最小化
    していても上下左右へのドッキングアイコンが現れてうざいのだがそれが出なくなる


などのご利益がある。

ついでに、AddinFormを継承したクラスで
protected override string GetPersistString()
{
return base.GetPersistString() + "," + isFakeDataEnabled.ToString();
}
とデフォルトの永続化文字列に","に続けて文字列を連結して永続化文字列として返すと
上記フォームビルダーのValueプロパティにセットされた上でAddInForm.getが呼び出される。
これでフォーム毎の設定の保存、復元ができる。こういった部分が中途半端にしかドキュメント
化されていないのでReflectorでにらめっこしながら四苦八苦しなくてはならなくて大変だった。

ついでだからこのフォームビルダーの仕組みもメモしておく。
.addinファイルの<AddIn>要素の中に
<Path name="/AddIn/Forms">
<Form id="Tomorrowplusplus.Mimohuta.MimohutaMain+MimohutaForm"
builder="Tomorrowplusplus.Mimohuta.MimohutaBuilder" />
</Path>
と、上で例にしたようなAddinFormを拡張したクラスのフルネームとビルダークラスのフルネームを登録する。なお、私はAddinFormを継承したクラスを作成するのはこのようなビルダークラスと一意に紐付けするためだけの形式な物に思えたのでインナークラスとして定義してしまった。この場合"."ではなく"+"で外クラス名に繋ぐ。でも、上で書いたくらいに大幅に実装の拡張をするならば、インナークラスにするというのは正しい選択ではないかもしれない。そのうち修正しよう。

でも、いずれにせよ、本当に一段落したという感じだなあ。しばらくは細かい調整のみ。

再開したらまずやるのは注文リストを定期的に監視して新規建て注文約定-返済注文それぞれの時刻と値を調べてトレードの様子と損益を視覚化する事だろう。このようにこちらから連続して情報を身に行く方法以外に約定を知る方法はないみたい。休んでいる間に約定通知の方法が出来上がればいいな。

今日の後場の動画



だんだん、自分の「身も蓋もない」への認識が、ただのビジュアライゼーションツールになってきた。
あんまりこういう撮影を繰り返すのも不毛だけど、歴史的暴落みたいなのを一度でも通日で記録できたらいいな。

で、なぜかYoutubeではmp4動画がサムネイル生成までは行くんだけどその後処理中でずっとそのまま。面倒は嫌なのでニコニコ動画とYoutubeで同じ動画ファイルをアップロードするようにしたいんだけどなあ。まあflvを作るのもmp4を作るのもこれくらいの時間なら対してかからないんだけど。

追記:
一晩で見れるようになりました。一度flvを作ってアップロードしたけれどmp4版に変更。
まあYoutubeではどのみち再エンコされるので、私の方でニコニコ動画とyoutubeでアップロードするファイルを共通にできるという利便性が確保されてだけです。

寄付

「身も蓋もない」にY様から寄付があった。健康上の問題という自分に責任のない嫌がらせのような理由で人生ドロップアウト気味なので収入と言える物が一応自分の力で少しでも得られたという事実が泣きたくなるほど嬉しい。そういう事情もあってサイトには身も蓋もないの開発資金に使うことは保証されないと注意書きしておいたけど、やっぱり出来る限り開発に還元する方向で有効に活用させて頂きます。

後場の記録

今日はただひたすら後場のティック・四本値表示の様子を記録してみました。mp4にしてみたので無駄に高画質です。
Youtubeの方がいつまでたっても処理中なので(別形式でアップしなおした方が良いのかもしれない)とりあえずサイドバーのニコニコ動画リストからご覧下さい。

タスクスイッチャ

と思ったらタスクスイッチャに出てこない以上TopMostにしないとやってられん事が分かった。