13

アプリケーションのロード中にスプラッシュ スクリーンを表示したいと考えています。ただし、一部のサードパーティ コンポーネントは、初期化中にメイン スレッドを数秒間ブロックするため、すべてのフォームが更新されません。メインスレッドがビジーなときにも更新されるように、独自のスレッドでスプラッシュ画面を表示することは可能ですか?

アプリケーションは win32 および Delphi バージョン 2007 です。

編集:「未描画のスプラッシュ スクリーン」効果を回避しようとしています。これは、(他のアプリケーションからの) 他のウィンドウがスプラッシュ スクリーンの上部にある場合に発生します。

4

6 に答える 6

9

別のスレッドでスプラッシュ画面を実行できますが、その場合は、生のWindows API呼び出し、またはVCLのようなクラスを実装するサードパーティのライブラリ(Key Objects Libraryなど)を使用する必要があります。ただし、スプラッシュスレッドからVCLにアクセスしないでください。

そのルートを使用する場合(ほとんど利益が得られないため、多くの作業が必要になるため、そうすべきではないと思います)、複数のスレッドからのWindowsAPIアクセスに関するルールを必ず守ってください。詳細については、たとえば「ユーザーインターフェイススレッド」のGoogle。

編集:

以前は気づいていませんでしたが、実際にはCodeCentralにDelphi用のスレッドスプラッシュスクリーンを実装するコンポーネントがあります。このコンポーネントを使用すると、(まだ試していませんが)実際には別のスレッドでスプラッシュ画面を表示するのは簡単かもしれませんが、セカンダリスレッドからのVCLアクセスに対する警告は残ります。

于 2008-12-23T13:27:15.587 に答える
3

最初に DPR でスプラッシュ スクリーンを作成しますが、 Application.CreateFormメソッドを使用しないでください。簡単なコードを次に示します。

begin
  Application.Initialize;
  SplashForm := TSplashForm.Create(nil);
  try
    SplashForm.FormStyle := fsStayOnTop;
    SplashForm.Show;
    Application.ProcessMessages;
    Application.CreateForm(TForm14, Form14);
    // Other Form Creation here . . . .
    Application.Run;
  finally
    if assigned(SplashForm) then
      SplashForm.Release;
  end;
end.

次に、MainFrom (この場合は Form14) の Show イベント ハンドラー (または後で - 初期化が完了したとき) に次のコードを配置します。

SplashForm.Close;
SplashForm.Release;
SplashForm := nil;

(フォームで Free の代わりに Release を呼び出し、それを nil に割り当てて、DRP が release を再度呼び出さないようにします。DRP の release は、メインフォームの作成に失敗した場合に備えています。)

スプラッシュ フォームはFormStyle := fsStayOnTopであるため、メイン スレッドがブロックされたときにペイント メッセージが表示されないことは問題になりません。次に、メイン スレッドのブロックが解除されたら、更新メッセージを送信します (プログレス バーを変更するなど)。ただし、サード パーティのコンポーネント ベンダーに連絡して、メイン スレッドのブロックを停止するように依頼する必要があるという Gamecat の意見には同意します。

または、別のスレッドでサードパーティ コンポーネントを作成することもできます (視覚的でない場合は、少し難しくなります)。

これは、Application.MainFormOnTaskBarを true に設定しても機能します。

于 2008-12-23T13:04:24.590 に答える
0

起動コードでスプラッシュを作成し、常に最上位に設定してから、適切な場所で frmSplash.Update を使用して、スプラッシュが表示され、更新されるようにします。メイン フォーム create は、それを呼び出す場所の 1 つです。

問題は、Delphi 2007 が最初のフォームがメイン フォームであると想定し、コア コードでメイン フォームを置き換える方法がないことです。おそらく、メインアプリを実行する高速で小さなスプラッシュアプ​​リを用意するという古いビジュアルベーシックソリューションの方が実際には優れているかもしれません!

于 2008-12-23T12:03:52.730 に答える
0

メイン スレッドをブロックする問題は、スプラッシュ スクリーンを別のスレッドで実行しても解決されません。これは、スクリーンの更新にメイン スレッドが必要になるためです。

スプラッシュ スクリーンが変化しない場合、これは問題ではありません。

このような長いブロックは実際の問題であるため、サードパーティのコンポーネント ベンダーに連絡する必要があるかもしれません。

于 2008-12-23T12:09:25.527 に答える
0

Jim McKeeth は素晴らしいアイデアを思いつきましたが、問題になるかもしれないし問題にならないかもしれないことについては 1 つも触れていません。初期化に時間がかかるコンポーネントについて話します。それは、初期化セクション、またはフォームの作成中など、後で発生する何かを意味しますか? DPR 内のコードが実行される前に、すべての初期化セクションが実行されるためです。その部分に時間がかかる場合は、スプラッシュ スクリーンがすべての前に表示されるようにするには、いくつかのトリッキーなことを行う必要があります。

フォームのユニットを .DPR の最上部にできるだけ近づけます。(ただし、FastMM など、最初に実行する必要があるものの前ではありません)。そのユニットの初期化セクションにスプラッシュ スクリーンを表示するコードを配置します。そして、スプラッシュ スクリーンが使用する初期化期間が長いユニットがないことを確認してください (または、スプラッシュ スクリーンを使用するユニットや、依存関係ツリーのどこにもないことを確認してください)。

ただし、初期初期化スタックが終了するまでスローダウンの問題が始まらない場合は、Jim の言ったことに従ってください。

于 2008-12-23T22:10:46.560 に答える