C++Builder の TProgressBar のバグを誤魔化す
2013-11-27
アプリケーションの起動に時間を要する場合は、スプラッシュスクリーンを準備します。設ける目的は、アプリケーションが起動していることをユーザーに通知することです。起動時、しばらく何も出てこなかったら、「本当に起動しようとしているの?」とユーザーが不安になってしまいますから。そのついでにシステム名称や社名をコマーシャルしたり、アプリケーションのバージョンを表示したりするわけですが、スクリーン内にプログレスバーを設けて、起動の進捗状況を報告することがあります。
で、今回 C++Builder で開発するアプリケーションに、VCL の TProgressBar
を使って実装しようと思ったのですが、TProgressBar
を Windows 7(XPの頃からかもしれないけど) で動かそうとすると、どうも更新したステップ数と、表示されているステップ数が合いません。いろいろ考えたのですが、結局解決することができず、以下のような小細工をしました。小細工の内容は、setProgressMax()
の長ったらしいコメントを参照してください。
TForm_Splash.cpp
/*!
プログレスバーの最大値設定
@param max :全ステップ数(progressUpdate()をコールする回数)
@return なし。
*/
void __fastcall TForm_Splash::setProgressMax(int max) {
/*
TProgressBarに対してStepIt()すると、遅延して描画されるためか
1ステップ遅れたり、一気に2ステップ進んだり等して、綺麗に進捗を表示できない。
ずれは1ステップ程度のため、誤魔化し処理として指定された最大値に
16を乗算し、1ステップでpositionプロパティを16進めるようにすることで、
見た目上のずれを軽減している。
また、本クラスを利用するクラスの方で、最後にApplication->ProcessMessages()をコールして
Windowsのメッセージキューを処理させないと、最終ステップが描画されない。
何故か、progressUpdate()でやってもダメで、利用元クラスでやる必要がある。訳が分からない。
そして、100%になった時に微量に100%にならないのは、どうにもならなかった。ギブアップ。
こんな小細工ばかりを組み込みたくなければ、TCGuageコンポーネントで代用できる。
しかし、ランタイムの関係かビジュアルが美しくない(Windows7っぽくない)ので今回はパスする。
*/
ProgressBar->Max = (max * 16); // 最大値を16倍にしておいて
ProgressBar->Step = 16; // 1ステップ[ 一度のStepIt() ]でPositionが16進むようにする。
ProgressBar->Position = 0;
}
/*!
ユーザー向けに表示しているメッセージを更新し、プログレスバーを1段階進める。
@param userMessage :フォームに表示するユーザー向けメッセージ
@return なし。
*/
void __fastcall TForm_Splash::progressUpdate(const UnicodeString &userMessage) {
if (!userMessage.IsEmpty()) {
Label_UserMessage->Caption = userMessage;
}
ProgressBar->StepIt();
Application->ProcessMessages();
}
利用元クラス
// スプラッシュフォームクラスに、初期化の全ステップ数を通知
Form_Splash->setProgressMax(10);
Form_Splash->progressUpdate(L"データベースへ接続中");
connectDatabase();
・
・
・
Form_Splash->progressUpdate(L"システム設定データのロード中...");
systemDataLoad();
Form_Splash->progressUpdate(L"初期化完了!!");
Application->ProcessMessages(); // 大事なおまじない。理由はTForm_Splash.cppを参照