次の方法で共有


デスクトップ アプリの印刷

このセクションでは、ネイティブ 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 つは、複数のスレッドが同時に使用できるように、プログラムのデータ要素を保護することです。 データ要素を保護するには、同期オブジェクトを使用し、スレッド間の競合を回避するためにデータを整理します。 同時に、プログラムは、印刷中のプログラム・データの変更を防ぐ必要があります。 サンプル プログラムでは、複数の異なるマルチスレッド プログラミング手法を使用します。

同期イベント
サンプル プログラムでは、イベント、スレッド ハンドル、待機関数を使用して、印刷スレッドとメイン プログラムの間で処理を同期し、データが使用中であることを示します。
Application-Specific Windows メッセージ
このサンプル プログラムでは、アプリケーション固有のウィンドウ メッセージを使用して、他のネイティブ Windows プログラムとの互換性を高めます。 処理を小さなステップに分割し、それらのステップをウィンドウ メッセージ ループにキューに入れることで、コンピューター上で実行されている可能性がある他のアプリケーションをブロックすることなく、Windows で処理を簡単に管理できるようになります。
データ構造
サンプル プログラムは、データ要素をデータ構造にグループ化しますが、オブジェクトとクラスを使用してオブジェクト指向のスタイルで記述されることはありません。 このサンプルでは、オブジェクト指向のアプローチを使用して、あるアプローチが別のアプローチよりも優れているか悪いかを示すのを避けます。
サンプル プログラムの関数とデータ構造は、プログラムを設計する際の開始点として使用できます。 オブジェクト指向プログラムを設計するかどうかに関係なく、注意すべき重要な設計上の考慮事項は、関連するデータ要素をグループ化して、必要に応じて異なるスレッドで安全に使用できるようにすることです。

プリンター デバイス コンテキスト

印刷時に、デバイス コンテキストに印刷するコンテンツをレンダリングすることが必要になる場合があります。 方法: プリンター デバイス コンテキストを取得する は、プリンター デバイス コンテキストを取得するさまざまな方法について説明します。

Windows アプリケーションから印刷する方法