Impression d’applications de bureau

Cette section explique comment imprimer à partir d’un programme de bureau Windows natif.

Vue d’ensemble

Pour offrir la meilleure expérience utilisateur lorsque vous imprimez à partir d’un programme Windows natif, le programme doit être conçu pour imprimer à partir d’un thread dédié. Dans un programme Windows natif, le programme est responsable de la gestion des événements et des messages de l’interface utilisateur. Les opérations d’impression peuvent nécessiter des périodes de calcul intenses à mesure que le contenu de l’application est affiché pour l’imprimante, ce qui peut empêcher le programme de répondre à l’interaction de l’utilisateur si ce traitement est effectué dans le même thread que le traitement des événements de l’interaction utilisateur.

Si vous êtes déjà familiarisé avec l’écriture d’un programme Windows natif multithread, accédez directement à Comment imprimer à partir d’une application Windows et découvrez comment ajouter des fonctionnalités d’impression à votre programme.

Configuration requise pour le programme Windows de base

Pour optimiser les performances et la réactivité du programme, n’effectuez pas le traitement du travail d’impression d’un programme dans le thread qui traite l’interaction utilisateur.

Cette séparation entre l’impression et l’interaction utilisateur influence la façon dont le programme gère les données d’application. Vous devez bien comprendre ces implications avant de commencer à écrire l’application. Les rubriques suivantes décrivent les exigences de base de la gestion de l’impression dans un thread distinct d’un programme.

Concepts de base du programme Windows

Un programme Windows natif doit fournir la procédure de fenêtre main pour traiter les messages de fenêtre qu’il reçoit du système d’exploitation. Chaque fenêtre d’un programme Windows a une fonction WndProc correspondante qui traite ces messages de fenêtre. Le thread dans lequel cette fonction s’exécute est appelé l’interface utilisateur, ou iU, thread.

Utilisez des ressources pour les chaînes.
Utilisez des ressources de chaîne du fichier de ressources du programme au lieu de constantes de chaîne pour les chaînes qui peuvent avoir besoin d’être modifiées lorsque vous prenez en charge une autre langue. Avant qu’un programme puisse utiliser une ressource de chaîne comme chaîne, le programme doit récupérer la ressource à partir du fichier de ressources et la copier dans une mémoire tampon locale. Cela nécessite une programmation supplémentaire au début, mais permet de faciliter la modification, la traduction et la localisation du programme à l’avenir.
Traitez les données par étapes.
Traitez le travail d’impression en étapes qui peuvent être interrompues. Cette conception permet à l’utilisateur d’annuler une opération de traitement longue avant qu’elle ne se termine et empêche le programme de bloquer d’autres programmes qui peuvent être en cours d’exécution en même temps.
Utilisez les données utilisateur de la fenêtre.
Les applications d’impression ont souvent plusieurs fenêtres et threads. Pour conserver les données disponibles entre les threads et les étapes de traitement sans utiliser de variables globales statiques, référencez les structures de données à l’aide d’un pointeur de données qui fait partie de la fenêtre dans laquelle elles sont utilisées.

L’exemple de code suivant montre un point d’entrée main pour une application d’impression. Cet exemple montre comment utiliser des ressources de chaîne au lieu de constantes de chaîne et montre également la boucle de message main qui traite les messages de fenêtre du programme.

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;
}

Informations sur le document

Les programmes Windows natifs qui s’impriment doivent être conçus pour le traitement multithread. L’une des exigences d’une conception multithread est de protéger les éléments de données du programme afin qu’ils soient sécurisés pour plusieurs threads à utiliser en même temps. Vous pouvez protéger les éléments de données en utilisant des objets de synchronisation et en organisant les données pour éviter les conflits entre les threads. Dans le même temps, le programme doit empêcher les modifications apportées aux données du programme pendant leur impression. L’exemple de programme utilise plusieurs techniques de programmation multithread différentes.

Événements de synchronisation
L’exemple de programme utilise des événements, des handles de thread et des fonctions d’attente pour synchroniser le traitement entre le thread d’impression et le programme main et pour indiquer que les données sont en cours d’utilisation.
Messages Windows spécifiques à l’application
L’exemple de programme utilise des messages de fenêtre spécifiques à l’application pour rendre le programme plus compatible avec d’autres programmes Windows natifs. Le fractionnement du traitement en étapes plus petites et la mise en file d’attente de ces étapes dans la boucle de message de la fenêtre permettent à Windows de gérer plus facilement le traitement sans bloquer d’autres applications qui peuvent également s’exécuter sur l’ordinateur.
Structures de données
L’exemple de programme n’est pas écrit dans un style orienté objet à l’aide d’objets et de classes, bien qu’il regroupe des éléments de données dans des structures de données. L’exemple n’utilise pas d’approche orientée objet pour éviter d’impliquer qu’une approche est meilleure ou pire qu’une autre.
Vous pouvez utiliser les fonctions et les structures de données de l’exemple de programme comme point de départ lorsque vous concevez votre programme. Que vous décidiez ou non de concevoir un programme orienté objet, la considération importante à retenir est de regrouper les éléments de données associés afin de pouvoir les utiliser en toute sécurité dans différents threads si nécessaire.

Contexte du périphérique d’imprimante

Lors de l’impression, vous souhaiterez peut-être afficher le contenu à imprimer dans un contexte d’appareil. Guide pratique pour récupérer un contexte de périphérique d’imprimante décrit les différentes façons dont vous pouvez obtenir un contexte de périphérique d’imprimante.

Comment imprimer à partir d’une application Windows