普通のコンポーネントで【初期化】やってみた。[Delphi][Plugin]プロジェクトロ...>2014-12-21普通のコンポーネントで【初期化】やってみた。2014の21日目の記事です。Calendarですよ!もっと開発環境の話もぶっ込んでいきましょう!前フリ最近じゃ珍しい機能でも何でもないですが、DelphiのIDEと言えばやっぱりポトペタですよね。コンポーネントパレットから選んで、クリックで配置。そのコンポーネントを配置した際、毎回やることってありません?例えば、TEditやTMemoを置いた際に、TextやLinesを空にする、みたいな。TPanelを置いた際に、Captionを空にしたり、ShowCaptionをFalseにする、みたいな。コンポーネントの各プロパティの初期値って必ずしもよく使う状態にはなっていなくて、置く度に毎回「自分好みの初期化」をすることって、よくありますよね。今まではどうしていたかもちろん手で毎回入力してるという方がほとんどだと思いますが、この初期化問題を解消しようと思った場合、今まではカスタムコンポーネントを作っていました。これで置いた時からTextが空になるend;end.こうやってコンポーネントを自作すれば処理を追加し放題なので、もちろんプロパティの初期化もできます。初期化だけをしたい場合、新しくコンポーネントを作るというのは大げさですし、何よりこれを使用したソースを配布する場合、カスタムコンポーネントのソースも添付し、尚且つ利用者の環境にインストールしてもらわなければなりません。Initializerです。ハードルを上げて登場しておきながら、実はこのプラグイン、インストールしても何も起きません。自分でカスタマイズこのプラグインは、使用者がプログラミングをすることで初めて真価を発揮します。プラグインのソースを見てみると、IDE上でコンポーネントが作成された時に呼ばれる関数があり、この中に自由に処理を記述できるようになっています。そこでコンポーネントの初期化をするコードを書けば、新しくカスタムコンポーネントを作ることなく、好きな状態でコンポーネントを作成できるわけです。作成されるのはカスタムコンポーネントではなく元のコンポーネントなので、このプラグインが入っていない環境にソースを持って行ったとしても、プラグインが設定した値はオブジェクトインスペクタで指定した時と同様にdfm内に記録されるため、カスタムコンポーネントの時のデメリットも解消されています。実際に使ってみるまずはプラグインをダウンロードして下さい。ver.0.0.1をダウンロード中身を適当なフォルダに展開したら、DelphiのIDEからCompInitPkg.dpkをロードし、プロジェクトマネージャを見るとContainsの中にUMain.pasがあるので、ダブルクリック等で開いて下さい。するとユニットの下の方に以下のような定義が見つかると思います。}end;ここに初期化コードを記述すればいいわけですが、サンプルとしてユニットの上の方にコメントアウトされた処理があるので、最初はここからコピーすると分かりやすいと思います。Calendar用に以下のような記述をしてみます。endend;このように書き換えたら、プロジェクトマネージャのパッケージ名の上で右クリックし、インストールを選択します。試しに新規フォーム上でTMemoを配置してみるとこうなります。このようにpublishedなプロパティに対する処理であれば、実行時のように好きなコードを書くことができます。この例ではVCLコンポーネントのプロパティを設定しましたが、もちろんFireMonkeyでも可能です*1。本当はこのような設定用UIも途中まで作りかけてはいたんですが、値の設定部分が恐ろしく面倒だったので断念しました。直接コードで書けば1行で済むようなことが、汎用性を持たせたUIにするだけで数百行を要するような苦行に早変わりするんですよね...。コードで書いた方が柔軟性が高いと、いいところ特になかった。おまけこれを作る過程で懐かしの痛IDEプラグインにも近代化改修を施してみました。これに伴いXE以下の対応を切りましたが、代わりにXE5〜XE7で動作するようになったかもしれません。各バージョン毎のパッケージライブラリを用意するのが面倒だったので、オープンソース化します。動作テストはめんどくさいのでXE4のみで行いましたが、今のところ特に問題なく動いているようです。Library、超絶便利です。3分ハッキングで使用した関数フックは、フック先関数を使用せずに自前関数に飛ばすので、自前関数内でフック先関数を呼びたい場合は対応ができませんでした。フック先の先頭をジャンプ命令に書き換えてしまった関係上、正常動作しないからです。このライブラリはいわゆるトランポリンフックを行うので、先頭をジャンプ命令に書き換えてしまった関数でも、正しく呼び出すことができます。これができると何が便利かというと、任意の関数の前後に好きな処理を追加する、といったことが超簡単にできます。以下のコードは、TStringList.Addに処理時間の計測を後付けしています。Calendarの記事を参考にして下さい。InterceptRemove(@OrgTStringList_Add);end.これで普通にTStringList.Addを使っていれば、Stopwatchに総経過時間が、CallCountに呼び出し回数がそれぞれ入るようになります。おまけのおまけ全然関係ない上にあんまり需要無いかもですが、最近こんなの作ったのでついでに置いておきます。ver.0.0.1をダウンロードx86、x64両対応のPE情報表示ツールです。使ってる方には分かると思いますが、見た目からしてeXeScopeのパクインスパイアで、あれからリソース機能を全カットしてx64に対応した感じです。EXEのインポート関数やDLLのエクスポート関数の確認に使います。Editorという使いやすいツールがすでにあるのでまぁ非対応でいいかなと。そんな程度なので特筆すべきところは特にないですが、DLLのエクスポート転送や遅延ロードテーブルに対応してるのが売りと言えば売りです。同系のCUIツールだとだいたい見れるんだけど、GUI系の似たようなツールだと意外と見れないんですよね、この辺の情報。Initializer凄いですね!こう言うの欲しかったです!!ありがとうございます!!それで早速インストールさせてもらって、おーできたできた、と喜んでて、フォントサイズやフォント名変更したかったので変更した後に、一旦アンインストールしてインストールしたんですが・・・なぜだか反映しないのです。フォント名の指定がおかしいのか、と思い、Font.Name指定をコメントアウトしてもだめ。「コンポーネント>パッケージのインストール」には「ComponentInitializer」出ています。Windows7です。23:36どこでもいいんですが、initialization内などにShowMessage('hogehoge')のような文を追加して、インストール時にダイアログが表示されるか試してみて下さい。表示されないようであれば、編集したものとは別のソースコードがコンパイル&インストールされています。あるケースとしては、一度編集してdskファイルが生成されたプロジェクトをフォルダごとコピーして、そちらのプロジェクトを開くとコピー前のソースコードをIDE上にロードしてしまう(dskにはフルパスで開いていたファイル名が記録されているため)というのがあります。この場合はIDE上で開いているユニットを一度全て閉じたり、プロジェクトをロードする前にdskを削除すれば直ります。逆に言えば上記以外だと原因はちょっと分からないですね...すいません。