デスクトップ アプリの印刷
このセクションでは、ネイティブ Windows デスクトップ プログラムから印刷する方法について説明します。
概要
ネイティブ Windows プログラムから印刷するときに最適なユーザー エクスペリエンスを提供するには、専用スレッドから印刷するようにプログラムを設計する必要があります。 ネイティブ Windows プログラムでは、プログラムはユーザー インターフェイスのイベントとメッセージを管理する役割を担います。 印刷操作では、プリンターに対してアプリケーション コンテンツがレンダリングされるため、一定の計算期間が必要になります。これにより、ユーザー操作のイベント処理と同じスレッドでこの処理が実行されると、プログラムがユーザーの操作に応答できなくなる可能性があります。
マルチスレッド ネイティブ Windows プログラムの作成方法を既に理解している場合は、「 Windows アプリケーションから印刷する方法」に 直接移動し、プログラムに印刷機能を追加する方法について説明します。
Windows プログラムの基本的な要件
パフォーマンスとプログラムの応答性を最大限に高めるには、ユーザーの操作を処理するスレッドでプログラムの印刷ジョブ処理を実行しないでください。
このユーザー操作からの印刷の分離は、プログラムがアプリケーション データを管理する方法に影響します。 アプリケーションの作成を開始する前に、これらの影響を十分に理解しておく必要があります。 次のトピックでは、プログラムの別のスレッドで印刷を処理するための基本的な要件について説明します。
Windows プログラムの基本
ネイティブ Windows プログラムは、オペレーティング システムから受信したウィンドウ メッセージを処理するために、メイン ウィンドウ プロシージャを提供する必要があります。 Windows プログラムのすべてのウィンドウには、これらのウィンドウ メッセージを処理する対応する WndProc 関数があります。 この関数が実行されるスレッドは、ユーザー インターフェイス (UI) スレッドと呼ばれます。
文字列にはリソースを使用します。
別の言語をサポートする場合に変更が必要になる可能性がある文字列には、文字列定数ではなく、プログラムのリソース ファイルの文字列リソースを使用します。 プログラムで文字列リソースを文字列として使用するには、リソース ファイルからリソースを取得し、ローカル メモリ バッファーにコピーする必要があります。 これには、最初にいくつかの追加のプログラミングが必要ですが、将来、プログラムの変更、翻訳、ローカライズを簡単に行うことができます。
ステップでデータを処理します。
中断できるステップで印刷ジョブを処理します。 この設計により、ユーザーは完了する前に長い処理操作を取り消し、同時に実行されている可能性のある他のプログラムがプログラムでブロックされないようにすることができます。
ウィンドウ ユーザー データを使用します。
印刷アプリケーションには、多くの場合、複数のウィンドウとスレッドがあります。 静的なグローバル変数を使用せずにスレッドと処理ステップの間でデータを使用できるようにするには、使用されるウィンドウの一部であるデータ ポインターによってデータ構造を参照します。
次のコード例は、印刷アプリケーションのメインエントリ ポイントを示しています。 この例では、文字列定数の代わりに文字列リソースを使用する方法と、プログラムのウィンドウ メッセージを処理するメインメッセージ ループも示します。
int APIENTRY
wWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow
)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;
HRESULT hr = S_OK;
// Register the main window class name
WCHAR szWindowClass[MAXIMUM_RESOURCE_STRING_LENGTH];
LoadString(
hInstance,
IDC_PRINTSAMPLE,
szWindowClass,
MAXIMUM_RESOURCE_STRING_LENGTH);
MyRegisterClass(hInstance, szWindowClass);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
// Unable to initialize this instance of the application
// so display error message and exit
MessageBoxWithResourceString (
hInstance,
GetDesktopWindow(),
IDS_ERROR_INSTINITFAIL,
IDS_CAPTION_ERROR,
(MB_OK | MB_ICONEXCLAMATION));
return FALSE;
}
// Init COM for printing interfaces
if (FAILED(hr = CoInitializeEx(0, COINIT_MULTITHREADED)))
{
// Unable to initialize COM
// so display error message and exit
MessageBoxWithResourceString (
hInstance,
GetDesktopWindow(),
IDS_ERROR_COMINITFAIL,
IDS_CAPTION_ERROR,
(MB_OK | MB_ICONEXCLAMATION));
return FALSE;
}
hAccelTable = LoadAccelerators(
hInstance,
MAKEINTRESOURCE(IDC_PRINTSAMPLE));
// Main message handling loop
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Uninitialize (close) the COM interface
CoUninitialize();
return (int) msg.wParam;
}
ドキュメント情報
印刷するネイティブ Windows プログラムは、マルチスレッド処理用に設計する必要があります。 マルチスレッド設計の要件の 1 つは、プログラムのデータ要素を保護して、複数のスレッドが同時に使用できるようにすることです。 同期オブジェクトを使用し、スレッド間の競合を回避するためにデータを整理することで、データ要素を保護できます。 同時に、プログラムは印刷中にプログラム・データの変更を防ぐ必要があります。 サンプル プログラムでは、いくつかの異なるマルチスレッド プログラミング手法を使用します。
同期イベント
サンプル プログラムでは、イベント、スレッド ハンドル、待機関数を使用して、印刷スレッドとメイン プログラムの間で処理を同期し、データが使用中であることを示します。
アプリケーション固有の Windows メッセージ
サンプル プログラムでは、アプリケーション固有のウィンドウ メッセージを使用して、他のネイティブ Windows プログラムとの互換性を高めます。 処理を小さなステップに分割し、ウィンドウ メッセージ ループでそれらのステップをキューに入れることで、コンピューター上で実行されている可能性がある他のアプリケーションをブロックすることなく、Windows で処理を簡単に管理できます。
データ構造
サンプル プログラムは、データ要素をデータ構造にグループ化しますが、オブジェクトとクラスを使用してオブジェクト指向のスタイルで書き込まれません。 このサンプルでは、オブジェクト指向のアプローチを使用して、あるアプローチが別のアプローチよりも優れているか悪いかを暗示しないようにします。
サンプル プログラムの関数とデータ構造は、プログラムを設計する際の出発点として使用できます。 オブジェクト指向プログラムを設計するかどうかに関係なく、覚えておくべき重要な設計上の考慮事項は、関連するデータ要素をグループ化して、必要に応じて異なるスレッドで安全に使用できるようにすることです。
プリンター デバイス コンテキスト
印刷時に、デバイス コンテキストに印刷するコンテンツをレンダリングする必要がある場合があります。 方法: プリンター デバイス コンテキストを取得するプリンター デバイス コンテキスト を取得するさまざまな方法について説明します。
関連トピック