Utskrift från skrivbordsprogramvara

I det här avsnittet beskrivs hur du skriver ut från ett internt Windows-skrivbordsprogram.

Överblick

För att ge den bästa användarupplevelsen när du skriver ut från ett internt Windows-program måste programmet vara utformat för att skriva ut från en dedikerad tråd. I ett internt Windows-program ansvarar programmet för att hantera händelser och meddelanden i användargränssnittet. Utskriftsåtgärder kan kräva perioder av intensiv beräkning eftersom programinnehållet återges för skrivaren, vilket kan hindra programmet från att svara på användarinteraktion om bearbetningen utförs i samma tråd som händelsebearbetningen av användarinteraktionen.

Om du redan är bekant med hur du skriver ett inbyggt Windows-program med flera trådar går du direkt till Så här skriver du ut från ett Windows-program och lär dig hur du lägger till utskriftsfunktioner i ditt program.

Grundläggande krav för Windows-program

För bästa prestanda och programrespons ska du inte utföra ett programs utskriftsjobbsbearbetning i tråden som bearbetar användarinteraktion.

Den här separationen av utskrifter från användarinteraktion påverkar hur programmet hanterar programdata. Du bör fullt förstå dessa konsekvenser innan du börjar skriva ansökan. Följande avsnitt beskriver de grundläggande kraven för att hantera utskrifter i en separat tråd i ett program.

Grunderna i Windows-program

Ett internt Windows-program måste ange huvudfönsterproceduren för att bearbeta de fönstermeddelanden som det tar emot från operativsystemet. Varje fönster i ett Windows-program har en motsvarande WndProc- funktion som bearbetar dessa fönstermeddelanden. Tråden där denna funktion körs kallas användargränssnittstråden.

Använd resurser för strängar.
Använd strängresurser från programmets resursfil i stället för strängkonstanter för strängar som kan behöva ändras när du stöder ett annat språk. Innan ett program kan använda en strängresurs som en sträng måste programmet hämta resursen från resursfilen och kopiera den till en lokal minnesbuffert. Detta kräver ytterligare programmering i början, men möjliggör enklare ändring, översättning och lokalisering av programmet i framtiden.
Bearbeta data i steg.
Bearbeta utskriftsjobbet i steg som kan avbrytas. Den här designen gör det möjligt för användaren att avbryta en lång bearbetningsåtgärd innan den slutförs och förhindrar att programmet blockerar andra program som kan köras samtidigt.
Använd användardata för fönstret.
Utskriftsprogram har ofta flera fönster och trådar. Om du vill hålla data tillgängliga mellan trådar och bearbetningssteg utan att använda statiska, globala variabler, refererar du till datastrukturerna med en datapekare som är en del av fönstret där de används.

I följande kodexempel visas en huvudinmatningspunkt för ett utskriftsprogram. Det här exemplet visar hur du använder strängresurser i stället för strängkonstanter och visar även huvudmeddelandeloopen som bearbetar programmets fönstermeddelanden.

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

Dokumentinformation

Inbyggda Windows-program som skriver ut bör utformas för bearbetning med flera trådar. Ett av kraven för en design med flera trådar är att skydda programmets dataelement så att de är säkra för flera trådar att använda samtidigt. Du kan skydda dataelement med hjälp av synkroniseringsobjekt och organisera data för att undvika konflikter mellan trådarna. Samtidigt måste programmet förhindra ändringar i programdata när de skrivs ut. Exempelprogrammet använder flera olika programmeringstekniker med flera trådar.

synkroniseringshändelser
Exempelprogrammet använder händelser, trådhandtag och väntefunktioner för att synkronisera bearbetningen mellan utskriftstråden och huvudprogrammet och för att indikera att data används.
Application-Specific Windows-meddelanden
Exempelprogrammet använder programspecifika fönstermeddelanden för att göra programmet mer kompatibelt med andra interna Windows-program. Genom att dela upp bearbetningen i mindre steg och köa stegen i fönstermeddelandeloopen blir det enklare för Windows att hantera bearbetningen utan att blockera andra program som också kan köras på datorn.
datastrukturer
Exempelprogrammet är inte skrivet i ett objektorienterat format med hjälp av objekt och klasser, även om det grupperar dataelement i datastrukturer. Exemplet använder inte en objektorienterad metod för att undvika att antyda att en metod är bättre eller sämre än en annan.
Du kan använda funktionerna och datastrukturerna i exempelprogrammet som utgångspunkt när du utformar programmet. Oavsett om du bestämmer dig för att utforma ett objektorienterat program eller inte är det viktigt att komma ihåg att gruppera relaterade dataelement så att du kan använda dem på ett säkert sätt i olika trådar efter behov.

Skrivarenhetskontext

När du skriver ut kanske du vill återge innehållet som ska skrivas ut till en enhetskontext. Så här hämtar du en skrivarenhetskontext beskriver de olika sätt som du kan hämta en skrivarenhetskontext på.

Skriva ut från ett Windows-program