0

reportbuilderを使用してフォームのレポートを作成します。メインフォームで、グリッド上のいくつかのアイテムを選択してから、アイテムのレポートを生成します。Tthreadでこれを実行したいのですが、「リストインデックスが範囲外です」というエラーが発生します。

コールスタックは次のとおりです。

Classes.TList.Get(1244868)
Classes.TList.Get(???)
Forms.TScreen.GetCustomForms(???)
Forms.TApplication.DoActionIdle
Forms.TApplication.Idle(???)
Forms.TApplication.HandleMessage
Forms.TApplication.Run

一部のフォームがScreen.Formsコレクションにタイムリーに追加されていないか、DoActionIdleのループ中にフォームから解放されているようです。

この問題を回避する方法について何かアイデアはありますか?私はWindowsXPとdelphi2010で作業しています。

また、アプリケーションのテスト手順に問題があります。TForm3は、コードのない単なるフォームです。

TDebugThread = class(TThread)
protected
  procedure Execute; override;
public
  constructor Create();
end;

constructor TDebugThread.Create;
begin
   FreeOnTerminate := True;
   inherited Create(False);
end;

procedure TDebugThread.Execute;
var
  oReport:  DeBugReport.TForm3;
begin
  inherited;
  oReport:=  DeBugReport.TForm3.Create(Nil);
  try
    sleep(1000);
  finally
    oReport.Free;
  end;
end;

....
procedure RunThread();
begin
  TDebugThread.Create();
end;

要約:

フォームにいくつかの介入のリストがあります。介入の各詳細と再開は、2/5のレポートに印刷できます。したがって、別のフォーム(表示されない)でレポートコンポーネント(reportbuilder)を使用します。新機能は、リスト上のいくつかの介入を複数選択し、レポートをpdf形式のフォルダーに設定することでした。これは、各介入でレポートフォームといくつかのパラメータを呼び出して変更し、PDFに保存するだけで簡単でした。しかし、これには時間がかかります。ユーザーは、手順が終了するまで待つ必要があります。スレッドでプロシージャを設定しても問題ありません。しかし、「リストインデックスが範囲外です」というエラーが発生します。ArgggArggg、私はレポートフォーム(彼の仕事のために作成され、その後破棄された)が問題であると疑われましたが、別の解決策があることを望んでいました。TFormをTDataModuleに変更しようと考えていました。フォームのすべてのコンポーネントをデータモジュールに設定できますか?TDbGridを使用して、デザインのいくつかの値を確認します。しかし、TdatamoduleではTDBGridを設定できません。わかりました、私はTDbGridなしで生きることができます。そこで、TFormをTDataModuleに変換しました。しかし、TDataModuleは答えではありません。そこで、TBitmapから「Graphics.OutOfResource」というエラーが発生します。TBitmapはTppReportから呼び出していると思います。これで完了です。2日以上コードを変更しましたが、結果がありません。今回はTThreadを離れます。TBitmapはTppReportから呼び出していると思います。これで完了です。2日以上コードを変更しましたが、結果がありません。今回はTThreadを離れます。TBitmapはTppReportから呼び出していると思います。これで完了です。2日以上コードを変更しましたが、結果がありません。今回はTThreadを離れます。

4

1 に答える 1

2

見てみましょうTApplication.DoActionIdle

procedure TApplication.DoActionIdle;
var
  I: Integer;
begin
  for I := 0 to Screen.CustomFormCount - 1 do
    with Screen.CustomForms[I] do
      if HandleAllocated and IsWindowVisible(Handle) and
        IsWindowEnabled(Handle) then
        UpdateActions;
end;

Screen.CustomFormCountと が正しく実装されており、 によってインデックス付けされたアイテムの数を常に返すと仮定しましょうScreen.CustomForms。その場合、結論は、ループの本体がフォームを削除していることです。つまりScreen.CustomFormCount、ループの実行中に変化しています。

これが発生する唯一の方法は、フォームのアクション更新ハンドラーの 1 つによってフォームが削除された場合です。ですから、それ以上のことは言えませんが、この分析によって問題の根本原因が明らかになるはずです。


質問の 2 番目の部分は非常に単純です。メイン GUI スレッドの外部で VCL コンポーネントを使用することはできません。

実際、スレッドで VCL フォームを破棄するとScreen.CustomFormCount、 の GUI スレッドでの実行中に変更が生じる可能性がありTApplication.DoActionIdleます。

于 2013-03-19T13:31:30.817 に答える