最近の記事
- 9/1 - 将棋始めました
- 5/16 - サーバー引っ越し
- 4/24 - 優先順位
- 3/17 - vbNullString と 空文字列 ""
- 3/15 - InputBox 関数の戻り値
- 3/13 - 紙と Excel と VBA
- 3/9 - 未だに Visual Basic 6
- 11/14 - ぼて閉鎖
- 11/9 - 関数オブジェクトの呼び出し
- 9/7 - メソッドとしての関数オブジェクト
Entering Passive Mode
次のステップに進むか。
現状のホストには大きな制限がある。
それはリソースの問題だ。
スクリーンセーバーの名前とアイコンは、
ホストに Windows のリソースとして埋め込まれる。
これらは、プラグインで置き換えることはできない。
これにより生じる制約は以下の 2 つ。
・表示するスクリーンセーバーの名前を変えられない
・スクリーンセーバーのアイコンを変えられない。
音楽 CD の寿命ってどんなもんなんだろ。
今日、お気に入りの CD の 2 曲目で音飛びが発生。
傷やほこりが原因で、針が同じ場所に戻される
昔のレコード版のような現象。
それも 5 秒おきくらいに 3 箇所で同時に。
音飛びの原因と言えば、以下の 2 種類であることが多い。
1 つはレーベル側の傷による記録層の損傷、
1 つは読み取り側にある樹脂の傷による反射性能低下。
描画コードとの連携も完成したので、
ちゃんと動作するかテストしてみる。
実行してみると、画面の中央に、
「Hello World!」と表示されたことが確認できた。
……これだけだと短すぎるので、もう少し書くか。
このスクリーンセーバーの実行は
C++ ネイティブアプリと違い、起動に多少時間がかかる。
突如現れた delete 構文。
この delete の意味するのは何なんだろうか。
まず、昨日のコードから、大事な部分を引用していこう。
Graphics ^g = Graphics::FromHdc(...);
try {
...
} finally {
delete g;
}
Create/Destroy の準備ができたので、
本題となる Dispatcher::Paint の実装を行う。
void Dispatcher::Paint(HWND hwnd) {
// 描画開始
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
try {
GCHandle::Alloc でハンドルに ID を割り当てると、
数値として取り扱えるようになるので便利だが、
不要になった時にはちゃんと解放しなければならない。
これを怠ると、ハンドルへの参照が残ってしまうので、
オブジェクトがガベッジコレクションされなくなり、
メモリリークを引き起こす要因となる。
GCHandle::Alloc で参照したハンドルを解放するためには、
どこかで GCHandle::Free を呼ぶ必要がある。
GCHandle を使って割り当てた ID はただの数値なので、
利用するときにはハンドルに戻さなければならない。
ID からハンドルに戻すのは、
ハンドルから ID に変換した時と逆の手順を踏めば良い。
// ウィンドウのユーザデータから ID を取得
LONG_PTR value = GetWindowLongPtr(hwnd, GWLP_USERDATA);
void *pointer = reinterpret_cast<void *>(value);
ハンドル型の値は演算も変換もできないため、
そのままではスコープを超えて、
オブジェクトを保持することが困難である。
グローバル領域に変数を確保し、
ハンドル型の値を保持する手はあるが、
変数の可視性を高めてしまうのは、
保守性に劣り、見通しも悪くなるのでやりたくない。
ではどうすれば良いか。
次に作るのは、描画コードの呼び出しだ。
Configure メソッドを作成した際は、
「HelloSaver saver;」という形で変数を宣言した。
この場合、saver 変数のスコープは、
Configure メソッドの内部なので、
メソッドから戻る直前に変数がスコープから外れ、
自動的にデストラクタが呼び出されて解放される。
でも、描画コードの呼び出し部分の実装は、
Configure のような単発の呼び出しではなく、
Create => Paint => Destroy の流れとなる。
まだ Configure メソッドしか作っていないが、
設定画面を表示させるコードは完成した。
描画用のコードを書いてないので、
スクリーンセーバーの実行テストはできないが、
とりあえず設定画面が表示されるか確認してみたい。
まずは、Dispatcher.cpp をコンパイルしておく。
$ cl /c /W4 /clr /FoDispatcher.obj Dispatcher.cpp
エラーがなければリンクする。