2

C++ Builder XE7 VCL を使用しています。

2016 年 8 月 11 日午後 2 時 (UTC) 頃、印刷の問題についてユーザー ベースから複数の苦情を受け始めました。これらの印刷モジュールのほとんどは、何年にもわたって安定していることが証明されており、過去 24 時間以内に私のプロジェクトに更新はありませんでした。開発/テスト環境で同様の問題を再現できました。

私のプロジェクトの多くの詳細には触れずに、失敗している非常に単純な印刷プログラムを提示させてください:

void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
    // Test Print:
    TPrinter *Prntr = Printer();
    Prntr->Title = "Test_";
    Prntr->BeginDoc();
    Prntr->Canvas->Font->Size = 10;
    Prntr->Canvas->TextOut(300,1050,"* * * Printing Test * * *");
    if (Prntr->Printing) {
        Prntr->EndDoc();
    }
}

最初に印刷しようとすると、すべてが期待どおりに完全に機能します。ボタンをもう一度クリックTPrinterすると、小さな PDF が生成されますが、実際には PDF ファイルが破損しており、ファイル ハンドルが貼り付いているように見えます。

ボタンを 3 回クリックすると、印刷されず、次のエラー メッセージが表示されます。

Printer is not currently printing.

私自身のテストは PDF プリンター ドライバーを使用して行われましたが、ユーザーから受け取った苦情には、さまざまなローカル プリンター、ネットワーク プリンター、PDF プリンターなどがあります。

私の実際のプロジェクトでは、try/catch例外処理を行っているため、実際の結果はわずかに異なりますが、この結果とほぼ同じです。結果は、不安定性やメモリ リークの特徴を示していますが、エラー メッセージはほとんどありません。

Embarcadero DLL と絡み合っている Microsoft Windows の更新がいくつかあったのではないかと思いますが、これまでのところ確認できていません。

他の誰かが同様の問題を抱えていますか?

4

7 に答える 7

4

TPrintDialogまたはTPrinterSetupDialog"works" を使用してエラーを修正する理由は、シングルトンTPrinterオブジェクト (Vcl.Printers.Printer()関数によって返される) が現在のハンドルをプリンターに解放することを強制するためです。その結果TPrinter.BeginDoc()、新しいハンドルが作成されます。 TPrinter次の場合にプリンター ハンドルを解放します。

  • それは破壊されています。
  • そのNumCopiesOrientation、またはPrinterIndexプロパティが設定されています。
  • そのSetPrinter()メソッドが呼び出されます (内部的にPrinterIndexプロパティ セッターとSetToDefaultPrinter()メソッドによって、および と によってTPrintDialog) TPrinterSetupDialog

そうしないと、複数回呼び出すとTPrinter.BeginDoc()、同じプリンターハンドルを再利用し続けるだけです。また、最近の Microsoft のセキュリティ アップデートがハンドルの再利用に影響を与えているようです。

つまり、(Microsoft の更新プログラムをアンインストールせずに) への呼び出しの合間に、プリンター ハンドルを解放して再作成する何かBeginDoc()行う必要があります。その後、問題は解決するはずです。少なくとも、Embarcadero がこの問題に対処するためのパッチをリリースできるまでは。おそらく、現在のプリンター ハンドルを更新または解放することができます (現在はしていません)。TPrinterTPrinterTPrinter.EndDoc()TPrinter.Refresh()

したがって、次の回避策により、ユーザー インターフェイスを変更することなく印刷の問題を解決できます。

void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
    // Test Print:
    TPrinter *Prntr = Printer();
    Prntr->Title = "Test_";
    Prntr->Copies = 1;  // Here is the workaround
    Prntr->BeginDoc();
    if (Prntr->Printing) {
        Prntr->Canvas->Font->Size = 10;
        Prntr->Canvas->TextOut(300,1050,"* * * Printing Test * * *");
        Prntr->EndDoc();
    }
}
于 2016-08-18T02:35:06.827 に答える
1

今日もここで始まりました。私の Windows 10 セットアップでは、これは TForm の Print() を 3 回呼び出した後に発生します。Microsoft Print to PDF と Microsoft XPS Document Writer の両方を試しましたが、どちらも同じエラーが発生しました。

簡単なデバッグを行ったところ、値 <= 0 を返すのは StartDoc() の呼び出しであることがわかりました。

これを実際に引き起こしている原因を突き止めるまでの一時的な修正は、呼び出してプリンターでプリンターオブジェクトを再作成することです

Vcl.Printers.SetPrinter(TPrinter.Create).Free;

Printer オブジェクトを使用している何かを呼び出した後。それを行うことはお勧めできないかもしれませんが、今のところ私の問題は解決しました。

EndDoc() を呼び出すときに、何かが正しく解放されていないようです

于 2016-08-11T22:46:48.683 に答える
0

Windows 10 64 ビット システムで XE7 でビルドされた 32 ビット Delphi アプリケーションを実行しているときに、ほぼ同時に同じ奇妙な動作を経験し始めました。

Windows 10 の最新のセキュリティ アップグレード (KB3176493) をアンインストールすると、これらのアプリケーションからの印刷が正常に機能するようになります。

この更新プログラムをアンインストールすると、ファイルの関連付け (特定のファイルの種類を処理するための既定のプログラム) が Microsoft Windows の既定値に戻されるという、かなり驚くべき副作用があるようです...

于 2016-08-12T11:20:50.730 に答える