[DFって何?][日記][コマンド一覧][関連リンク][予定表][他のファイラー][逃げ帰る]
ヘルプに次の記述を追加。
アプリケーションキーでコンテキストメニューを出すつもりがShift+アプリケーションキーになっていたのを修正。
さらにキーワードを追加。いつ終わるのだ。
まだまだキーワードを追加。重複しているキーワードをいくつか減らした。UNCとかまだ重複しているのはあるけど分散するためのいい見出しが思いつかなかったり。
ワイルドカード対応、ファイル名判定ルーチン、IsMatch()がバグってた。
前者は手抜きが原因。
後者は、*の次のaを探す時点で
とりあえず、次の文字から検索を再開させることにした。
この手の文字列検索はもっと高速なアルゴリズムがあるので随時書き換えておきたい。
*が2つ以上あった時にはまだ誤動作するハズ。
Web上の仕様書のほうも9801になっていたので初期値を9801に変更。
INIファイルから読み込んだ値を使っていなかったバグを修正。
とりあえず、正式版に向けて処理性能を上げるためのチューニング。
キーボードドロップ時の爆撃目標としてリストに表示するウィンドウの条件から「親がいないこと」という条件を外す。
原則的にタスクバーに表示するアルゴリズムに似たものを採用していたのだけど、タスクバーとAlt+Tabでは表示されるものが違うということに今まで気付かなかった。
道理でFIVAPMが表示されることがまれにあったわけだ。Windows 98からかな。Windows 95の時にはコントロールパネルのアプレットダイアログがAlt+Tabの一覧に出てこなくて不便だったのが改善されていたし。
ついでに「表示中」という条件も外す。タスクバーに隠しているBecky!のウィンドウに落とせなくて不便なことがあるので。
チューンしたときにうっかり間違えた。
情けなや。
この手のデバッグにWATCOMデバッガを使おうとするとものすごく面倒。なんでローカル変数のシンボル情報が無くなってしまうのだろう。
チューンしたときにうっかり間違えた。
情けなや。
なぜかソートしてなかった。ソートした方が見やすいじゃん。
…もしかしたら何か見落としてる?
ソートするとマズい理由があったのかも。
リストボックスにソートオプションをつけるとインクリメンタルサーチが使えることが解った。
なので、ソートオプションを付けておく。
ソートオプションを付けても表示はソートしていないので問題ない。
ビットマップビューアにバグ発見。16bpp(65536色)のビットマップを正しく表示しない。以前にほぼ同じ現象が出てViXで作った16bppなビットマップは正しく表示できたのだけど。
BMPフォーマットをいまいち理解しきれていないのが敗因だと思う。割と単純なのでついつい解ったつもりになってしまうのだけど。
なんで開発環境が構築できない状態のときにバグを見つけてしまうのだろう。
誰か、部屋を片づけてくれ〜。
せっかくだからVisual C++4.2でデバッグ開始。今からでもユーザ登録したらアップグレードかけられるんだろうか。試しに登録してみようか。
生成コードに不満が有るのでVisual C++4.2でコンパイルしたものはあまり公開したくないのだけど。
とりあえず、FIVAの16bpp壁紙とViXで作った16bppなビットマップを見比べる。6ドットほどズレて表示されているので、ピクセルフォーマット分ずれているようだ。
最初は16bppにピクセルフォーマットがあることを忘れて、逆方向に6ドットズレていたのを、匿名熱望さんの協力もあって原因が解って修正した。しかし、こういうことになるとは。
BITMAPFILEHEADERのbfOffBitsをみる。ViXで作ったものは66。これはBITMAPFILEHEADERのサイズ14バイト、BITMAPINFOHEADERのサイズ40バイトとピクセルフォーマットの12バイトを合計したものに等しい。シナリオ通りだ。
FIVAの壁紙はどうかというと54。やはり12足りない。ということはピクセルフォーマットが存在しないということか。
BITMAPINFOHEADERのあとに有るはずのピクセルフォーマットを見る。ViXで作ったものはソレらしいビットパターンが記録されている。しかしFIVAの壁紙には断続したビットが記録されている。これではピクセルフォーマットとしては使えない。
さて、これをどこかで区別しないとピクセルフォーマット分ズレてしまうわけだ。
どこで違いを見分ければいいのか…。BITMAPFILEHEADERとBITMAPINFOHEADERを見ながら考える。
このbiCompression、16bppの時にはBI_BITFIELDSでなければならない。ハズだ。
と思っていたが、BITMAPINFOの解説を誤読したためらしい。突然、
BITMAPCOREHEADER構造体のbcBitCountメンバは、 ビットマップ内の各ピクセルを定義するビット数と、 最大の色数を決めるものです。このメンバは、 次の値のいずれかになります。
(略)
- 1
- ビットマップはモノクロです。(略)
- 4
- ビットマップの色は最大で16色です。(略)
- 8
- ビットマップの色は最大で256色です。(略)
- 16
- ビットマップの色は最大で2^16色です。BITMAPINFOHEADERのbiCompressionメンバは、 BI_BITFIELDSでなければなりません。
(略)
なんていう解説が出てくるのだけど、BITMAPINFO構造体にはBITMAPCOREHEADER構造体は登場しない。良く似た感じのBITMAPINFOHEADERがメンバに有るので、BITMAPINFOHEADER構造体のbiBitCountについて記述したものだと思いこんでいた。
なぜならBITMAPCOREINFOHEADERの解説には、
とあるので、bcBitCountが16になることはあり得ない。
このことから
と解釈していた。実は全く関係なかったらしい。がーん。
つまり、16bppのビットマップにピクセルフォーマットが登録されているとは限らなくてあくまでbiCompressionがBI_BITFIELDSの時にのみピクセルフォーマットが登録されているということらしい。うーむ。
MSDN Onlineにはしっかり書いてある。日本語版のばかーッ!
サイズ縮小。
削除時のメッセージを「[ファイル|ディレクトリ]○○○を削除しますか?」に変更。
5分後に元に戻す。複数選択したときに意味がない。うーん。
以前から、コマンドラインにディレクトリを指定するとそこをカレントディレクトリとして起動するという隠し機能があった。
これを指定して起動すると、先にカレントディレクトリを切り替えてから設定ファイルを読みに行くため、キー定義ファイルをフルパスで指定していないと残念な思いをする。
というわけで、設定ファイルを読み込んでからディレクトリを変更するように順序を入れ換える。
ただし、もともとキー定義ファイルをフルパスで指定しないとカレントディレクトリからの相対指定で読み込むためD:\BIN\DF.EXEをC:\windowsから起動すると、C:\windowsからの相対指定で読み込もうとするため残念な思いをすることには変わりはない。
コンボボックスの動作について指摘された不具合を修正する。
SDKのリファレンスを見るかぎりでは、どうもオープン中のコンボボックスからフォーカスを失った場合はキャンセル扱いらしいのだが、Wordは値を変更する動作をしている。
見た感じ、キャンセル扱いにすると違和感がある。
設定ファイルを読み込むタイミングを切り替えたところ、設定ファイルのオプション設定を読み込めないというバグが発生。
スタックを4バイト節約しようとしていたのが敗因。オプションを読み込んだ変数を後からコマンドラインの解釈時に破壊していた。
ファイルのコピーや移動を中断できるようにした。ただし、一つのファイルを処理している間は中断できない。
ファイルサイズ 88,576バイト。
画像のロード、デコードを行うスレッドの優先順位を下げた。
コピー中でも一部の操作を受け付けるようにした。
ファイルサイズ 89,088バイト。
失敗。
ShellExecute()からShellExecuteEx()に変更。これでShellExecute()を呼び出す部分がなくなった。インポートテーブルが小さくなることを期待する。
DFのコピーを改造しようとして悩む。DOS形式のファイル名がネックだ。
ソースを読んで、どう修正するか悩んでいるうちにマズいところを見つけてしまい悩む。検索状態からLFNに対応していないNetWareサーバなどにコピーしようとするとハマる可能性がっ。
検索モードに入ったとき、8.3形式のサブディレクトリ名までは保持していない(情報ウィンドウにもファイル名しか表示していない)ため、コピー先を生成するときにディレクトリまで作れない。
コピー元は、8.3形式だろうがLFNだろうがとにかくその名前でアクセスできるので問題ない。
やりたいことは、サブディレクトリに分散しているファイルを、同じディレクトリにコピーしたいというだけの話。
今のDFだと、Ctrl+Wで検索して、コピーするとディレクトリ構成ごとコピーしてしまうので良くない。コレはコレで使い勝手がいいのだけど。
サブディレクトリにあるファイルをまとめて同じ場所にコピーするオプションを追加。
もともとは各所に分散している.objとかを消せればいい、開ければいい、ディレクトリ構成ごとコピーできれば…という感じだったのだけど。
これでfoo/foo.c、bar/bar.c、baz/baz.cを*.cで検索してまとめてsrc/にコピーすることができる。今まではsrc/foo/foo.cというコピーしかできなかった。
スクロールするときの動作はさらに改善できそう。もうちょっと試行錯誤。
ファイルサイズ 89,600バイト。
右にスクロールする時の高速化に成功。左は…描画してみないとどのくらいスクロールするのかわからないのでBitBlt()できない。うーん。
ファイルサイズ 89,088バイト。
エラーが発生していないのにエラーだと誤解するバグ。
掲示板で報告されていたので調べる。私の環境ではふつーに動いていたのでまったく気付かなかった。LiteStepいれてると変になることがあるけど。
戻り値を間違えていた部分があったので修正。多分、これか?
削除したときに画面を二度続けて更新することがあったのを修正。
削除した直後に画面を更新して、その後にもう一度更新するという動作をしていたのだけど、なぜこのような動作をするのかさっぱり解っていなかった。
削除した直後にはプログラムのほうで画面の更新を行うようにしているけど、このタイミングが早すぎてディスクキャッシュの都合か何かでディレクトリ更新通知が上がってきているのだろう、という程度にしか考えていなかったので深く調べてもいなかった。実害もないし。更新しないよりマシ。
そしたらあーた、更新通知フラグが立ちっぱなしだったとかいうオチ。画面の更新を行うタイミングで更新通知フラグを降ろしておけと。
DFのソースを眺めていたらどうもバグっぽいのが。
if(OnCommand(LOWORD(wParam), lParam, pList)){
/* 更新発生 */
if(!pList->hChange){
if(WaitForSingleObject(pList->hChange, 0)==WAIT_OBJECT_0){
log_put("処理により変更あり更新");
GetFiles(pList, FALSE);
}
}else{
pList->dwOpt &= ~OPT_UPDATE;/* 更新ウェイトフラグを解除 */
pList->dwTime = GetTickCount();
}
}else{
/* 操作があったので更新待機時間を設定 */
pList->dwTime = GetTickCount()+WAIT_TIMER;
}
OnCommand()はWM_COMMANDのハンドラ。削除した時とか、ディレクトリ表示に変更がありそうな処理をした時にはOnCommand()が1を返す。
そこでGetFiles()でディレクトリ一覧を更新する。GetFiles()というネーミングはN66SR-BASICのファイル一覧を表示させるコマンド、FILESのパロディ。N88-BASICでも同じコマンド。
ディレクトリ更新通知ハンドルが取れていないときにはGetFiles()を呼び出していないような気がする。別のタイミングで呼んでいたっけ。
やっぱり呼んでない。
要はGetFiles()を呼びそこねる場合があるので、呼ぶようにすればOk。
呼び出す条件というのが
ってことは
if(OnCommand(LOWORD(wParam), lParam, pList)){
/* 更新発生 */
if(!pList->hChange || WaitForSingleObject(pList->hChange, 0)==WAIT_OBJECT_0){
log_put("処理により変更あり更新");
GetFiles(pList, FALSE);
}
}else{
/* 操作があったので更新待機時間を設定 */
pList->dwTime = GetTickCount()+WAIT_TIMER;
}
でいいのか。フラグの制御はGetFiles()でやってるし。
おっと、これだと検索モードのときに誤動作する。21日に検索モードのフラグを見ないで更新ハンドルだけを見るように変えたのだった。やっぱり検索モードのフラグを見ないとダメか。
ついでに更新を遅延させているところも確認する。この間、プログラムを起動するところを修正してエラーチェックのほうを修正し忘れたというミスをしたので、今度はちゃんと関連するところも見落とさないようにしないと。
タイマーが発動したら無条件で画面の更新を行っている。更新があったかどうか確認してからのほうが良さそうだ。
あ、この時点ではすでに更新通知がリセットされているからダメか。コレはこのままでよしと。
おおむね修正完了。
OPT_UPDATEよりOPT_DELAYの方が名前としてはいいような気がする。折りを見て変えよう。
メールはこちらCopyrigiht © 2001 びい(@nifty ID:RXA01732)